Uprev webrtc-apm to upstream WebRTC M89

This change is created by:
1. ./script/sync-apm.sh <webrtc branch-heads/4389> .
with head commit https://webrtc-review.googlesource.com/c/src/+/205280
2. Modify modules.mk files until everything compiles
3. Re-apply commit 1a11b8a webrtc-apm: Replace deprected Json::Reader call.

BUG=b:175761810
TEST=emerge webrtc-apm and deploy
Execute 'cras_test_client -C /dev/null --effects aec' to verify
on octopus

Change-Id: Ia213c55ab76b9bbaa2e9bdf9ff343f114d6e6ba0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/webrtc-apm/+/2671443
Reviewed-by: Hsinyu Chao <hychao@chromium.org>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Commit-Queue: Hsinyu Chao <hychao@chromium.org>
diff --git a/Makefile b/Makefile
index 8771078..cc2df0e 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,7 @@
 
 libwebrtc_apm_CXX_OBJECTS = \
 	libaudio_processing \
+	rnn_vad \
 	rtc_base/librtc_base \
 	common_audio/libcommon_audio \
 	system_wrappers/source/libsystem_wrappers \
@@ -35,6 +36,7 @@
 
 ifeq (${USE_SSE2},1)
 libwebrtc_apm_CXX_OBJECTS += \
+	rnn_vad_avx2 \
 	common_audio_avx2 \
 	aec3_avx2
 endif
@@ -52,6 +54,7 @@
 	common_audio/libcommon_audio.pic.a \
 	system_wrappers/source/libsystem_wrappers.pic.a \
 	modules/audio_coding/libaudio_coding.pic.a \
+	rnn_vad.pic.a \
 	rtc_base/librtc_base.pic.a \
 	libaudioproc_debug_proto.pic.a \
 	absl.pic.a \
@@ -62,7 +65,8 @@
 ifeq (${USE_SSE2},1)
 CXX_LIBRARY(libwebrtc_apm.so): LDLIBS += \
 	aec3_avx2.pic.a \
-	common_audio_avx2.pic.a
+	common_audio_avx2.pic.a \
+	rnn_vad_avx2.pic.a
 endif
 
 all: CXX_LIBRARY(libwebrtc_apm.so)
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index 0b772df..6da20c4 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -12,19 +12,16 @@
 # 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.
-#
-
-load(
-    ":compiler_config_setting.bzl",
-    "create_llvm_config",
-)
 
 package(default_visibility = ["//visibility:public"])
 
 licenses(["notice"])
 
-create_llvm_config(
-    name = "llvm_compiler",
+config_setting(
+    name = "clang_compiler",
+    flag_values = {
+        "@bazel_tools//tools/cpp:compiler": "clang",
+    },
     visibility = [":__subpackages__"],
 )
 
diff --git a/absl/abseil.podspec.gen.py b/absl/abseil.podspec.gen.py
index 6aefb79..6375298 100755
--- a/absl/abseil.podspec.gen.py
+++ b/absl/abseil.podspec.gen.py
@@ -40,8 +40,8 @@
     'USE_HEADERMAP' => 'NO',
     'ALWAYS_SEARCH_USER_PATHS' => 'NO',
   }
-  s.ios.deployment_target = '7.0'
-  s.osx.deployment_target = '10.9'
+  s.ios.deployment_target = '9.0'
+  s.osx.deployment_target = '10.10'
   s.tvos.deployment_target = '9.0'
   s.watchos.deployment_target = '2.0'
 """
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 229cd71..a3002b7 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "algorithm",
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 2457d78..6398438 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -90,10 +90,10 @@
 // lookup of std::begin and std::end, i.e.
 //   using std::begin;
 //   using std::end;
-//   std::foo(begin(c), end(c);
+//   std::foo(begin(c), end(c));
 // becomes
 //   std::foo(container_algorithm_internal::begin(c),
-//   container_algorithm_internal::end(c));
+//            container_algorithm_internal::end(c));
 // These are meant for internal use only.
 
 template <typename C>
@@ -188,7 +188,7 @@
 // c_none_of()
 //
 // Container-based version of the <algorithm> `std::none_of()` function to
-// test if no elements in a container fulfil a condition.
+// test if no elements in a container fulfill a condition.
 template <typename C, typename Pred>
 bool c_none_of(const C& c, Pred&& pred) {
   return std::none_of(container_algorithm_internal::c_begin(c),
@@ -340,24 +340,45 @@
 // c_mismatch()
 //
 // Container-based version of the <algorithm> `std::mismatch()` function to
-// return the first element where two ordered containers differ.
+// return the first element where two ordered containers differ. Applies `==` to
+// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIterPairType<C1, C2>
 c_mismatch(C1& c1, C2& c2) {
-  return std::mismatch(container_algorithm_internal::c_begin(c1),
-                       container_algorithm_internal::c_end(c1),
-                       container_algorithm_internal::c_begin(c2));
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    // Negates equality because Cpp17EqualityComparable doesn't require clients
+    // to overload both `operator==` and `operator!=`.
+    if (!(*first1 == *first2)) {
+      break;
+    }
+  }
+
+  return std::make_pair(first1, first2);
 }
 
 // Overload of c_mismatch() for using a predicate evaluation other than `==` as
-// the function's test condition.
+// the function's test condition. Applies `pred`to the first N elements of `c1`
+// and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2, typename BinaryPredicate>
 container_algorithm_internal::ContainerIterPairType<C1, C2>
-c_mismatch(C1& c1, C2& c2, BinaryPredicate&& pred) {
-  return std::mismatch(container_algorithm_internal::c_begin(c1),
-                       container_algorithm_internal::c_end(c1),
-                       container_algorithm_internal::c_begin(c2),
-                       std::forward<BinaryPredicate>(pred));
+c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    if (!pred(*first1, *first2)) {
+      break;
+    }
+  }
+
+  return std::make_pair(first1, first2);
 }
 
 // c_equal()
@@ -539,12 +560,20 @@
 // c_swap_ranges()
 //
 // Container-based version of the <algorithm> `std::swap_ranges()` function to
-// swap a container's elements with another container's elements.
+// swap a container's elements with another container's elements. Swaps the
+// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
-  return std::swap_ranges(container_algorithm_internal::c_begin(c1),
-                          container_algorithm_internal::c_end(c1),
-                          container_algorithm_internal::c_begin(c2));
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  using std::swap;
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    swap(*first1, *first2);
+  }
+  return first2;
 }
 
 // c_transform()
@@ -562,16 +591,23 @@
 }
 
 // Overload of c_transform() for performing a transformation using a binary
-// predicate.
+// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
+// where N = min(size(c1), size(c2)).
 template <typename InputSequence1, typename InputSequence2,
           typename OutputIterator, typename BinaryOp>
 OutputIterator c_transform(const InputSequence1& input1,
                            const InputSequence2& input2, OutputIterator output,
                            BinaryOp&& binary_op) {
-  return std::transform(container_algorithm_internal::c_begin(input1),
-                        container_algorithm_internal::c_end(input1),
-                        container_algorithm_internal::c_begin(input2), output,
-                        std::forward<BinaryOp>(binary_op));
+  auto first1 = container_algorithm_internal::c_begin(input1);
+  auto last1 = container_algorithm_internal::c_end(input1);
+  auto first2 = container_algorithm_internal::c_begin(input2);
+  auto last2 = container_algorithm_internal::c_end(input2);
+  for (; first1 != last1 && first2 != last2;
+       ++first1, (void)++first2, ++output) {
+    *output = binary_op(*first1, *first2);
+  }
+
+  return output;
 }
 
 // c_replace()
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 0a4abe9..605afc8 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -57,9 +57,7 @@
 };
 
 struct AccumulateCalls {
-  void operator()(int value) {
-    calls.push_back(value);
-  }
+  void operator()(int value) { calls.push_back(value); }
   std::vector<int> calls;
 };
 
@@ -68,7 +66,6 @@
 bool Equals(int v1, int v2) { return v1 == v2; }
 bool IsOdd(int x) { return x % 2 != 0; }
 
-
 TEST_F(NonMutatingTest, Distance) {
   EXPECT_EQ(container_.size(), absl::c_distance(container_));
   EXPECT_EQ(sequence_.size(), absl::c_distance(sequence_));
@@ -151,13 +148,90 @@
 }
 
 TEST_F(NonMutatingTest, Mismatch) {
-  absl::c_mismatch(container_, sequence_);
-  absl::c_mismatch(sequence_, container_);
+  // Testing necessary as absl::c_mismatch executes logic.
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, vector_.end());
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, vector_.end());
+  }
+
+  sequence_.back() = 5;
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, std::prev(vector_.end()));
+    EXPECT_EQ(result.second, std::prev(sequence_.end()));
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, std::prev(sequence_.end()));
+    EXPECT_EQ(result.second, std::prev(vector_.end()));
+  }
+
+  sequence_.pop_back();
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, std::prev(vector_.end()));
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, std::prev(vector_.end()));
+  }
+  {
+    struct NoNotEquals {
+      constexpr bool operator==(NoNotEquals) const { return true; }
+      constexpr bool operator!=(NoNotEquals) const = delete;
+    };
+    std::vector<NoNotEquals> first;
+    std::list<NoNotEquals> second;
+
+    // Check this still compiles.
+    absl::c_mismatch(first, second);
+  }
 }
 
 TEST_F(NonMutatingTest, MismatchWithPredicate) {
-  absl::c_mismatch(container_, sequence_, BinPredicate);
-  absl::c_mismatch(sequence_, container_, BinPredicate);
+  // Testing necessary as absl::c_mismatch executes logic.
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.begin());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, sequence_.begin());
+    EXPECT_EQ(result.second, vector_.begin());
+  }
+
+  sequence_.front() = 0;
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.begin());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, std::next(sequence_.begin()));
+    EXPECT_EQ(result.second, std::next(vector_.begin()));
+  }
+
+  sequence_.clear();
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, vector_.begin());
+  }
 }
 
 TEST_F(NonMutatingTest, Equal) {
@@ -519,11 +593,9 @@
 TEST_F(SortingTest, NthElement) {
   std::vector<int> unsorted = {2, 4, 1, 3};
   absl::c_nth_element(unsorted, unsorted.begin() + 2);
-  EXPECT_THAT(unsorted,
-              ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
+  EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
   absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>());
-  EXPECT_THAT(unsorted,
-              ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
+  EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
 }
 
 TEST(MutatingTest, IsPartitioned) {
@@ -676,6 +748,15 @@
   absl::c_swap_ranges(odds, evens);
   EXPECT_THAT(odds, ElementsAre(1, 3, 5));
   EXPECT_THAT(evens, ElementsAre(2, 4, 6));
+
+  odds.pop_back();
+  absl::c_swap_ranges(odds, evens);
+  EXPECT_THAT(odds, ElementsAre(2, 4));
+  EXPECT_THAT(evens, ElementsAre(1, 3, 6));
+
+  absl::c_swap_ranges(evens, odds);
+  EXPECT_THAT(odds, ElementsAre(1, 3));
+  EXPECT_THAT(evens, ElementsAre(2, 4, 6));
 }
 
 TEST_F(NonMutatingTest, Transform) {
@@ -690,6 +771,20 @@
   EXPECT_EQ(std::vector<int>({1, 5, 4}), z);
   *end = 7;
   EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);
+
+  z.clear();
+  y.pop_back();
+  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+  EXPECT_EQ(std::vector<int>({1, 5}), z);
+  *end = 7;
+  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
+
+  z.clear();
+  std::swap(x, y);
+  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+  EXPECT_EQ(std::vector<int>({1, 5}), z);
+  *end = 7;
+  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
 }
 
 TEST(MutatingTest, Replace) {
@@ -755,10 +850,9 @@
 TEST(MutatingTest, StableSort) {
   std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};
   absl::c_stable_sort(test_vector);
-  EXPECT_THAT(
-      test_vector,
-      ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
-                  IsElement(2, 0), IsElement(2, 2)));
+  EXPECT_THAT(test_vector,
+              ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
+                          IsElement(2, 0), IsElement(2, 2)));
 }
 
 TEST(MutatingTest, StableSortWithPredicate) {
@@ -766,10 +860,9 @@
   absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) {
     return e2 < e1;
   });
-  EXPECT_THAT(
-      test_vector,
-      ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
-                  IsElement(1, 1), IsElement(1, 0)));
+  EXPECT_THAT(test_vector,
+              ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
+                          IsElement(1, 1), IsElement(1, 0)));
 }
 
 TEST(MutatingTest, ReplaceCopyIf) {
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 2c4887b..9d96abe 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "atomic_hook",
diff --git a/absl/base/BUILD.gn b/absl/base/BUILD.gn
index 16a6387..346a47d 100644
--- a/absl/base/BUILD.gn
+++ b/absl/base/BUILD.gn
@@ -6,7 +6,7 @@
 
 absl_source_set("atomic_hook") {
   public = [ "internal/atomic_hook.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -15,14 +15,14 @@
 
 absl_source_set("errno_saver") {
   public = [ "internal/errno_saver.h" ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
 }
 
 absl_source_set("log_severity") {
   sources = [ "log_severity.cc" ]
   public = [ "log_severity.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -31,7 +31,7 @@
 absl_source_set("raw_logging_internal") {
   sources = [ "internal/raw_logging.cc" ]
   public = [ "internal/raw_logging.h" ]
-  deps = [
+  public_deps = [
     ":atomic_hook",
     ":config",
     ":core_headers",
@@ -86,7 +86,7 @@
     "port.h",
     "thread_annotations.h",
   ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
 }
 
 absl_source_set("malloc_internal") {
@@ -95,7 +95,7 @@
     "internal/direct_mmap.h",
     "internal/low_level_alloc.h",
   ]
-  deps = [
+  public_deps = [
     ":base",
     ":base_internal",
     ":config",
@@ -113,7 +113,7 @@
     "internal/invoke.h",
     "internal/scheduling_mode.h",
   ]
-  deps = [
+  public_deps = [
     ":config",
     "//third_party/abseil-cpp/absl/meta:type_traits",
   ]
@@ -144,7 +144,7 @@
   # TODO(mbonadei): The bazel file has:
   #   "-DEFAULTLIB:advapi32.lib"
   # understand if this is needed here as well.
-  deps = [
+  public_deps = [
     ":atomic_hook",
     ":base_internal",
     ":config",
@@ -160,7 +160,7 @@
 absl_source_set("throw_delegate") {
   sources = [ "internal/throw_delegate.cc" ]
   public = [ "internal/throw_delegate.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":raw_logging_internal",
   ]
@@ -170,7 +170,7 @@
 absl_source_set("exception_testing") {
   testonly = true
   public = [ "internal/exception_testing.h" ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
 }
 
@@ -224,7 +224,7 @@
     "internal/endian.h",
     "internal/unaligned_access.h",
   ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -232,7 +232,7 @@
 
 absl_source_set("bits") {
   public = [ "internal/bits.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -242,7 +242,7 @@
 absl_source_set("exponential_biased") {
   sources = [ "internal/exponential_biased.cc" ]
   public = [ "internal/exponential_biased.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -252,7 +252,7 @@
 absl_source_set("periodic_sampler") {
   sources = [ "internal/periodic_sampler.cc" ]
   public = [ "internal/periodic_sampler.h" ]
-  deps = [
+  public_deps = [
     ":core_headers",
     ":exponential_biased",
   ]
@@ -262,8 +262,10 @@
   testonly = true
   public = [ "internal/scoped_set_env.h" ]
   sources = [ "internal/scoped_set_env.cc" ]
-  deps = [
+  public_deps = [
     ":config",
+  ]
+  deps = [
     ":raw_logging_internal",
   ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
@@ -272,8 +274,10 @@
 absl_source_set("strerror") {
   sources = [ "internal/strerror.cc" ]
   public = [ "internal/strerror.h" ]
-  deps = [
+  public_deps = [
     ":config",
+  ]
+  deps = [
     ":core_headers",
     ":errno_saver",
   ]
@@ -282,7 +286,7 @@
 
 absl_source_set("fast_type_id") {
   public = [ "internal/fast_type_id.h" ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
 }
 
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 046fbea..f1d3cfe 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -607,6 +607,7 @@
 // When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
 // has no effect on diagnostics. In any case this macro has no effect on runtime
 // behavior and performance of code.
+
 #ifdef ABSL_FALLTHROUGH_INTENDED
 #error "ABSL_FALLTHROUGH_INTENDED should not be defined."
 #endif
diff --git a/absl/base/casts.h b/absl/base/casts.h
index 322cc1d..83c6912 100644
--- a/absl/base/casts.h
+++ b/absl/base/casts.h
@@ -159,16 +159,19 @@
   return dest;
 }
 
-// NOTE: This overload is only picked if the requirements of bit_cast are not
-// met. It is therefore UB, but is provided temporarily as previous versions of
-// this function template were unchecked. Do not use this in new code.
+// NOTE: This overload is only picked if the requirements of bit_cast are
+// not met. It is therefore UB, but is provided temporarily as previous
+// versions of this function template were unchecked. Do not use this in
+// new code.
 template <
     typename Dest, typename Source,
     typename std::enable_if<
-        !internal_casts::is_bitcastable<Dest, Source>::value, int>::type = 0>
+        !internal_casts::is_bitcastable<Dest, Source>::value,
+        int>::type = 0>
 ABSL_DEPRECATED(
-    "absl::bit_cast type requirements were violated. Update the types being "
-    "used such that they are the same size and are both TriviallyCopyable.")
+    "absl::bit_cast type requirements were violated. Update the types "
+    "being used such that they are the same size and are both "
+    "TriviallyCopyable.")
 inline Dest bit_cast(const Source& source) {
   static_assert(sizeof(Dest) == sizeof(Source),
                 "Source and destination types should have equal sizes.");
diff --git a/absl/base/config.h b/absl/base/config.h
index b1e095d..3f7f32b 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -364,7 +364,7 @@
 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||   \
     defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
     defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
-    defined(__ASYLO__)
+    defined(__ASYLO__) || defined(__myriad2__)
 #define ABSL_HAVE_MMAP 1
 #endif
 
@@ -474,9 +474,9 @@
   (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
    __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
   (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
-   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
   (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
-   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000))
+   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
 #else
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 1911272..94488ac 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -80,12 +80,9 @@
 #define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
 #if !defined(SWIG)
 #define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
-#else
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
 #endif
 #else
 #define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
 #endif
 
 // Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
@@ -268,19 +265,19 @@
 // -------------------------------------------------------------------------
 // Define IGNORE_READS_BEGIN/_END attributes.
 
-#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 #define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
   __attribute((exclusive_lock_function("*")))
 #define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
   __attribute((unlock_function("*")))
 
-#else  // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
+#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 #define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty
 #define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty
 
-#endif  // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
+#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 // -------------------------------------------------------------------------
 // Define IGNORE_READS_BEGIN/_END annotations.
diff --git a/absl/base/internal/exponential_biased_test.cc b/absl/base/internal/exponential_biased_test.cc
index 90a482d..075583c 100644
--- a/absl/base/internal/exponential_biased_test.cc
+++ b/absl/base/internal/exponential_biased_test.cc
@@ -185,7 +185,7 @@
   ABSL_CONST_INIT static ExponentialBiased eb_static;
   EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
 
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   thread_local ExponentialBiased eb_thread;
   EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
 #endif
diff --git a/absl/base/internal/strerror.cc b/absl/base/internal/strerror.cc
index af18151..d66ba12 100644
--- a/absl/base/internal/strerror.cc
+++ b/absl/base/internal/strerror.cc
@@ -14,6 +14,7 @@
 
 #include "absl/base/internal/strerror.h"
 
+#include <array>
 #include <cerrno>
 #include <cstddef>
 #include <cstdio>
@@ -21,13 +22,13 @@
 #include <string>
 #include <type_traits>
 
-#include "absl/base/attributes.h"
 #include "absl/base/internal/errno_saver.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 namespace {
+
 const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
 #if defined(_WIN32)
   int rc = strerror_s(buf, buflen, errnum);
@@ -35,15 +36,6 @@
   if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
   return buf;
 #else
-#if defined(__GLIBC__) || defined(__APPLE__)
-  // Use the BSD sys_errlist API provided by GNU glibc and others to
-  // avoid any need to copy the message into the local buffer first.
-  if (0 <= errnum && errnum < sys_nerr) {
-    if (const char* p = sys_errlist[errnum]) {
-      return p;
-    }
-  }
-#endif
   // The type of `ret` is platform-specific; both of these branches must compile
   // either way but only one will execute on any given platform:
   auto ret = strerror_r(errnum, buf, buflen);
@@ -57,9 +49,8 @@
   }
 #endif
 }
-}  // namespace
 
-std::string StrError(int errnum) {
+std::string StrErrorInternal(int errnum) {
   absl::base_internal::ErrnoSaver errno_saver;
   char buf[100];
   const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
@@ -70,6 +61,28 @@
   return str;
 }
 
+// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
+// to `StrErrorAdaptor()` if the value is larger than this.
+constexpr int kSysNerr = 135;
+
+std::array<std::string, kSysNerr>* NewStrErrorTable() {
+  auto* table = new std::array<std::string, kSysNerr>;
+  for (int i = 0; i < static_cast<int>(table->size()); ++i) {
+    (*table)[i] = StrErrorInternal(i);
+  }
+  return table;
+}
+
+}  // namespace
+
+std::string StrError(int errnum) {
+  static const auto* table = NewStrErrorTable();
+  if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
+    return (*table)[errnum];
+  }
+  return StrErrorInternal(errnum);
+}
+
 }  // namespace base_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/strerror_benchmark.cc b/absl/base/internal/strerror_benchmark.cc
index d8ca86b..c9ab14a 100644
--- a/absl/base/internal/strerror_benchmark.cc
+++ b/absl/base/internal/strerror_benchmark.cc
@@ -20,15 +20,6 @@
 #include "benchmark/benchmark.h"
 
 namespace {
-#if defined(__GLIBC__) || defined(__APPLE__)
-void BM_SysErrList(benchmark::State& state) {
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::string(sys_errlist[ERANGE]));
-  }
-}
-BENCHMARK(BM_SysErrList);
-#endif
-
 void BM_AbslStrError(benchmark::State& state) {
   for (auto _ : state) {
     benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index 349d926..4a3b205 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -426,7 +426,7 @@
 // userspace construct) to avoid unnecessary system calls. Without this caching,
 // it can take roughly 98ns, while it takes roughly 1ns with this caching.
 pid_t GetCachedTID() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   static thread_local pid_t thread_id = GetTID();
   return thread_id;
 #else
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index d63a04a..6ea010e 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -23,6 +23,7 @@
 #include <cassert>
 #include <memory>
 
+#include "absl/base/attributes.h"
 #include "absl/base/call_once.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
@@ -53,9 +54,11 @@
 // exist within a process (via dlopen() or similar), references to
 // thread_identity_ptr from each instance of the code will refer to
 // *different* instances of this ptr.
-#ifdef __GNUC__
+// Apple platforms have the visibility attribute, but issue a compile warning
+// that protected visibility is unsupported.
+#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
 __attribute__((visibility("protected")))
-#endif  // __GNUC__
+#endif  // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
 #if ABSL_PER_THREAD_TLS
 // Prefer __thread to thread_local as benchmarks indicate it is a bit faster.
 ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index ceb109b..d2a65fd 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -32,6 +32,7 @@
 
 #include "absl/base/config.h"
 #include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -69,30 +70,28 @@
                          // is using this PerThreadSynch as a terminator.  Its
                          // skip field must not be filled in because the loop
                          // might then skip over the terminator.
-
-  // The wait parameters of the current wait.  waitp is null if the
-  // thread is not waiting. Transitions from null to non-null must
-  // occur before the enqueue commit point (state = kQueued in
-  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
-  // null must occur after the wait is finished (state = kAvailable in
-  // Mutex::Block() and CondVar::WaitCommon()). This field may be
-  // changed only by the thread that describes this PerThreadSynch.  A
-  // special case is Fer(), which calls Enqueue() on another thread,
-  // but with an identical SynchWaitParams pointer, thus leaving the
-  // pointer unchanged.
-  SynchWaitParams *waitp;
-
-  bool suppress_fatal_errors;  // If true, try to proceed even in the face of
-                               // broken invariants.  This is used within fatal
-                               // signal handlers to improve the chances of
-                               // debug logging information being output
-                               // successfully.
-
-  intptr_t readers;     // Number of readers in mutex.
-  int priority;         // Priority of thread (updated every so often).
-
-  // When priority will next be read (cycles).
-  int64_t next_priority_read_cycles;
+  bool wake;             // This thread is to be woken from a Mutex.
+  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
+  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
+  //
+  // The value of "x->cond_waiter" is meaningless if "x" is not on a
+  // Mutex waiter list.
+  bool cond_waiter;
+  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
+                         // true if UnlockSlow could be searching
+                         // for a waiter to wake.  Used for an optimization
+                         // in Enqueue().  true is always a valid value.
+                         // Can be reset to false when the unlocker or any
+                         // writer releases the lock, or a reader fully
+                         // releases the lock.  It may not be set to false
+                         // by a reader that decrements the count to
+                         // non-zero. protected by mutex spinlock
+  bool suppress_fatal_errors;  // If true, try to proceed even in the face
+                               // of broken invariants.  This is used within
+                               // fatal signal handlers to improve the
+                               // chances of debug logging information being
+                               // output successfully.
+  int priority;                // Priority of thread (updated every so often).
 
   // State values:
   //   kAvailable: This PerThreadSynch is available.
@@ -111,30 +110,30 @@
   };
   std::atomic<State> state;
 
-  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
-                         // true if UnlockSlow could be searching
-                         // for a waiter to wake.  Used for an optimization
-                         // in Enqueue().  true is always a valid value.
-                         // Can be reset to false when the unlocker or any
-                         // writer releases the lock, or a reader fully releases
-                         // the lock.  It may not be set to false by a reader
-                         // that decrements the count to non-zero.
-                         // protected by mutex spinlock
+  // The wait parameters of the current wait.  waitp is null if the
+  // thread is not waiting. Transitions from null to non-null must
+  // occur before the enqueue commit point (state = kQueued in
+  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
+  // null must occur after the wait is finished (state = kAvailable in
+  // Mutex::Block() and CondVar::WaitCommon()). This field may be
+  // changed only by the thread that describes this PerThreadSynch.  A
+  // special case is Fer(), which calls Enqueue() on another thread,
+  // but with an identical SynchWaitParams pointer, thus leaving the
+  // pointer unchanged.
+  SynchWaitParams* waitp;
 
-  bool wake;  // This thread is to be woken from a Mutex.
+  intptr_t readers;     // Number of readers in mutex.
 
-  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
-  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
-  //
-  // The value of "x->cond_waiter" is meaningless if "x" is not on a
-  // Mutex waiter list.
-  bool cond_waiter;
+  // When priority will next be read (cycles).
+  int64_t next_priority_read_cycles;
 
   // Locks held; used during deadlock detection.
   // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
   SynchLocksHeld *all_locks;
 };
 
+// The instances of this class are allocated in NewThreadIdentity() with an
+// alignment of PerThreadSynch::kAlignment.
 struct ThreadIdentity {
   // Must be the first member.  The Mutex implementation requires that
   // the PerThreadSynch object associated with each thread is
@@ -212,7 +211,9 @@
 #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
 #elif defined(_WIN32) && !defined(__MINGW32__)
 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
+#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
+#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) &&        \
     (__GOOGLE_GRTE_VERSION__ >= 20140228L)
 // Support for async-safe TLS was specifically added in GRTEv4.  It's not
 // present in the upstream eglibc.
diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc
index c055f75..c260ff1 100644
--- a/absl/base/internal/throw_delegate.cc
+++ b/absl/base/internal/throw_delegate.cc
@@ -18,6 +18,7 @@
 #include <functional>
 #include <new>
 #include <stdexcept>
+
 #include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 
@@ -25,83 +26,186 @@
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
+// NOTE: The various STL exception throwing functions are placed within the
+// #ifdef blocks so the symbols aren't exposed on platforms that don't support
+// them, such as the Android NDK. For example, ANGLE fails to link when building
+// within AOSP without them, since the STL functions don't exist.
 namespace {
+#ifdef ABSL_HAVE_EXCEPTIONS
 template <typename T>
 [[noreturn]] void Throw(const T& error) {
-#ifdef ABSL_HAVE_EXCEPTIONS
   throw error;
-#else
-  ABSL_RAW_LOG(FATAL, "%s", error.what());
-  std::abort();
-#endif
 }
+#endif
 }  // namespace
 
 void ThrowStdLogicError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::logic_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdLogicError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::logic_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 void ThrowStdInvalidArgument(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::invalid_argument(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdInvalidArgument(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::invalid_argument(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdDomainError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::domain_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdDomainError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::domain_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdLengthError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::length_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdLengthError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::length_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdOutOfRange(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::out_of_range(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdOutOfRange(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::out_of_range(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdRuntimeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::runtime_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdRuntimeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::runtime_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdRangeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::range_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdRangeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::range_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdOverflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::overflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdOverflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::overflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdUnderflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::underflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdUnderflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::underflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
-void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
+void ThrowStdBadFunctionCall() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  Throw(std::bad_function_call());
+#else
+  std::abort();
+#endif
+}
 
-void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
+void ThrowStdBadAlloc() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  Throw(std::bad_alloc());
+#else
+  std::abort();
+#endif
+}
 
 }  // namespace base_internal
 ABSL_NAMESPACE_END
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index dd5250d..080c197 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -45,17 +45,7 @@
 // For all three tools, replacing an unaligned access with a tool-specific
 // callback solves the problem.
 
-// Make sure uint16_t/uint32_t/uint64_t are defined.
-#include <stdint.h>
-
-extern "C" {
-uint16_t __sanitizer_unaligned_load16(const void *p);
-uint32_t __sanitizer_unaligned_load32(const void *p);
-uint64_t __sanitizer_unaligned_load64(const void *p);
-void __sanitizer_unaligned_store16(void *p, uint16_t v);
-void __sanitizer_unaligned_store32(void *p, uint32_t v);
-void __sanitizer_unaligned_store64(void *p, uint64_t v);
-}  // extern "C"
+#include <sanitizer/common_interface_defs.h>
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc
index f1e7bbe..1545288 100644
--- a/absl/base/internal/unscaledcycleclock.cc
+++ b/absl/base/internal/unscaledcycleclock.cc
@@ -123,9 +123,7 @@
 
 #pragma intrinsic(__rdtsc)
 
-int64_t UnscaledCycleClock::Now() {
-  return __rdtsc();
-}
+int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
 
 double UnscaledCycleClock::Frequency() {
   return base_internal::NominalCPUFrequency();
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index 65a3b16..045f17f 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
-#define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#ifndef ABSL_BASE_LOG_SEVERITY_H_
+#define ABSL_BASE_LOG_SEVERITY_H_
 
 #include <array>
 #include <ostream>
@@ -118,4 +118,4 @@
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#endif  // ABSL_BASE_LOG_SEVERITY_H_
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
deleted file mode 100644
index 6696229..0000000
--- a/absl/compiler_config_setting.bzl
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright 2018 The Abseil Authors.
-#
-# 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
-#
-#      https://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.
-
-"""Creates config_setting that allows selecting based on 'compiler' value."""
-
-def create_llvm_config(name, visibility):
-    # The "do_not_use_tools_cpp_compiler_present" attribute exists to
-    # distinguish between older versions of Bazel that do not support
-    # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
-    # In the future, the only way to select on the compiler will be through
-    # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
-    # be removed.
-    if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
-        native.config_setting(
-            name = name,
-            flag_values = {
-                "@bazel_tools//tools/cpp:compiler": "llvm",
-            },
-            visibility = visibility,
-        )
-    else:
-        native.config_setting(
-            name = name,
-            values = {"compiler": "llvm"},
-            visibility = visibility,
-        )
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index cca5d44..8e72ad0 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "compressed_tuple",
diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h
index bb450ea..abc09b0 100644
--- a/absl/container/btree_map.h
+++ b/absl/container/btree_map.h
@@ -185,7 +185,7 @@
   // template <typename K> size_type erase(const K& key):
   //
   //   Erases the element with the matching key, if it exists, returning the
-  //   number of elements erased.
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // btree_map::insert()
@@ -325,6 +325,11 @@
   //   does not contain an element with a matching key, this function returns an
   //   empty node handle.
   //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
+  //
   // NOTE: In this context, `node_type` refers to the C++17 concept of a
   // move-only type that owns and provides access to the elements in associative
   // containers (https://en.cppreference.com/w/cpp/container/node_handle).
@@ -652,6 +657,11 @@
   //   does not contain an element with a matching key, this function returns an
   //   empty node handle.
   //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
+  //
   // NOTE: In this context, `node_type` refers to the C++17 concept of a
   // move-only type that owns and provides access to the elements in associative
   // containers (https://en.cppreference.com/w/cpp/container/node_handle).
diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h
index d3e7886..21ef0a0 100644
--- a/absl/container/btree_set.h
+++ b/absl/container/btree_set.h
@@ -183,7 +183,7 @@
   // template <typename K> size_type erase(const K& key):
   //
   //   Erases the element with the matching key, if it exists, returning the
-  //   number of elements erased.
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // btree_set::insert()
diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc
index 0c5f936..9b1b643 100644
--- a/absl/container/btree_test.cc
+++ b/absl/container/btree_test.cc
@@ -55,6 +55,7 @@
 using ::testing::IsEmpty;
 using ::testing::IsNull;
 using ::testing::Pair;
+using ::testing::SizeIs;
 
 template <typename T, typename U>
 void CheckPairEquals(const T &x, const U &y) {
@@ -1182,6 +1183,103 @@
   EXPECT_EQ(1, tmap.size());
 }
 
+}  // namespace
+
+class BtreeNodePeer {
+ public:
+  // Yields the size of a leaf node with a specific number of values.
+  template <typename ValueType>
+  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
+    return btree_node<
+        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
+                   /*TargetNodeSize=*/256,  // This parameter isn't used here.
+                   /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
+  }
+
+  // Yields the number of values in a (non-root) leaf node for this btree.
+  template <typename Btree>
+  constexpr static size_t GetNumValuesPerNode() {
+    return btree_node<typename Btree::params_type>::kNodeValues;
+  }
+
+  template <typename Btree>
+  constexpr static size_t GetMaxFieldType() {
+    return std::numeric_limits<
+        typename btree_node<typename Btree::params_type>::field_type>::max();
+  }
+
+  template <typename Btree>
+  constexpr static bool UsesLinearNodeSearch() {
+    return btree_node<typename Btree::params_type>::use_linear_search::value;
+  }
+};
+
+namespace {
+
+class BtreeMapTest : public ::testing::Test {
+ public:
+  struct Key {};
+  struct Cmp {
+    template <typename T>
+    bool operator()(T, T) const {
+      return false;
+    }
+  };
+
+  struct KeyLin {
+    using absl_btree_prefer_linear_node_search = std::true_type;
+  };
+  struct CmpLin : Cmp {
+    using absl_btree_prefer_linear_node_search = std::true_type;
+  };
+
+  struct KeyBin {
+    using absl_btree_prefer_linear_node_search = std::false_type;
+  };
+  struct CmpBin : Cmp {
+    using absl_btree_prefer_linear_node_search = std::false_type;
+  };
+
+  template <typename K, typename C>
+  static bool IsLinear() {
+    return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
+  }
+};
+
+TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
+  // Test requesting linear search by directly exporting an alias.
+  EXPECT_FALSE((IsLinear<Key, Cmp>()));
+  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+  EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+}
+
+TEST_F(BtreeMapTest, LinearChoiceTree) {
+  // Cmp has precedence, and is forcing binary
+  EXPECT_FALSE((IsLinear<Key, CmpBin>()));
+  EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
+  EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
+  EXPECT_FALSE((IsLinear<int, CmpBin>()));
+  EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
+  // Cmp has precedence, and is forcing linear
+  EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
+  EXPECT_TRUE((IsLinear<int, CmpLin>()));
+  EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
+  // Cmp has no preference, Key determines linear vs binary.
+  EXPECT_FALSE((IsLinear<Key, Cmp>()));
+  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+  EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
+  // arithmetic key w/ std::less or std::greater: linear
+  EXPECT_TRUE((IsLinear<int, std::less<int>>()));
+  EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
+  // arithmetic key w/ custom compare: binary
+  EXPECT_FALSE((IsLinear<int, Cmp>()));
+  // non-arithmetic key: binary
+  EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
+}
+
 TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
   absl::btree_map<std::string, std::unique_ptr<std::string>> m;
 
@@ -1327,34 +1425,6 @@
   EXPECT_EQ(tracker.swaps(), 0);
 }
 
-}  // namespace
-
-class BtreeNodePeer {
- public:
-  // Yields the size of a leaf node with a specific number of values.
-  template <typename ValueType>
-  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
-    return btree_node<
-        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
-                   /*TargetNodeSize=*/256,  // This parameter isn't used here.
-                   /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
-  }
-
-  // Yields the number of values in a (non-root) leaf node for this set.
-  template <typename Set>
-  constexpr static size_t GetNumValuesPerNode() {
-    return btree_node<typename Set::params_type>::kNodeValues;
-  }
-
-  template <typename Set>
-  constexpr static size_t GetMaxFieldType() {
-    return std::numeric_limits<
-        typename btree_node<typename Set::params_type>::field_type>::max();
-  }
-};
-
-namespace {
-
 // A btree set with a specific number of values per node.
 template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
 class SizedBtreeSet
@@ -2109,6 +2179,31 @@
                                Pair(4, 1), Pair(4, 4), Pair(5, 5)));
 }
 
+TEST(Btree, MergeIntoSetMovableOnly) {
+  absl::btree_set<MovableOnlyInstance> src;
+  src.insert(MovableOnlyInstance(1));
+  absl::btree_multiset<MovableOnlyInstance> dst1;
+  dst1.insert(MovableOnlyInstance(2));
+  absl::btree_set<MovableOnlyInstance> dst2;
+
+  // Test merge into multiset.
+  dst1.merge(src);
+
+  EXPECT_TRUE(src.empty());
+  // ElementsAre/ElementsAreArray don't work with move-only types.
+  ASSERT_THAT(dst1, SizeIs(2));
+  EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));
+  EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));
+
+  // Test merge into set.
+  dst2.merge(dst1);
+
+  EXPECT_TRUE(dst1.empty());
+  ASSERT_THAT(dst2, SizeIs(2));
+  EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));
+  EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));
+}
+
 struct KeyCompareToWeakOrdering {
   template <typename T>
   absl::weak_ordering operator()(const T &a, const T &b) const {
@@ -2551,6 +2646,181 @@
 }
 #endif
 
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(Btree, NodeHandleMutableKeyAccess) {
+  {
+    absl::btree_map<std::string, std::string> map;
+
+    map["key1"] = "mapped";
+
+    auto nh = map.extract(map.begin());
+    nh.key().resize(3);
+    map.insert(std::move(nh));
+
+    EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+  }
+  // Also for multimap.
+  {
+    absl::btree_multimap<std::string, std::string> map;
+
+    map.emplace("key1", "mapped");
+
+    auto nh = map.extract(map.begin());
+    nh.key().resize(3);
+    map.insert(std::move(nh));
+
+    EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+  }
+}
+#endif
+
+struct MultiKey {
+  int i1;
+  int i2;
+};
+
+bool operator==(const MultiKey a, const MultiKey b) {
+  return a.i1 == b.i1 && a.i2 == b.i2;
+}
+
+// A heterogeneous comparator that has different equivalence classes for
+// different lookup types.
+struct MultiKeyComp {
+  using is_transparent = void;
+  bool operator()(const MultiKey a, const MultiKey b) const {
+    if (a.i1 != b.i1) return a.i1 < b.i1;
+    return a.i2 < b.i2;
+  }
+  bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
+  bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
+};
+
+TEST(Btree, MultiKeyEqualRange) {
+  absl::btree_set<MultiKey, MultiKeyComp> set;
+
+  for (int i = 0; i < 100; ++i) {
+    for (int j = 0; j < 100; ++j) {
+      set.insert({i, j});
+    }
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    auto equal_range = set.equal_range(i);
+    EXPECT_EQ(equal_range.first->i1, i);
+    EXPECT_EQ(equal_range.first->i2, 0);
+    EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
+  }
+}
+
+TEST(Btree, MultiKeyErase) {
+  absl::btree_set<MultiKey, MultiKeyComp> set = {
+      {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+  EXPECT_EQ(set.erase(2), 2);
+  EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));
+}
+
+TEST(Btree, MultiKeyCount) {
+  const absl::btree_set<MultiKey, MultiKeyComp> set = {
+      {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+  EXPECT_EQ(set.count(2), 2);
+}
+
+TEST(Btree, AllocConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set(alloc);
+
+  set.insert({1, 2, 3});
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocInitializerListConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set({1, 2, 3}, alloc);
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocRangeConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  std::vector<int> v = {1, 2, 3};
+  Set set(v.begin(), v.end(), alloc);
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocCopyConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used1 = 0;
+  Alloc alloc1(&bytes_used1);
+  Set set1(alloc1);
+
+  set1.insert({1, 2, 3});
+
+  int64_t bytes_used2 = 0;
+  Alloc alloc2(&bytes_used2);
+  Set set2(set1, alloc2);
+
+  EXPECT_THAT(set1, ElementsAre(1, 2, 3));
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used1, set1.size() * sizeof(int));
+  EXPECT_EQ(bytes_used1, bytes_used2);
+}
+
+TEST(Btree, AllocMoveConstructor_SameAlloc) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set1(alloc);
+
+  set1.insert({1, 2, 3});
+
+  const int64_t original_bytes_used = bytes_used;
+  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+  Set set2(std::move(set1), alloc);
+
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  EXPECT_EQ(bytes_used, original_bytes_used);
+}
+
+TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used1 = 0;
+  Alloc alloc1(&bytes_used1);
+  Set set1(alloc1);
+
+  set1.insert({1, 2, 3});
+
+  const int64_t original_bytes_used = bytes_used1;
+  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+  int64_t bytes_used2 = 0;
+  Alloc alloc2(&bytes_used2);
+  Set set2(std::move(set1), alloc2);
+
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  // We didn't free these bytes allocated by `set1` yet.
+  EXPECT_EQ(bytes_used1, original_bytes_used);
+  EXPECT_EQ(bytes_used2, original_bytes_used);
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index c8fe8d9..fcb3e54 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -232,8 +232,8 @@
 
   // FixedArray::at
   //
-  // Bounds-checked access.  Returns a reference to the ith element of the
-  // fiexed array, or throws std::out_of_range
+  // Bounds-checked access.  Returns a reference to the ith element of the fixed
+  // array, or throws std::out_of_range
   reference at(size_type i) {
     if (ABSL_PREDICT_FALSE(i >= size())) {
       base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index fcb70d8..74def0d 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -234,7 +234,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // flat_hash_map::insert()
@@ -383,6 +384,11 @@
   //   key value and returns a node handle owning that extracted data. If the
   //   `flat_hash_map` does not contain an element with a matching key, this
   //   function returns an empty node handle.
+  //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
   using Base::extract;
 
   // flat_hash_map::merge()
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 2823c32..89ec60c 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -267,6 +267,21 @@
   }
 }
 
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(FlatHashMap, NodeHandleMutableKeyAccess) {
+  flat_hash_map<std::string, std::string> map;
+
+  map["key1"] = "mapped";
+
+  auto nh = map.extract(map.begin());
+  nh.key().resize(3);
+  map.insert(std::move(nh));
+
+  EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 94be6e3..81e145a 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -227,7 +227,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // flat_hash_set::insert()
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index 293e577..f2fc31d 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -137,15 +137,14 @@
 };
 
 // A helper class to convert a boolean comparison into a three-way "compare-to"
-// comparison that returns a negative value to indicate less-than, zero to
-// indicate equality and a positive value to indicate greater-than. This helper
+// comparison that returns an `absl::weak_ordering`. This helper
 // class is specialized for less<std::string>, greater<std::string>,
 // less<string_view>, greater<string_view>, less<absl::Cord>, and
 // greater<absl::Cord>.
 //
 // key_compare_to_adapter is provided so that btree users
 // automatically get the more efficient compare-to code when using common
-// google string types with common comparison functors.
+// Abseil string types with common comparison functors.
 // These string-like specializations also turn on heterogeneous lookup by
 // default.
 template <typename Compare>
@@ -183,12 +182,47 @@
   using type = StringBtreeDefaultGreater;
 };
 
+// Detects an 'absl_btree_prefer_linear_node_search' member. This is
+// a protocol used as an opt-in or opt-out of linear search.
+//
+//  For example, this would be useful for key types that wrap an integer
+//  and define their own cheap operator<(). For example:
+//
+//   class K {
+//    public:
+//     using absl_btree_prefer_linear_node_search = std::true_type;
+//     ...
+//    private:
+//     friend bool operator<(K a, K b) { return a.k_ < b.k_; }
+//     int k_;
+//   };
+//
+//   btree_map<K, V> m;  // Uses linear search
+//
+// If T has the preference tag, then it has a preference.
+// Btree will use the tag's truth value.
+template <typename T, typename = void>
+struct has_linear_node_search_preference : std::false_type {};
+template <typename T, typename = void>
+struct prefers_linear_node_search : std::false_type {};
+template <typename T>
+struct has_linear_node_search_preference<
+    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+    : std::true_type {};
+template <typename T>
+struct prefers_linear_node_search<
+    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+    : T::absl_btree_prefer_linear_node_search {};
+
 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
           bool Multi, typename SlotPolicy>
 struct common_params {
   // If Compare is a common comparator for a string-like type, then we adapt it
   // to use heterogeneous lookup and to be a key-compare-to comparator.
   using key_compare = typename key_compare_to_adapter<Compare>::type;
+  // True when key_compare has been adapted to StringBtreeDefault{Less,Greater}.
+  using is_key_compare_adapted =
+      absl::negation<std::is_same<key_compare, Compare>>;
   // A type which indicates if we have a key-compare-to functor or a plain old
   // key-compare functor.
   using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;
@@ -292,6 +326,11 @@
   }
   static const Key &key(const slot_type *s) { return slot_policy::key(s); }
   static const Key &key(slot_type *s) { return slot_policy::key(s); }
+  // For use in node handle.
+  static auto mutable_key(slot_type *s)
+      -> decltype(slot_policy::mutable_key(s)) {
+    return slot_policy::mutable_key(s);
+  }
   static mapped_type &value(value_type *value) { return value->second; }
 };
 
@@ -384,6 +423,10 @@
 // useful information.
 template <typename V>
 struct SearchResult<V, false> {
+  SearchResult() {}
+  explicit SearchResult(V value) : value(value) {}
+  SearchResult(V value, MatchKind /*match*/) : value(value) {}
+
   V value;
 
   static constexpr bool HasMatch() { return false; }
@@ -414,15 +457,22 @@
   using difference_type = typename Params::difference_type;
 
   // Btree decides whether to use linear node search as follows:
+  //   - If the comparator expresses a preference, use that.
+  //   - If the key expresses a preference, use that.
   //   - If the key is arithmetic and the comparator is std::less or
   //     std::greater, choose linear.
   //   - Otherwise, choose binary.
   // TODO(ezb): Might make sense to add condition(s) based on node-size.
   using use_linear_search = std::integral_constant<
       bool,
-                std::is_arithmetic<key_type>::value &&
-                    (std::is_same<std::less<key_type>, key_compare>::value ||
-                     std::is_same<std::greater<key_type>, key_compare>::value)>;
+      has_linear_node_search_preference<key_compare>::value
+          ? prefers_linear_node_search<key_compare>::value
+          : has_linear_node_search_preference<key_type>::value
+                ? prefers_linear_node_search<key_type>::value
+                : std::is_arithmetic<key_type>::value &&
+                      (std::is_same<std::less<key_type>, key_compare>::value ||
+                       std::is_same<std::greater<key_type>,
+                                    key_compare>::value)>;
 
   // This class is organized by gtl::Layout as if it had the following
   // structure:
@@ -665,7 +715,7 @@
       }
       ++s;
     }
-    return {s};
+    return SearchResult<int, false>{s};
   }
 
   // Returns the position of the first value whose key is not less than k using
@@ -700,7 +750,7 @@
         e = mid;
       }
     }
-    return {s};
+    return SearchResult<int, false>{s};
   }
 
   // Returns the position of the first value whose key is not less than k using
@@ -793,12 +843,6 @@
   // Deletes a node and all of its children.
   static void clear_and_delete(btree_node *node, allocator_type *alloc);
 
- public:
-  // Exposed only for tests.
-  static bool testonly_uses_linear_node_search() {
-    return use_linear_search::value;
-  }
-
  private:
   template <typename... Args>
   void value_init(const field_type i, allocator_type *alloc, Args &&... args) {
@@ -1009,6 +1053,9 @@
   using node_type = btree_node<Params>;
   using is_key_compare_to = typename Params::is_key_compare_to;
   using init_type = typename Params::init_type;
+  using field_type = typename node_type::field_type;
+  using is_multi_container = typename Params::is_multi_container;
+  using is_key_compare_adapted = typename Params::is_key_compare_adapted;
 
   // We use a static empty node for the root/leftmost/rightmost of empty btrees
   // in order to avoid branching in begin()/end().
@@ -1043,7 +1090,7 @@
 #endif
   }
 
-  enum {
+  enum : uint32_t {
     kNodeValues = node_type::kNodeValues,
     kMinNodeValues = kNodeValues / 2,
   };
@@ -1095,21 +1142,35 @@
   // before this method is called. This method is used in copy construction,
   // copy assignment, and move assignment.
   template <typename Btree>
-  void copy_or_move_values_in_order(Btree *other);
+  void copy_or_move_values_in_order(Btree &other);
 
   // Validates that various assumptions/requirements are true at compile time.
   constexpr static bool static_assert_validation();
 
  public:
-  btree(const key_compare &comp, const allocator_type &alloc);
+  btree(const key_compare &comp, const allocator_type &alloc)
+      : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
 
-  btree(const btree &other);
+  btree(const btree &other) : btree(other, other.allocator()) {}
+  btree(const btree &other, const allocator_type &alloc)
+      : btree(other.key_comp(), alloc) {
+    copy_or_move_values_in_order(other);
+  }
   btree(btree &&other) noexcept
       : root_(std::move(other.root_)),
         rightmost_(absl::exchange(other.rightmost_, EmptyNode())),
         size_(absl::exchange(other.size_, 0)) {
     other.mutable_root() = EmptyNode();
   }
+  btree(btree &&other, const allocator_type &alloc)
+      : btree(other.key_comp(), alloc) {
+    if (alloc == other.allocator()) {
+      swap(other);
+    } else {
+      // Move values from `other` one at a time when allocators are different.
+      copy_or_move_values_in_order(other);
+    }
+  }
 
   ~btree() {
     // Put static_asserts in destructor to avoid triggering them before the type
@@ -1140,11 +1201,11 @@
   // Finds the first element whose key is not less than key.
   template <typename K>
   iterator lower_bound(const K &key) {
-    return internal_end(internal_lower_bound(key));
+    return internal_end(internal_lower_bound(key).value);
   }
   template <typename K>
   const_iterator lower_bound(const K &key) const {
-    return internal_end(internal_lower_bound(key));
+    return internal_end(internal_lower_bound(key).value);
   }
 
   // Finds the first element whose key is greater than key.
@@ -1158,15 +1219,13 @@
   }
 
   // Finds the range of values which compare equal to key. The first member of
-  // the returned pair is equal to lower_bound(key). The second member pair of
-  // the pair is equal to upper_bound(key).
+  // the returned pair is equal to lower_bound(key). The second member of the
+  // pair is equal to upper_bound(key).
   template <typename K>
-  std::pair<iterator, iterator> equal_range(const K &key) {
-    return {lower_bound(key), upper_bound(key)};
-  }
+  std::pair<iterator, iterator> equal_range(const K &key);
   template <typename K>
   std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
-    return {lower_bound(key), upper_bound(key)};
+    return const_cast<btree *>(this)->equal_range(key);
   }
 
   // Inserts a value into the btree only if it does not already exist. The
@@ -1231,16 +1290,6 @@
   // to the element after the last erased element.
   std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
 
-  // Erases the specified key from the btree. Returns 1 if an element was
-  // erased and 0 otherwise.
-  template <typename K>
-  size_type erase_unique(const K &key);
-
-  // Erases all of the entries matching the specified key from the
-  // btree. Returns the number of elements erased.
-  template <typename K>
-  size_type erase_multi(const K &key);
-
   // Finds the iterator corresponding to a key or returns end() if the key is
   // not present.
   template <typename K>
@@ -1252,23 +1301,6 @@
     return internal_end(internal_find(key));
   }
 
-  // Returns a count of the number of times the key appears in the btree.
-  template <typename K>
-  size_type count_unique(const K &key) const {
-    const iterator begin = internal_find(key);
-    if (begin.node == nullptr) {
-      // The key doesn't exist in the tree.
-      return 0;
-    }
-    return 1;
-  }
-  // Returns a count of the number of times the key appears in the btree.
-  template <typename K>
-  size_type count_multi(const K &key) const {
-    const auto range = equal_range(key);
-    return std::distance(range.first, range.second);
-  }
-
   // Clear the btree, deleting all of the values it contains.
   void clear();
 
@@ -1445,28 +1477,19 @@
   static IterType internal_last(IterType iter);
 
   // Returns an iterator pointing to the leaf position at which key would
-  // reside in the tree. We provide 2 versions of internal_locate. The first
-  // version uses a less-than comparator and is incapable of distinguishing when
-  // there is an exact match. The second version is for the key-compare-to
-  // specialization and distinguishes exact matches. The key-compare-to
-  // specialization allows the caller to avoid a subsequent comparison to
-  // determine if an exact match was made, which is important for keys with
-  // expensive comparison, such as strings.
+  // reside in the tree, unless there is an exact match - in which case, the
+  // result may not be on a leaf. When there's a three-way comparator, we can
+  // return whether there was an exact match. This allows the caller to avoid a
+  // subsequent comparison to determine if an exact match was made, which is
+  // important for keys with expensive comparison, such as strings.
   template <typename K>
   SearchResult<iterator, is_key_compare_to::value> internal_locate(
       const K &key) const;
 
-  template <typename K>
-  SearchResult<iterator, false> internal_locate_impl(
-      const K &key, std::false_type /* IsCompareTo */) const;
-
-  template <typename K>
-  SearchResult<iterator, true> internal_locate_impl(
-      const K &key, std::true_type /* IsCompareTo */) const;
-
   // Internal routine which implements lower_bound().
   template <typename K>
-  iterator internal_lower_bound(const K &key) const;
+  SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
+      const K &key) const;
 
   // Internal routine which implements upper_bound().
   template <typename K>
@@ -1495,13 +1518,6 @@
     return res;
   }
 
- public:
-  // Exposed only for tests.
-  static bool testonly_uses_linear_node_search() {
-    return node_type::testonly_uses_linear_node_search();
-  }
-
- private:
   // We use compressed tuple in order to save space because key_compare and
   // allocator_type are usually empty.
   absl::container_internal::CompressedTuple<key_compare, allocator_type,
@@ -1824,7 +1840,7 @@
 // btree methods
 template <typename P>
 template <typename Btree>
-void btree<P>::copy_or_move_values_in_order(Btree *other) {
+void btree<P>::copy_or_move_values_in_order(Btree &other) {
   static_assert(std::is_same<btree, Btree>::value ||
                     std::is_same<const btree, Btree>::value,
                 "Btree type must be same or const.");
@@ -1832,11 +1848,11 @@
 
   // We can avoid key comparisons because we know the order of the
   // values is the same order we'll store them in.
-  auto iter = other->begin();
-  if (iter == other->end()) return;
+  auto iter = other.begin();
+  if (iter == other.end()) return;
   insert_multi(maybe_move_from_iterator(iter));
   ++iter;
-  for (; iter != other->end(); ++iter) {
+  for (; iter != other.end(); ++iter) {
     // If the btree is not empty, we can just insert the new value at the end
     // of the tree.
     internal_emplace(end(), maybe_move_from_iterator(iter));
@@ -1875,13 +1891,40 @@
 }
 
 template <typename P>
-btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
-    : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
+template <typename K>
+auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {
+  const SearchResult<iterator, is_key_compare_to::value> res =
+      internal_lower_bound(key);
+  const iterator lower = internal_end(res.value);
+  if (res.HasMatch() ? !res.IsEq()
+                     : lower == end() || compare_keys(key, lower.key())) {
+    return {lower, lower};
+  }
 
-template <typename P>
-btree<P>::btree(const btree &other)
-    : btree(other.key_comp(), other.allocator()) {
-  copy_or_move_values_in_order(&other);
+  const iterator next = std::next(lower);
+  // When the comparator is heterogeneous, we can't assume that comparison with
+  // non-`key_type` will be equivalent to `key_type` comparisons so there
+  // could be multiple equivalent keys even in a unique-container. But for
+  // heterogeneous comparisons from the default string adapted comparators, we
+  // don't need to worry about this.
+  if (!is_multi_container::value &&
+      (std::is_same<K, key_type>::value || is_key_compare_adapted::value)) {
+    // The next iterator after lower must point to a key greater than `key`.
+    // Note: if this assert fails, then it may indicate that the comparator does
+    // not meet the equivalence requirements for Compare
+    // (see https://en.cppreference.com/w/cpp/named_req/Compare).
+    assert(next == end() || compare_keys(key, next.key()));
+    return {lower, next};
+  }
+  // Try once more to avoid the call to upper_bound() if there's only one
+  // equivalent key. This should prevent all calls to upper_bound() in cases of
+  // unique-containers with heterogeneous comparators in which all comparison
+  // operators have the same equivalence classes.
+  if (next == end() || compare_keys(key, next.key())) return {lower, next};
+
+  // In this case, we need to call upper_bound() to avoid worst case O(N)
+  // behavior if we were to iterate over equal keys.
+  return {lower, upper_bound(key)};
 }
 
 template <typename P>
@@ -1892,8 +1935,8 @@
     mutable_root() = rightmost_ = new_leaf_root_node(1);
   }
 
-  auto res = internal_locate(key);
-  iterator &iter = res.value;
+  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
+  iterator iter = res.value;
 
   if (res.HasMatch()) {
     if (res.IsEq()) {
@@ -2007,7 +2050,7 @@
       *mutable_allocator() = other.allocator();
     }
 
-    copy_or_move_values_in_order(&other);
+    copy_or_move_values_in_order(other);
   }
   return *this;
 }
@@ -2037,7 +2080,7 @@
         // comparator while moving the values so we can't swap the key
         // comparators.
         *mutable_key_comp() = other.key_comp();
-        copy_or_move_values_in_order(&other);
+        copy_or_move_values_in_order(other);
       }
     }
   }
@@ -2161,31 +2204,6 @@
 }
 
 template <typename P>
-template <typename K>
-auto btree<P>::erase_unique(const K &key) -> size_type {
-  const iterator iter = internal_find(key);
-  if (iter.node == nullptr) {
-    // The key doesn't exist in the tree, return nothing done.
-    return 0;
-  }
-  erase(iter);
-  return 1;
-}
-
-template <typename P>
-template <typename K>
-auto btree<P>::erase_multi(const K &key) -> size_type {
-  const iterator begin = internal_lower_bound(key);
-  if (begin.node == nullptr) {
-    // The key doesn't exist in the tree, return nothing done.
-    return 0;
-  }
-  // Delete all of the keys between begin and upper_bound(key).
-  const iterator end = internal_end(internal_upper_bound(key));
-  return erase_range(begin, end).first;
-}
-
-template <typename P>
 void btree<P>::clear() {
   if (!empty()) {
     node_type::clear_and_delete(root(), mutable_allocator());
@@ -2243,11 +2261,11 @@
         // inserting at the end of the right node then we bias rebalancing to
         // fill up the left node.
         int to_move = (kNodeValues - left->count()) /
-                      (1 + (insert_position < kNodeValues));
+                      (1 + (insert_position < static_cast<int>(kNodeValues)));
         to_move = (std::max)(1, to_move);
 
         if (insert_position - to_move >= node->start() ||
-            left->count() + to_move < kNodeValues) {
+            left->count() + to_move < static_cast<int>(kNodeValues)) {
           left->rebalance_right_to_left(to_move, node, mutable_allocator());
 
           assert(node->max_count() - node->count() == to_move);
@@ -2271,12 +2289,12 @@
         // We bias rebalancing based on the position being inserted. If we're
         // inserting at the beginning of the left node then we bias rebalancing
         // to fill up the right node.
-        int to_move = (kNodeValues - right->count()) /
+        int to_move = (static_cast<int>(kNodeValues) - right->count()) /
                       (1 + (insert_position > node->start()));
         to_move = (std::max)(1, to_move);
 
         if (insert_position <= node->finish() - to_move ||
-            right->count() + to_move < kNodeValues) {
+            right->count() + to_move < static_cast<int>(kNodeValues)) {
           node->rebalance_left_to_right(to_move, right, mutable_allocator());
 
           if (insert_position > node->finish()) {
@@ -2339,7 +2357,7 @@
     // Try merging with our left sibling.
     node_type *left = parent->child(iter->node->position() - 1);
     assert(left->max_count() == kNodeValues);
-    if (1 + left->count() + iter->node->count() <= kNodeValues) {
+    if (1U + left->count() + iter->node->count() <= kNodeValues) {
       iter->position += 1 + left->count();
       merge_nodes(left, iter->node);
       iter->node = left;
@@ -2350,7 +2368,7 @@
     // Try merging with our right sibling.
     node_type *right = parent->child(iter->node->position() + 1);
     assert(right->max_count() == kNodeValues);
-    if (1 + iter->node->count() + right->count() <= kNodeValues) {
+    if (1U + iter->node->count() + right->count() <= kNodeValues) {
       merge_nodes(iter->node, right);
       return true;
     }
@@ -2427,7 +2445,7 @@
     --iter;
     ++iter.position;
   }
-  const int max_count = iter.node->max_count();
+  const field_type max_count = iter.node->max_count();
   allocator_type *alloc = mutable_allocator();
   if (iter.node->count() == max_count) {
     // Make room in the leaf for the new item.
@@ -2459,61 +2477,48 @@
 template <typename K>
 inline auto btree<P>::internal_locate(const K &key) const
     -> SearchResult<iterator, is_key_compare_to::value> {
-  return internal_locate_impl(key, is_key_compare_to());
-}
-
-template <typename P>
-template <typename K>
-inline auto btree<P>::internal_locate_impl(
-    const K &key, std::false_type /* IsCompareTo */) const
-    -> SearchResult<iterator, false> {
   iterator iter(const_cast<node_type *>(root()));
   for (;;) {
-    iter.position = iter.node->lower_bound(key, key_comp()).value;
-    // NOTE: we don't need to walk all the way down the tree if the keys are
-    // equal, but determining equality would require doing an extra comparison
-    // on each node on the way down, and we will need to go all the way to the
-    // leaf node in the expected case.
-    if (iter.node->leaf()) {
-      break;
-    }
-    iter.node = iter.node->child(iter.position);
-  }
-  return {iter};
-}
-
-template <typename P>
-template <typename K>
-inline auto btree<P>::internal_locate_impl(
-    const K &key, std::true_type /* IsCompareTo */) const
-    -> SearchResult<iterator, true> {
-  iterator iter(const_cast<node_type *>(root()));
-  for (;;) {
-    SearchResult<int, true> res = iter.node->lower_bound(key, key_comp());
+    SearchResult<int, is_key_compare_to::value> res =
+        iter.node->lower_bound(key, key_comp());
     iter.position = res.value;
-    if (res.match == MatchKind::kEq) {
+    if (res.IsEq()) {
       return {iter, MatchKind::kEq};
     }
+    // Note: in the non-key-compare-to case, we don't need to walk all the way
+    // down the tree if the keys are equal, but determining equality would
+    // require doing an extra comparison on each node on the way down, and we
+    // will need to go all the way to the leaf node in the expected case.
     if (iter.node->leaf()) {
       break;
     }
     iter.node = iter.node->child(iter.position);
   }
+  // Note: in the non-key-compare-to case, the key may actually be equivalent
+  // here (and the MatchKind::kNe is ignored).
   return {iter, MatchKind::kNe};
 }
 
 template <typename P>
 template <typename K>
-auto btree<P>::internal_lower_bound(const K &key) const -> iterator {
+auto btree<P>::internal_lower_bound(const K &key) const
+    -> SearchResult<iterator, is_key_compare_to::value> {
   iterator iter(const_cast<node_type *>(root()));
+  SearchResult<int, is_key_compare_to::value> res;
+  bool seen_eq = false;
   for (;;) {
-    iter.position = iter.node->lower_bound(key, key_comp()).value;
+    res = iter.node->lower_bound(key, key_comp());
+    iter.position = res.value;
+    // TODO(ezb): we should be able to terminate early on IsEq() if there can't
+    // be multiple equivalent keys in container for this lookup type.
     if (iter.node->leaf()) {
       break;
     }
+    seen_eq = seen_eq || res.IsEq();
     iter.node = iter.node->child(iter.position);
   }
-  return internal_last(iter);
+  if (res.IsEq()) return {iter, MatchKind::kEq};
+  return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};
 }
 
 template <typename P>
@@ -2533,7 +2538,7 @@
 template <typename P>
 template <typename K>
 auto btree<P>::internal_find(const K &key) const -> iterator {
-  auto res = internal_locate(key);
+  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
   if (res.HasMatch()) {
     if (res.IsEq()) {
       return res.value;
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index 3b2e8a9..887eda4 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -23,6 +23,7 @@
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/container/internal/btree.h"  // IWYU pragma: export
 #include "absl/container/internal/common.h"
+#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 
 namespace absl {
@@ -68,8 +69,21 @@
   explicit btree_container(const key_compare &comp,
                            const allocator_type &alloc = allocator_type())
       : tree_(comp, alloc) {}
-  btree_container(const btree_container &other) = default;
-  btree_container(btree_container &&other) noexcept = default;
+  explicit btree_container(const allocator_type &alloc)
+      : tree_(key_compare(), alloc) {}
+
+  btree_container(const btree_container &other)
+      : btree_container(other, absl::allocator_traits<allocator_type>::
+                                   select_on_container_copy_construction(
+                                       other.get_allocator())) {}
+  btree_container(const btree_container &other, const allocator_type &alloc)
+      : tree_(other.tree_, alloc) {}
+
+  btree_container(btree_container &&other) noexcept(
+      std::is_nothrow_move_constructible<Tree>::value) = default;
+  btree_container(btree_container &&other, const allocator_type &alloc)
+      : tree_(std::move(other.tree_), alloc) {}
+
   btree_container &operator=(const btree_container &other) = default;
   btree_container &operator=(btree_container &&other) noexcept(
       std::is_nothrow_move_assignable<Tree>::value) = default;
@@ -90,6 +104,11 @@
 
   // Lookup routines.
   template <typename K = key_type>
+  size_type count(const key_arg<K> &key) const {
+    auto equal_range = this->equal_range(key);
+    return std::distance(equal_range.first, equal_range.second);
+  }
+  template <typename K = key_type>
   iterator find(const key_arg<K> &key) {
     return tree_.find(key);
   }
@@ -138,6 +157,11 @@
   iterator erase(const_iterator first, const_iterator last) {
     return tree_.erase_range(iterator(first), iterator(last)).second;
   }
+  template <typename K = key_type>
+  size_type erase(const key_arg<K> &key) {
+    auto equal_range = this->equal_range(key);
+    return tree_.erase_range(equal_range.first, equal_range.second).first;
+  }
 
   // Extract routines.
   node_type extract(iterator position) {
@@ -151,7 +175,6 @@
     return extract(iterator(position));
   }
 
- public:
   // Utility routines.
   void clear() { tree_.clear(); }
   void swap(btree_container &other) { tree_.swap(other.tree_); }
@@ -235,7 +258,7 @@
   using super_type::super_type;
   btree_set_container() {}
 
-  // Range constructor.
+  // Range constructors.
   template <class InputIterator>
   btree_set_container(InputIterator b, InputIterator e,
                       const key_compare &comp = key_compare(),
@@ -243,18 +266,19 @@
       : super_type(comp, alloc) {
     insert(b, e);
   }
+  template <class InputIterator>
+  btree_set_container(InputIterator b, InputIterator e,
+                      const allocator_type &alloc)
+      : btree_set_container(b, e, key_compare(), alloc) {}
 
-  // Initializer list constructor.
+  // Initializer list constructors.
   btree_set_container(std::initializer_list<init_type> init,
                       const key_compare &comp = key_compare(),
                       const allocator_type &alloc = allocator_type())
       : btree_set_container(init.begin(), init.end(), comp, alloc) {}
-
-  // Lookup routines.
-  template <typename K = key_type>
-  size_type count(const key_arg<K> &key) const {
-    return this->tree_.count_unique(key);
-  }
+  btree_set_container(std::initializer_list<init_type> init,
+                      const allocator_type &alloc)
+      : btree_set_container(init.begin(), init.end(), alloc) {}
 
   // Insertion routines.
   std::pair<iterator, bool> insert(const value_type &v) {
@@ -313,14 +337,10 @@
     return res.first;
   }
 
-  // Deletion routines.
-  template <typename K = key_type>
-  size_type erase(const key_arg<K> &key) {
-    return this->tree_.erase_unique(key);
-  }
-  using super_type::erase;
-
   // Node extraction routines.
+  // TODO(ezb): when the comparator is heterogeneous and has different
+  // equivalence classes for different lookup types, we should extract the first
+  // equivalent value if there are multiple.
   template <typename K = key_type>
   node_type extract(const key_arg<K> &key) {
     auto it = this->find(key);
@@ -342,7 +362,7 @@
           int> = 0>
   void merge(btree_container<T> &src) {  // NOLINT
     for (auto src_it = src.begin(); src_it != src.end();) {
-      if (insert(std::move(*src_it)).second) {
+      if (insert(std::move(params_type::element(src_it.slot()))).second) {
         src_it = src.erase(src_it);
       } else {
         ++src_it;
@@ -369,6 +389,7 @@
 class btree_map_container : public btree_set_container<Tree> {
   using super_type = btree_set_container<Tree>;
   using params_type = typename Tree::params_type;
+  friend class BtreeNodePeer;
 
  private:
   template <class K>
@@ -533,7 +554,7 @@
   using super_type::super_type;
   btree_multiset_container() {}
 
-  // Range constructor.
+  // Range constructors.
   template <class InputIterator>
   btree_multiset_container(InputIterator b, InputIterator e,
                            const key_compare &comp = key_compare(),
@@ -541,18 +562,19 @@
       : super_type(comp, alloc) {
     insert(b, e);
   }
+  template <class InputIterator>
+  btree_multiset_container(InputIterator b, InputIterator e,
+                           const allocator_type &alloc)
+      : btree_multiset_container(b, e, key_compare(), alloc) {}
 
-  // Initializer list constructor.
+  // Initializer list constructors.
   btree_multiset_container(std::initializer_list<init_type> init,
                            const key_compare &comp = key_compare(),
                            const allocator_type &alloc = allocator_type())
       : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
-
-  // Lookup routines.
-  template <typename K = key_type>
-  size_type count(const key_arg<K> &key) const {
-    return this->tree_.count_multi(key);
-  }
+  btree_multiset_container(std::initializer_list<init_type> init,
+                           const allocator_type &alloc)
+      : btree_multiset_container(init.begin(), init.end(), alloc) {}
 
   // Insertion routines.
   iterator insert(const value_type &v) { return this->tree_.insert_multi(v); }
@@ -598,14 +620,9 @@
     return res;
   }
 
-  // Deletion routines.
-  template <typename K = key_type>
-  size_type erase(const key_arg<K> &key) {
-    return this->tree_.erase_multi(key);
-  }
-  using super_type::erase;
-
   // Node extraction routines.
+  // TODO(ezb): we are supposed to extract the first equivalent key if there are
+  // multiple, but this isn't guaranteed to extract the first one.
   template <typename K = key_type>
   node_type extract(const key_arg<K> &key) {
     auto it = this->find(key);
@@ -625,8 +642,9 @@
                            typename T::params_type::is_map_container>>::value,
           int> = 0>
   void merge(btree_container<T> &src) {  // NOLINT
-    insert(std::make_move_iterator(src.begin()),
-           std::make_move_iterator(src.end()));
+    for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
+      insert(std::move(params_type::element(src_it.slot())));
+    }
     src.clear();
   }
 
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
index 8990f29..030e9d4 100644
--- a/absl/container/internal/common.h
+++ b/absl/container/internal/common.h
@@ -146,8 +146,11 @@
 
   constexpr node_handle() {}
 
-  auto key() const -> decltype(PolicyTraits::key(std::declval<slot_type*>())) {
-    return PolicyTraits::key(this->slot());
+  // When C++17 is available, we can use std::launder to provide mutable
+  // access to the key. Otherwise, we provide const access.
+  auto key() const
+      -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {
+    return PolicyTraits::mutable_key(this->slot());
   }
 
   mapped_type& mapped() const {
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index 02bfd03..5ebe164 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -257,7 +257,7 @@
 
   template <int I>
   ElemT<I>& get() & {
-    return internal_compressed_tuple::Storage<ElemT<I>, I>::get();
+    return StorageT<I>::get();
   }
 
   template <int I>
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index c7777a9..e67529e 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -18,6 +18,7 @@
 #include <cassert>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <tuple>
 #include <type_traits>
 #include <utility>
@@ -56,8 +57,11 @@
   using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
   assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
          "allocator does not respect alignment");
   return p;
@@ -72,8 +76,11 @@
   using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  AT::deallocate(mem_alloc, static_cast<M*>(p),
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  AT::deallocate(my_mem_alloc, static_cast<M*>(p),
                  (n + sizeof(M) - 1) / sizeof(M));
 }
 
@@ -352,6 +359,20 @@
     return slot->value;
   }
 
+  // When C++17 is available, we can use std::launder to provide mutable
+  // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+  static K& mutable_key(slot_type* slot) {
+    // Still check for kMutableKeys so that we can avoid calling std::launder
+    // unless necessary because it can interfere with optimizations.
+    return kMutableKeys::value ? slot->key
+                               : *std::launder(const_cast<K*>(
+                                     std::addressof(slot->value.first)));
+  }
+#else  // !(defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606)
+  static const K& mutable_key(slot_type* slot) { return key(slot); }
+#endif
+
   static const K& key(const slot_type* slot) {
     return kMutableKeys::value ? slot->key : slot->value.first;
   }
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index 75c4db6..59cc5aa 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -41,8 +41,10 @@
 }  // namespace
 
 std::mt19937_64* GetSharedRng() {
-  RandomDeviceSeedSeq seed_seq;
-  static auto* rng = new std::mt19937_64(seed_seq);
+  static auto* rng = [] {
+    RandomDeviceSeedSeq seed_seq;
+    return new std::mt19937_64(seed_seq);
+  }();
   return rng;
 }
 
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index 3e1209c..46c97b1 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -17,6 +17,7 @@
 
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <type_traits>
 #include <utility>
 
@@ -29,15 +30,34 @@
 // Defines how slots are initialized/destroyed/moved.
 template <class Policy, class = void>
 struct hash_policy_traits {
+  // The type of the keys stored in the hashtable.
+  using key_type = typename Policy::key_type;
+
  private:
   struct ReturnKey {
-    // We return `Key` here.
+    // When C++17 is available, we can use std::launder to provide mutable
+    // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+    template <class Key,
+              absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
+    static key_type& Impl(Key&& k, int) {
+      return *std::launder(
+          const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
+    }
+#endif
+
+    template <class Key>
+    static Key Impl(Key&& k, char) {
+      return std::forward<Key>(k);
+    }
+
     // When Key=T&, we forward the lvalue reference.
     // When Key=T, we return by value to avoid a dangling reference.
     // eg, for string_hash_map.
     template <class Key, class... Args>
-    Key operator()(Key&& k, const Args&...) const {
-      return std::forward<Key>(k);
+    auto operator()(Key&& k, const Args&...) const
+        -> decltype(Impl(std::forward<Key>(k), 0)) {
+      return Impl(std::forward<Key>(k), 0);
     }
   };
 
@@ -52,9 +72,6 @@
   // The actual object stored in the hash table.
   using slot_type = typename Policy::slot_type;
 
-  // The type of the keys stored in the hashtable.
-  using key_type = typename Policy::key_type;
-
   // The argument type for insertions into the hashtable. This is different
   // from value_type for increased performance. See initializer_list constructor
   // and insert() member functions for more details.
@@ -156,7 +173,7 @@
   // Returns the "key" portion of the slot.
   // Used for node handle manipulation.
   template <class P = Policy>
-  static auto key(slot_type* slot)
+  static auto mutable_key(slot_type* slot)
       -> decltype(P::apply(ReturnKey(), element(slot))) {
     return P::apply(ReturnKey(), element(slot));
   }
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index 886524f..e4484fb 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -67,6 +67,7 @@
   capacity.store(0, std::memory_order_relaxed);
   size.store(0, std::memory_order_relaxed);
   num_erases.store(0, std::memory_order_relaxed);
+  num_rehashes.store(0, std::memory_order_relaxed);
   max_probe_length.store(0, std::memory_order_relaxed);
   total_probe_length.store(0, std::memory_order_relaxed);
   hashes_bitwise_or.store(0, std::memory_order_relaxed);
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index 308119c..394348d 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -73,6 +73,7 @@
   std::atomic<size_t> capacity;
   std::atomic<size_t> size;
   std::atomic<size_t> num_erases;
+  std::atomic<size_t> num_rehashes;
   std::atomic<size_t> max_probe_length;
   std::atomic<size_t> total_probe_length;
   std::atomic<size_t> hashes_bitwise_or;
@@ -105,6 +106,11 @@
 #endif
   info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
   info->num_erases.store(0, std::memory_order_relaxed);
+  // There is only one concurrent writer, so `load` then `store` is sufficient
+  // instead of using `fetch_add`.
+  info->num_rehashes.store(
+      1 + info->num_rehashes.load(std::memory_order_relaxed),
+      std::memory_order_relaxed);
 }
 
 inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
@@ -113,7 +119,8 @@
   info->capacity.store(capacity, std::memory_order_relaxed);
   if (size == 0) {
     // This is a clear, reset the total/num_erases too.
-    RecordRehashSlow(info, 0);
+    info->total_probe_length.store(0, std::memory_order_relaxed);
+    info->num_erases.store(0, std::memory_order_relaxed);
   }
 }
 
@@ -122,12 +129,21 @@
 
 inline void RecordEraseSlow(HashtablezInfo* info) {
   info->size.fetch_sub(1, std::memory_order_relaxed);
-  info->num_erases.fetch_add(1, std::memory_order_relaxed);
+  // There is only one concurrent writer, so `load` then `store` is sufficient
+  // instead of using `fetch_add`.
+  info->num_erases.store(
+      1 + info->num_erases.load(std::memory_order_relaxed),
+      std::memory_order_relaxed);
 }
 
 HashtablezInfo* SampleSlow(int64_t* next_sample);
 void UnsampleSlow(HashtablezInfo* info);
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 class HashtablezInfoHandle {
  public:
   explicit HashtablezInfoHandle() : info_(nullptr) {}
@@ -179,14 +195,27 @@
   friend class HashtablezInfoHandlePeer;
   HashtablezInfo* info_;
 };
+#else
+// Ensure that when Hashtablez is turned off at compile time, HashtablezInfo can
+// be removed by the linker, in order to reduce the binary size.
+class HashtablezInfoHandle {
+ public:
+  explicit HashtablezInfoHandle() = default;
+  explicit HashtablezInfoHandle(std::nullptr_t) {}
 
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
-#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+  inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
+  inline void RecordRehash(size_t /*total_probe_length*/) {}
+  inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {}
+  inline void RecordErase() {}
+
+  friend inline void swap(HashtablezInfoHandle& /*lhs*/,
+                          HashtablezInfoHandle& /*rhs*/) {}
+};
 #endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
-#endif  // ABSL_PER_THREAD_TLS
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 // Returns an RAII sampling handle that manages registration and unregistation
 // with the global sampler.
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index b4c4ff9..8d10a1e 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -38,6 +38,7 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 class HashtablezInfoHandlePeer {
  public:
   static bool IsSampled(const HashtablezInfoHandle& h) {
@@ -46,6 +47,13 @@
 
   static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }
 };
+#else
+class HashtablezInfoHandlePeer {
+ public:
+  static bool IsSampled(const HashtablezInfoHandle&) { return false; }
+  static HashtablezInfo* GetInfo(HashtablezInfoHandle*) { return nullptr; }
+};
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 namespace {
 using ::absl::synchronization_internal::ThreadPool;
@@ -76,6 +84,7 @@
   EXPECT_EQ(info.capacity.load(), 0);
   EXPECT_EQ(info.size.load(), 0);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 0);
   EXPECT_EQ(info.max_probe_length.load(), 0);
   EXPECT_EQ(info.total_probe_length.load(), 0);
   EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
@@ -95,6 +104,7 @@
   EXPECT_EQ(info.capacity.load(), 0);
   EXPECT_EQ(info.size.load(), 0);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 0);
   EXPECT_EQ(info.max_probe_length.load(), 0);
   EXPECT_EQ(info.total_probe_length.load(), 0);
   EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
@@ -167,9 +177,10 @@
   EXPECT_EQ(info.size.load(), 2);
   EXPECT_EQ(info.total_probe_length.load(), 3);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 1);
 }
 
-#if defined(ABSL_HASHTABLEZ_SAMPLE)
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 TEST(HashtablezSamplerTest, SmallSampleParameter) {
   SetHashtablezEnabled(true);
   SetHashtablezSampleParameter(100);
@@ -213,7 +224,6 @@
   }
   EXPECT_NEAR(sample_rate, 0.01, 0.005);
 }
-#endif
 
 TEST(HashtablezSamplerTest, Handle) {
   auto& sampler = HashtablezSampler::Global();
@@ -243,6 +253,8 @@
   });
   EXPECT_FALSE(found);
 }
+#endif
+
 
 TEST(HashtablezSamplerTest, Registration) {
   HashtablezSampler sampler;
diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc
index 757272f..1d7158f 100644
--- a/absl/container/internal/layout_test.cc
+++ b/absl/container/internal/layout_test.cc
@@ -128,8 +128,10 @@
   {
     using L = Layout<int32_t, int32_t>;
     SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
-    SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial())::ElementTypes>();
-    SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial(0))::ElementTypes>();
+    SameType<std::tuple<int32_t, int32_t>,
+             decltype(L::Partial())::ElementTypes>();
+    SameType<std::tuple<int32_t, int32_t>,
+             decltype(L::Partial(0))::ElementTypes>();
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
@@ -368,18 +370,21 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
   }
   {
     using L = Layout<int32_t, int32_t>;
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
-    EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
     EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
     EXPECT_EQ(12,
-              Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+    EXPECT_EQ(
+        12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
     EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
   }
@@ -387,39 +392,44 @@
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
-    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
-    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
+    EXPECT_EQ(
+        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
     EXPECT_EQ(8,
               Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
     EXPECT_EQ(
-        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+        4,
+        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(
         8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(
@@ -428,7 +438,8 @@
         24,
         Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(
-        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+        8,
+        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -439,75 +450,78 @@
   alignas(max_align_t) const unsigned char p[100] = {};
   {
     using L = Layout<int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
-    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+        0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+        0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+                                 L::Partial(0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         0,
         Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+                                 L::Partial(1, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         8,
         Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+                                 L::Partial(5, 3).Pointer<int32_t>(p))));
     EXPECT_EQ(
         24,
         Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+                                 L::Partial(0, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<const Int128*>(
                                  L::Partial(0, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        4,
-        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+                                 L::Partial(1, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(8, Distance(p, Type<const Int128*>(
                                  L::Partial(1, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(24, Distance(p, Type<const Int128*>(
                                   L::Partial(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        8,
-        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+                                 L::Partial(5, 3, 1).Pointer<int32_t>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
   }
 }
 
@@ -548,15 +562,18 @@
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -568,48 +585,61 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(8,
               Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(
         24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
@@ -790,67 +820,72 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
   }
   {
     using L = Layout<int32_t, int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
     EXPECT_EQ(
         12,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
-    EXPECT_EQ(12,
-              Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+               p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
     EXPECT_EQ(
         0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        8,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+               p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
@@ -864,7 +899,8 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         4,
         Distance(
@@ -878,7 +914,8 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(
@@ -890,12 +927,14 @@
             p,
             Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+        0,
+        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
     EXPECT_EQ(
-        8, Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+        8,
+        Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
   }
 }
 
@@ -906,98 +945,94 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
+        0,
+        Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
-            Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(
-            p,
-            Type<Span<const int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        8,
-        Distance(
-            p,
-            Type<Span<const int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+            Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
-            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+            Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p))
+        Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
                         .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(0, 0).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
+                        .data()));
+    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(1, 0).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
+                        .data()));
+    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(5, 3).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(0, 0, 0).Slice<int8_t>(p))
+                                 .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(0, 0, 0).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
                                  L::Partial(0, 0, 0).Slice<Int128>(p))
                                  .data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p,
-            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p))
-                        .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(1, 0, 0).Slice<int8_t>(p))
+                                 .data()));
+    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(1, 0, 0).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
                                  L::Partial(1, 0, 0).Slice<Int128>(p))
                                  .data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p,
-            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(5, 3, 1).Slice<int8_t>(p))
+                                 .data()));
     EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
                                   L::Partial(5, 3, 1).Slice<Int128>(p))
                                   .data()));
-    EXPECT_EQ(
-        8,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p))
-                        .data()));
+    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(5, 3, 1).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+        Distance(p,
+                 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p,
                  Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        8, Distance(
-               p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+        8,
+        Distance(
+            p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
   }
 }
 
@@ -1005,18 +1040,19 @@
   alignas(max_align_t) unsigned char p[100];
   {
     using L = Layout<int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
   }
   {
     using L = Layout<int32_t, int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
     EXPECT_EQ(
         12,
         Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
@@ -1025,55 +1061,63 @@
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        4, Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        8, Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
+        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
     EXPECT_EQ(
         0, Distance(
                p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        4,
-        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
+        4, Distance(
+               p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
     EXPECT_EQ(
         8, Distance(
                p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24, Distance(
                 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
     EXPECT_EQ(
-        8,
-        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+        8, Distance(
+               p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(24,
               Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
-    EXPECT_EQ(8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+    EXPECT_EQ(8,
+              Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
   }
 }
 
@@ -1082,66 +1126,84 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4, Distance(
-               p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        8, Distance(
-               p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
+            p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(
+            p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(
+            p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
             Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         4,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         8,
         Distance(
             p,
             Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(
@@ -1150,14 +1212,16 @@
     EXPECT_EQ(
         8,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+            p,
+            Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+        8,
+        Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
   }
 }
 
@@ -1256,17 +1320,17 @@
   }
   {
     const auto x = L::Partial(1, 2, 3);
-    EXPECT_THAT(
-        (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
-        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
-              IsSameSlice(x.Slice<2>(p))));
+    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+                    x.Slices(p))),
+                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+                      IsSameSlice(x.Slice<2>(p))));
   }
   {
     const L x(1, 2, 3);
-    EXPECT_THAT(
-        (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
-        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
-              IsSameSlice(x.Slice<2>(p))));
+    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+                    x.Slices(p))),
+                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+                      IsSameSlice(x.Slice<2>(p))));
   }
 }
 
@@ -1398,7 +1462,8 @@
               x.DebugString());
   }
   {
-    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
+    constexpr auto x =
+        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
         "@16" +
@@ -1406,7 +1471,8 @@
         x.DebugString());
   }
   {
-    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
+    constexpr auto x =
+        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
         "@16" +
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 919ac07..2f744a6 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -27,7 +27,7 @@
 
 // Returns "random" seed.
 inline size_t RandomSeed() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   static thread_local size_t counter = 0;
   size_t value = ++counter;
 #else   // ABSL_HAVE_THREAD_LOCAL
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 48a1a8c..67364b7 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -122,6 +122,16 @@
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+template <typename AllocType>
+void SwapAlloc(AllocType& lhs, AllocType& rhs,
+               std::true_type /* propagate_on_container_swap */) {
+  using std::swap;
+  swap(lhs, rhs);
+}
+template <typename AllocType>
+void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
+               std::false_type /* propagate_on_container_swap */) {}
+
 template <size_t Width>
 class probe_seq {
  public:
@@ -169,10 +179,14 @@
 
 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
 template <class T>
-constexpr bool IsNoThrowSwappable() {
+constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
   using std::swap;
   return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
 }
+template <class T>
+constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
+  return false;
+}
 
 template <typename T>
 int TrailingZeros(T x) {
@@ -1051,7 +1065,9 @@
   }
 
   iterator insert(const_iterator, node_type&& node) {
-    return insert(std::move(node)).first;
+    auto res = insert(std::move(node));
+    node = std::move(res.node);
+    return res.position;
   }
 
   // This overload kicks in if we can deduce the key from args. This enables us
@@ -1231,8 +1247,8 @@
 
   void swap(raw_hash_set& that) noexcept(
       IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
-      (!AllocTraits::propagate_on_container_swap::value ||
-       IsNoThrowSwappable<allocator_type>())) {
+      IsNoThrowSwappable<allocator_type>(
+          typename AllocTraits::propagate_on_container_swap{})) {
     using std::swap;
     swap(ctrl_, that.ctrl_);
     swap(slots_, that.slots_);
@@ -1242,12 +1258,8 @@
     swap(hash_ref(), that.hash_ref());
     swap(eq_ref(), that.eq_ref());
     swap(infoz_, that.infoz_);
-    if (AllocTraits::propagate_on_container_swap::value) {
-      swap(alloc_ref(), that.alloc_ref());
-    } else {
-      // If the allocators do not compare equal it is officially undefined
-      // behavior. We choose to do nothing.
-    }
+    SwapAlloc(alloc_ref(), that.alloc_ref(),
+              typename AllocTraits::propagate_on_container_swap{});
   }
 
   void rehash(size_t n) {
@@ -1317,6 +1329,7 @@
       }
       if (ABSL_PREDICT_TRUE(g.MatchEmpty())) return end();
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
   }
   template <class K = key_type>
@@ -1668,8 +1681,8 @@
 #endif
         return {seq.offset(mask.LowestBitSet()), seq.index()};
       }
-      assert(seq.index() < capacity_ && "full table!");
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
   }
 
@@ -1700,6 +1713,7 @@
       }
       if (ABSL_PREDICT_TRUE(g.MatchEmpty())) break;
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
     return {prepare_insert(hash), true};
   }
diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc
index 7ac4b9f..e73f53f 100644
--- a/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -424,6 +424,81 @@
   EXPECT_EQ(0, it->num_copies());
 }
 
+// This allocator is similar to std::pmr::polymorphic_allocator.
+// Note the disabled assignment.
+template <class T>
+class PAlloc {
+  template <class>
+  friend class PAlloc;
+
+ public:
+  // types
+  using value_type = T;
+
+  // traits
+  using propagate_on_container_swap = std::false_type;
+
+  PAlloc() noexcept = default;
+  explicit PAlloc(size_t id) noexcept : id_(id) {}
+  PAlloc(const PAlloc&) noexcept = default;
+  PAlloc& operator=(const PAlloc&) noexcept = delete;
+
+  template <class U>
+  PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {}  // NOLINT
+
+  template <class U>
+  struct rebind {
+    using other = PAlloc<U>;
+  };
+
+  constexpr PAlloc select_on_container_copy_construction() const { return {}; }
+
+  // public member functions
+  T* allocate(size_t) { return new T; }
+  void deallocate(T* p, size_t) { delete p; }
+
+  friend bool operator==(const PAlloc& a, const PAlloc& b) {
+    return a.id_ == b.id_;
+  }
+  friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); }
+
+ private:
+  size_t id_ = std::numeric_limits<size_t>::max();
+};
+
+// This doesn't compile with GCC 5.4 and 5.5 due to a bug in noexcept handing.
+#if !defined(__GNUC__) || __GNUC__ != 5 || (__GNUC_MINOR__ != 4 && \
+    __GNUC_MINOR__ != 5)
+TEST(NoPropagateOn, Swap) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  swap(t1, t2);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+#endif
+
+TEST(NoPropagateOn, CopyConstruct) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(t1);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA());
+}
+
+TEST(NoPropagateOn, Assignment) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  t1 = t2;
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index e327930..33d2773 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -847,7 +847,8 @@
 std::vector<int64_t> CollectBadMergeKeys(size_t N) {
   static constexpr int kGroupSize = Group::kWidth - 1;
 
-  auto topk_range = [](size_t b, size_t e, IntTable* t) -> std::vector<int64_t> {
+  auto topk_range = [](size_t b, size_t e,
+                       IntTable* t) -> std::vector<int64_t> {
     for (size_t i = b; i != e; ++i) {
       t->emplace(i);
     }
@@ -1001,8 +1002,8 @@
 // 1. Create new table and reserve it to keys.size() * 2
 // 2. Insert all keys xored with seed
 // 3. Collect ProbeStats from final table.
-ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector<int64_t>& keys,
-                                                size_t num_iters) {
+ProbeStats CollectProbeStatsOnKeysXoredWithSeed(
+    const std::vector<int64_t>& keys, size_t num_iters) {
   const size_t reserve_size = keys.size() * 2;
 
   ProbeStats stats;
@@ -1710,6 +1711,26 @@
   EXPECT_FALSE(node);
 }
 
+TEST(Nodes, HintInsert) {
+  IntTable t = {1, 2, 3};
+  auto node = t.extract(1);
+  EXPECT_THAT(t, UnorderedElementsAre(2, 3));
+  auto it = t.insert(t.begin(), std::move(node));
+  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+  EXPECT_EQ(*it, 1);
+  EXPECT_FALSE(node);
+
+  node = t.extract(2);
+  EXPECT_THAT(t, UnorderedElementsAre(1, 3));
+  // reinsert 2 to make the next insert fail.
+  t.insert(2);
+  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+  it = t.insert(t.begin(), std::move(node));
+  EXPECT_EQ(*it, 2);
+  // The node was not emptied by the insert call.
+  EXPECT_TRUE(node);
+}
+
 IntTable MakeSimpleTable(size_t size) {
   IntTable t;
   while (t.size() < size) t.insert(t.size());
@@ -1796,7 +1817,7 @@
   EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
 }
 
-#if defined(ABSL_HASHTABLEZ_SAMPLE)
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 TEST(RawHashSamplerTest, Sample) {
   // Enable the feature even if the prod default is off.
   SetHashtablezEnabled(true);
@@ -1817,7 +1838,7 @@
   EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
               0.01, 0.005);
 }
-#endif  // ABSL_HASHTABLEZ_SAMPLER
+#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
 
 TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
   // Enable the feature even if the prod default is off.
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 174b971..7a39f62 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -225,7 +225,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // node_hash_map::insert()
@@ -374,6 +375,11 @@
   //   key value and returns a node handle owning that extracted data. If the
   //   `node_hash_map` does not contain an element with a matching key, this
   //   function returns an empty node handle.
+  //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
   using Base::extract;
 
   // node_hash_map::merge()
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index 5d74b81..8f59a1e 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -254,6 +254,21 @@
   }
 }
 
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(NodeHashMap, NodeHandleMutableKeyAccess) {
+  node_hash_map<std::string, std::string> map;
+
+  map["key1"] = "mapped";
+
+  auto nh = map.extract(map.begin());
+  nh.key().resize(3);
+  map.insert(std::move(nh));
+
+  EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 56bab5c..56ce3b6 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -217,7 +217,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // node_hash_set::insert()
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
index 97bd283..51742c9 100644
--- a/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -5,47 +5,6 @@
 
 list(APPEND ABSL_CLANG_CL_FLAGS
     "/W3"
-    "-Wno-c++98-compat-pedantic"
-    "-Wno-conversion"
-    "-Wno-covered-switch-default"
-    "-Wno-deprecated"
-    "-Wno-disabled-macro-expansion"
-    "-Wno-double-promotion"
-    "-Wno-comma"
-    "-Wno-extra-semi"
-    "-Wno-extra-semi-stmt"
-    "-Wno-packed"
-    "-Wno-padded"
-    "-Wno-sign-compare"
-    "-Wno-float-conversion"
-    "-Wno-float-equal"
-    "-Wno-format-nonliteral"
-    "-Wno-gcc-compat"
-    "-Wno-global-constructors"
-    "-Wno-exit-time-destructors"
-    "-Wno-non-modular-include-in-module"
-    "-Wno-old-style-cast"
-    "-Wno-range-loop-analysis"
-    "-Wno-reserved-id-macro"
-    "-Wno-shorten-64-to-32"
-    "-Wno-switch-enum"
-    "-Wno-thread-safety-negative"
-    "-Wno-unknown-warning-option"
-    "-Wno-unreachable-code"
-    "-Wno-unused-macros"
-    "-Wno-weak-vtables"
-    "-Wno-zero-as-null-pointer-constant"
-    "-Wbitfield-enum-conversion"
-    "-Wbool-conversion"
-    "-Wconstant-conversion"
-    "-Wenum-conversion"
-    "-Wint-conversion"
-    "-Wliteral-conversion"
-    "-Wnon-literal-null-conversion"
-    "-Wnull-conversion"
-    "-Wobjc-literal-conversion"
-    "-Wno-sign-conversion"
-    "-Wstring-conversion"
     "/DNOMINMAX"
     "/DWIN32_LEAN_AND_MEAN"
     "/D_CRT_SECURE_NO_WARNINGS"
@@ -78,6 +37,7 @@
     "-Wextra"
     "-Wcast-qual"
     "-Wconversion-null"
+    "-Wformat-security"
     "-Wmissing-declarations"
     "-Woverlength-strings"
     "-Wpointer-arith"
@@ -87,8 +47,6 @@
     "-Wvarargs"
     "-Wvla"
     "-Wwrite-strings"
-    "-Wno-missing-field-initializers"
-    "-Wno-sign-compare"
     "-DNOMINMAX"
 )
 
@@ -105,48 +63,36 @@
 list(APPEND ABSL_LLVM_FLAGS
     "-Wall"
     "-Wextra"
-    "-Weverything"
-    "-Wno-c++98-compat-pedantic"
-    "-Wno-conversion"
-    "-Wno-covered-switch-default"
-    "-Wno-deprecated"
-    "-Wno-disabled-macro-expansion"
-    "-Wno-double-promotion"
-    "-Wno-comma"
-    "-Wno-extra-semi"
-    "-Wno-extra-semi-stmt"
-    "-Wno-packed"
-    "-Wno-padded"
-    "-Wno-sign-compare"
-    "-Wno-float-conversion"
-    "-Wno-float-equal"
-    "-Wno-format-nonliteral"
-    "-Wno-gcc-compat"
-    "-Wno-global-constructors"
-    "-Wno-exit-time-destructors"
-    "-Wno-non-modular-include-in-module"
-    "-Wno-old-style-cast"
-    "-Wno-range-loop-analysis"
-    "-Wno-reserved-id-macro"
-    "-Wno-shorten-64-to-32"
-    "-Wno-switch-enum"
-    "-Wno-thread-safety-negative"
-    "-Wno-unknown-warning-option"
-    "-Wno-unreachable-code"
-    "-Wno-unused-macros"
-    "-Wno-weak-vtables"
-    "-Wno-zero-as-null-pointer-constant"
-    "-Wbitfield-enum-conversion"
-    "-Wbool-conversion"
-    "-Wconstant-conversion"
-    "-Wenum-conversion"
-    "-Wint-conversion"
+    "-Wcast-qual"
+    "-Wconversion"
+    "-Wfloat-overflow-conversion"
+    "-Wfloat-zero-conversion"
+    "-Wfor-loop-analysis"
+    "-Wformat-security"
+    "-Wgnu-redeclared-enum"
+    "-Winfinite-recursion"
     "-Wliteral-conversion"
-    "-Wnon-literal-null-conversion"
-    "-Wnull-conversion"
-    "-Wobjc-literal-conversion"
-    "-Wno-sign-conversion"
+    "-Wmissing-declarations"
+    "-Woverlength-strings"
+    "-Wpointer-arith"
+    "-Wself-assign"
+    "-Wshadow"
     "-Wstring-conversion"
+    "-Wtautological-overlap-compare"
+    "-Wundef"
+    "-Wuninitialized"
+    "-Wunreachable-code"
+    "-Wunused-comparison"
+    "-Wunused-local-typedefs"
+    "-Wunused-result"
+    "-Wvla"
+    "-Wwrite-strings"
+    "-Wno-float-conversion"
+    "-Wno-implicit-float-conversion"
+    "-Wno-implicit-int-float-conversion"
+    "-Wno-implicit-int-conversion"
+    "-Wno-shorten-64-to-32"
+    "-Wno-sign-conversion"
     "-DNOMINMAX"
 )
 
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
index bcdd61e..6707488 100644
--- a/absl/copts/GENERATED_copts.bzl
+++ b/absl/copts/GENERATED_copts.bzl
@@ -6,47 +6,6 @@
 
 ABSL_CLANG_CL_FLAGS = [
     "/W3",
-    "-Wno-c++98-compat-pedantic",
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    "-Wno-sign-compare",
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    "-Wno-gcc-compat",
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    "-Wno-zero-as-null-pointer-constant",
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
     "/DNOMINMAX",
     "/DWIN32_LEAN_AND_MEAN",
     "/D_CRT_SECURE_NO_WARNINGS",
@@ -79,6 +38,7 @@
     "-Wextra",
     "-Wcast-qual",
     "-Wconversion-null",
+    "-Wformat-security",
     "-Wmissing-declarations",
     "-Woverlength-strings",
     "-Wpointer-arith",
@@ -88,8 +48,6 @@
     "-Wvarargs",
     "-Wvla",
     "-Wwrite-strings",
-    "-Wno-missing-field-initializers",
-    "-Wno-sign-compare",
     "-DNOMINMAX",
 ]
 
@@ -106,48 +64,36 @@
 ABSL_LLVM_FLAGS = [
     "-Wall",
     "-Wextra",
-    "-Weverything",
-    "-Wno-c++98-compat-pedantic",
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    "-Wno-sign-compare",
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    "-Wno-gcc-compat",
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    "-Wno-zero-as-null-pointer-constant",
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
+    "-Wcast-qual",
+    "-Wconversion",
+    "-Wfloat-overflow-conversion",
+    "-Wfloat-zero-conversion",
+    "-Wfor-loop-analysis",
+    "-Wformat-security",
+    "-Wgnu-redeclared-enum",
+    "-Winfinite-recursion",
     "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
+    "-Wmissing-declarations",
+    "-Woverlength-strings",
+    "-Wpointer-arith",
+    "-Wself-assign",
+    "-Wshadow",
     "-Wstring-conversion",
+    "-Wtautological-overlap-compare",
+    "-Wundef",
+    "-Wuninitialized",
+    "-Wunreachable-code",
+    "-Wunused-comparison",
+    "-Wunused-local-typedefs",
+    "-Wunused-result",
+    "-Wvla",
+    "-Wwrite-strings",
+    "-Wno-float-conversion",
+    "-Wno-implicit-float-conversion",
+    "-Wno-implicit-int-float-conversion",
+    "-Wno-implicit-int-conversion",
+    "-Wno-shorten-64-to-32",
+    "-Wno-sign-conversion",
     "-DNOMINMAX",
 ]
 
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
index ff9a5ea..4d34254 100644
--- a/absl/copts/configure_copts.bzl
+++ b/absl/copts/configure_copts.bzl
@@ -23,15 +23,13 @@
 
 ABSL_DEFAULT_COPTS = select({
     "//absl:windows": ABSL_MSVC_FLAGS,
-    "//absl:llvm_compiler": ABSL_LLVM_FLAGS,
+    "//absl:clang_compiler": ABSL_LLVM_FLAGS,
     "//conditions:default": ABSL_GCC_FLAGS,
 })
 
-# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
-# to their (included header) dependencies and fail to build outside absl
 ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({
     "//absl:windows": ABSL_MSVC_TEST_FLAGS,
-    "//absl:llvm_compiler": ABSL_LLVM_TEST_FLAGS,
+    "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
     "//conditions:default": ABSL_GCC_TEST_FLAGS,
 })
 
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
index a3437c1..cf52981 100644
--- a/absl/copts/copts.py
+++ b/absl/copts/copts.py
@@ -16,77 +16,6 @@
     "/W3",
 ]
 
-LLVM_BIG_WARNING_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Weverything",
-]
-
-# Docs on single flags is preceded by a comment.
-# Docs on groups of flags is preceded by ###.
-LLVM_DISABLE_WARNINGS_FLAGS = [
-    # Abseil does not support C++98
-    "-Wno-c++98-compat-pedantic",
-    # Turns off all implicit conversion warnings. Most are re-enabled below.
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    ###
-    # Turned off as they include valid C++ code.
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    ###
-    # Google style does not use unsigned integers, though STL containers
-    # have unsigned types.
-    "-Wno-sign-compare",
-    ###
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    # Too aggressive: warns on Clang extensions enclosed in Clang-only
-    # compilation paths.
-    "-Wno-gcc-compat",
-    ###
-    # Some internal globals are necessary. Don't do this at home.
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    ###
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    # Warns on preferred usage of non-POD types such as string_view
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    # Causes warnings on include guards
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    # Causes warnings on usage of types/compare.h comparison operators.
-    "-Wno-zero-as-null-pointer-constant",
-    ###
-    # Implicit conversion warnings turned off by -Wno-conversion
-    # which are re-enabled below.
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
-]
-
 LLVM_TEST_DISABLE_WARNINGS_FLAGS = [
     "-Wno-c99-extensions",
     "-Wno-deprecated-declarations",
@@ -125,6 +54,7 @@
         "-Wextra",
         "-Wcast-qual",
         "-Wconversion-null",
+        "-Wformat-security",
         "-Wmissing-declarations",
         "-Woverlength-strings",
         "-Wpointer-arith",
@@ -134,13 +64,6 @@
         "-Wvarargs",
         "-Wvla",  # variable-length array
         "-Wwrite-strings",
-        # gcc-4.x has spurious missing field initializer warnings.
-        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
-        # Remove when gcc-4.x is no longer supported.
-        "-Wno-missing-field-initializers",
-        # Google style does not use unsigned integers, though STL containers
-        # have unsigned types.
-        "-Wno-sign-compare",
         # Don't define min and max macros (Build on Windows using gcc)
         "-DNOMINMAX",
     ],
@@ -153,15 +76,48 @@
         "-Wno-unused-parameter",
         "-Wno-unused-private-field",
     ],
-    "ABSL_LLVM_FLAGS":
-        LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + [
-            # Don't define min and max macros (Build on Windows using clang)
-            "-DNOMINMAX",
-        ],
+    "ABSL_LLVM_FLAGS": [
+        "-Wall",
+        "-Wextra",
+        "-Wcast-qual",
+        "-Wconversion",
+        "-Wfloat-overflow-conversion",
+        "-Wfloat-zero-conversion",
+        "-Wfor-loop-analysis",
+        "-Wformat-security",
+        "-Wgnu-redeclared-enum",
+        "-Winfinite-recursion",
+        "-Wliteral-conversion",
+        "-Wmissing-declarations",
+        "-Woverlength-strings",
+        "-Wpointer-arith",
+        "-Wself-assign",
+        "-Wshadow",
+        "-Wstring-conversion",
+        "-Wtautological-overlap-compare",
+        "-Wundef",
+        "-Wuninitialized",
+        "-Wunreachable-code",
+        "-Wunused-comparison",
+        "-Wunused-local-typedefs",
+        "-Wunused-result",
+        "-Wvla",
+        "-Wwrite-strings",
+        # Warnings that are enabled by group warning flags like -Wall that we
+        # explicitly disable.
+        "-Wno-float-conversion",
+        "-Wno-implicit-float-conversion",
+        "-Wno-implicit-int-float-conversion",
+        "-Wno-implicit-int-conversion",
+        "-Wno-shorten-64-to-32",
+        "-Wno-sign-conversion",
+        # Don't define min and max macros (Build on Windows using clang)
+        "-DNOMINMAX",
+    ],
     "ABSL_LLVM_TEST_FLAGS":
         LLVM_TEST_DISABLE_WARNINGS_FLAGS,
     "ABSL_CLANG_CL_FLAGS":
-        (MSVC_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES),
+        (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES),
     "ABSL_CLANG_CL_TEST_FLAGS":
         LLVM_TEST_DISABLE_WARNINGS_FLAGS,
     "ABSL_MSVC_FLAGS":
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index 9098ca4..cd6e454 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -26,7 +26,7 @@
     default_visibility = ["//visibility:public"],
 )
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "stacktrace",
@@ -239,7 +239,7 @@
 # These targets exists for use in tests only, explicitly configuring the
 # LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan.
 ABSL_LSAN_LINKOPTS = select({
-    "//absl:llvm_compiler": ["-fsanitize=leak"],
+    "//absl:clang_compiler": ["-fsanitize=leak"],
     "//conditions:default": [],
 })
 
@@ -249,7 +249,7 @@
     srcs = ["leak_check.cc"],
     hdrs = ["leak_check.h"],
     copts = select({
-        "//absl:llvm_compiler": ["-DLEAK_SANITIZER"],
+        "//absl:clang_compiler": ["-DLEAK_SANITIZER"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -276,7 +276,7 @@
     name = "leak_check_test",
     srcs = ["leak_check_test.cc"],
     copts = select({
-        "//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
+        "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc
index 6537606..329c285 100644
--- a/absl/debugging/internal/address_is_readable.cc
+++ b/absl/debugging/internal/address_is_readable.cc
@@ -68,6 +68,7 @@
 // unimplemented.
 // This is a namespace-scoped variable for correct zero-initialization.
 static std::atomic<uint64_t> pid_and_fds;  // initially 0, an invalid pid.
+
 bool AddressIsReadable(const void *addr) {
   absl::base_internal::ErrnoSaver errno_saver;
   // We test whether a byte is readable by using write().  Normally, this would
@@ -86,7 +87,7 @@
     int pid;
     int read_fd;
     int write_fd;
-    uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+    uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
     Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
     while (current_pid != pid) {
       int p[2];
@@ -98,13 +99,13 @@
       fcntl(p[1], F_SETFD, FD_CLOEXEC);
       uint64_t new_pid_and_fds = Pack(current_pid, p[0], p[1]);
       if (pid_and_fds.compare_exchange_strong(
-              local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
+              local_pid_and_fds, new_pid_and_fds, std::memory_order_release,
               std::memory_order_relaxed)) {
         local_pid_and_fds = new_pid_and_fds;  // fds exposed to other threads
       } else {  // fds not exposed to other threads; we can close them.
         close(p[0]);
         close(p[1]);
-        local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+        local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
       }
       Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
     }
@@ -124,7 +125,7 @@
       // If pid_and_fds contains the problematic file descriptors we just used,
       // this call will forget them, and the loop will try again.
       pid_and_fds.compare_exchange_strong(local_pid_and_fds, 0,
-                                          std::memory_order_relaxed,
+                                          std::memory_order_release,
                                           std::memory_order_relaxed);
     }
   } while (errno == EBADF);
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 87f13e5..46cdb67 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1082,20 +1082,28 @@
   return false;
 }
 
-// <ctor-dtor-name> ::= C1 | C2 | C3
+// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2
+// <base-class-type>
 //                  ::= D0 | D1 | D2
 // # GCC extensions: "unified" constructor/destructor.  See
-// # https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
+// #
+// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
 //                  ::= C4 | D4
 static bool ParseCtorDtorName(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "1234")) {
-    const char *const prev_name = state->out + state->parse_state.prev_name_idx;
-    MaybeAppendWithLength(state, prev_name,
-                          state->parse_state.prev_name_length);
-    return true;
+  if (ParseOneCharToken(state, 'C')) {
+    if (ParseCharClass(state, "1234")) {
+      const char *const prev_name =
+          state->out + state->parse_state.prev_name_idx;
+      MaybeAppendWithLength(state, prev_name,
+                            state->parse_state.prev_name_length);
+      return true;
+    } else if (ParseOneCharToken(state, 'I') && ParseCharClass(state, "12") &&
+               ParseClassEnumType(state)) {
+      return true;
+    }
   }
   state->parse_state = copy;
 
@@ -1265,12 +1273,40 @@
   return false;
 }
 
-// <function-type> ::= F [Y] <bare-function-type> [O] E
+//  <exception-spec> ::= Do                # non-throwing
+//                                           exception-specification (e.g.,
+//                                           noexcept, throw())
+//                   ::= DO <expression> E # computed (instantiation-dependent)
+//                                           noexcept
+//                   ::= Dw <type>+ E      # dynamic exception specification
+//                                           with instantiation-dependent types
+static bool ParseExceptionSpec(State *state) {
+  ComplexityGuard guard(state);
+  if (guard.IsTooComplex()) return false;
+
+  if (ParseTwoCharToken(state, "Do")) return true;
+
+  ParseState copy = state->parse_state;
+  if (ParseTwoCharToken(state, "DO") && ParseExpression(state) &&
+      ParseOneCharToken(state, 'E')) {
+    return true;
+  }
+  state->parse_state = copy;
+  if (ParseTwoCharToken(state, "Dw") && OneOrMore(ParseType, state) &&
+      ParseOneCharToken(state, 'E')) {
+    return true;
+  }
+  state->parse_state = copy;
+
+  return false;
+}
+
+// <function-type> ::= [exception-spec] F [Y] <bare-function-type> [O] E
 static bool ParseFunctionType(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'F') &&
+  if (Optional(ParseExceptionSpec(state)) && ParseOneCharToken(state, 'F') &&
       Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
       Optional(ParseOneCharToken(state, 'O')) &&
       ParseOneCharToken(state, 'E')) {
@@ -1900,7 +1936,8 @@
 bool Demangle(const char *mangled, char *out, int out_size) {
   State state;
   InitState(&state, mangled, out, out_size);
-  return ParseTopLevelMangledName(&state) && !Overflowed(&state);
+  return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&
+         state.parse_state.out_cur_idx > 0;
 }
 
 }  // namespace debugging_internal
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index d5cc174..90af852 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -44,48 +44,46 @@
     !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-#else
-#define ABSL_STACKTRACE_INL_HEADER \
-  "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
 #endif
 
 #elif defined(__linux__) && !defined(__ANDROID__)
 
-#if !defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__)
+#if defined(NO_FRAME_POINTER) && \
+    (defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))
+// Note: The libunwind-based implementation is not available to open-source
+// users.
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_x86-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_powerpc-inl.inc"
-# elif defined(__aarch64__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_aarch64-inl.inc"
-#elif defined(__arm__) && defined(__GLIBC__)
+  "absl/debugging/internal/stacktrace_libunwind-inl.inc"
+#define STACKTRACE_USES_LIBUNWIND 1
+#elif defined(NO_FRAME_POINTER) && defined(__has_include)
+#if __has_include(<execinfo.h>)
 // Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+#endif
+#elif defined(__i386__) || defined(__x86_64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#else  // defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+  "absl/debugging/internal/stacktrace_x86-inl.inc"
+#elif defined(__ppc__) || defined(__PPC__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_generic-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
+  "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+#elif defined(__aarch64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+  "absl/debugging/internal/stacktrace_aarch64-inl.inc"
+#elif defined(__has_include)
+#if __has_include(<execinfo.h>)
+// Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
-   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#endif  // NO_FRAME_POINTER
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+#endif
 
-#else
+#endif
+
+// Fallback to the empty implementation.
+#if !defined(ABSL_STACKTRACE_INL_HEADER)
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-
 #endif
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc
index b2792a1..b94c612 100644
--- a/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -43,17 +43,6 @@
 // glibc implementation itself will trigger malloc the first time it is called.
 // As such, we suppress usage of backtrace during this early stage of execution.
 static std::atomic<bool> disable_stacktraces(true);  // Disabled until healthy.
-// Waiting until static initializers run seems to be late enough.
-// This file is included into stacktrace.cc so this will only run once.
-ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {
-  void* unused_stack[1];
-  // Force the first backtrace to happen early to get the one-time shared lib
-  // loading (allocation) out of the way. After the first call it is much safer
-  // to use backtrace from a signal handler if we crash somewhere later.
-  backtrace(unused_stack, 1);
-  disable_stacktraces.store(false, std::memory_order_relaxed);
-  return 0;
-}();
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
@@ -99,7 +88,7 @@
 ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
-  return true;
+  return false;
 }
 }  // namespace debugging_internal
 ABSL_NAMESPACE_END
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index b3729af..4f26130 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -118,16 +118,14 @@
 //   filename != nullptr
 //
 // Returns true if the file was successfully registered.
-bool RegisterFileMappingHint(
-    const void* start, const void* end, uint64_t offset, const char* filename);
+bool RegisterFileMappingHint(const void* start, const void* end,
+                             uint64_t offset, const char* filename);
 
 // Looks up the file mapping registered by RegisterFileMappingHint for an
 // address range. If there is one, the file name is stored in *filename and
 // *start and *end are modified to reflect the registered mapping. Returns
 // whether any hint was found.
-bool GetFileMappingHint(const void** start,
-                        const void** end,
-                        uint64_t    *  offset,
+bool GetFileMappingHint(const void** start, const void** end, uint64_t* offset,
                         const char** filename);
 
 }  // namespace debugging_internal
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index eec7a6e..5e4a25d 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -14,9 +14,18 @@
 
 #include "absl/debugging/symbolize.h"
 
+#ifdef _WIN32
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
+    WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+// UWP doesn't have access to win32 APIs.
+#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
+#endif
+#endif
+
 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)
 #include "absl/debugging/symbolize_elf.inc"
-#elif defined(_WIN32)
+#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
 // The Windows Symbolizer only works if PDB files containing the debug info
 // are available to the program at runtime.
 #include "absl/debugging/symbolize_win32.inc"
diff --git a/absl/debugging/symbolize_darwin.inc b/absl/debugging/symbolize_darwin.inc
index cdadd40..443ce9e 100644
--- a/absl/debugging/symbolize_darwin.inc
+++ b/absl/debugging/symbolize_darwin.inc
@@ -77,8 +77,8 @@
 
   char tmp_buf[1024];
   if (debugging_internal::Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {
-    int len = strlen(tmp_buf);
-    if (len + 1 <= out_size) {  // +1 for '\0'
+    size_t len = strlen(tmp_buf);
+    if (len + 1 <= static_cast<size_t>(out_size)) {  // +1 for '\0'
       assert(len < sizeof(tmp_buf));
       memmove(out, tmp_buf, len + 1);
     }
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index 7c36fd1..f4d5727 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -1281,7 +1281,7 @@
     const int phnum = obj->elf_header.e_phnum;
     const int phentsize = obj->elf_header.e_phentsize;
     size_t phoff = obj->elf_header.e_phoff;
-    int num_executable_load_segments = 0;
+    size_t num_executable_load_segments = 0;
     for (int j = 0; j < phnum; j++) {
       ElfW(Phdr) phdr;
       if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
@@ -1342,7 +1342,7 @@
         // Note: some binaries have multiple "rx" LOAD segments. We must
         // find the right one.
         ElfW(Phdr) *phdr = nullptr;
-        for (int j = 0; j < obj->phdr.size(); j++) {
+        for (size_t j = 0; j < obj->phdr.size(); j++) {
           ElfW(Phdr) &p = obj->phdr[j];
           if (p.p_type != PT_LOAD) {
             // We only expect PT_LOADs. This must be PT_NULL that we didn't
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 92bd4f1..2bd9478 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "path_util",
@@ -114,7 +114,6 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = ["//visibility:private"],
     deps = [
         "//absl/base:config",
         "//absl/base:fast_type_id",
@@ -179,6 +178,7 @@
         ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/container:flat_hash_map",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -381,6 +381,8 @@
     deps = [
         ":flag",
         ":marshalling",
+        ":parse",
+        ":reflection",
         "//absl/strings",
         "//absl/time",
         "//absl/types:optional",
@@ -464,6 +466,7 @@
         ":flag",
         ":marshalling",
         ":reflection",
+        ":usage_internal",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
diff --git a/absl/flags/BUILD.gn b/absl/flags/BUILD.gn
index 99c61ca..8fa0603 100644
--- a/absl/flags/BUILD.gn
+++ b/absl/flags/BUILD.gn
@@ -61,7 +61,6 @@
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:fast_type_id",
   ]
-  visibility = [ ":*" ]
 }
 
 absl_source_set("commandlineflag") {
@@ -101,6 +100,7 @@
     ":private_handle_accessor",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/container:flat_hash_map",
     "//third_party/abseil-cpp/absl/strings",
     "//third_party/abseil-cpp/absl/synchronization",
   ]
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 343774d..8855191 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -165,6 +165,7 @@
     absl::flags_config
     absl::strings
     absl::synchronization
+    absl::flat_hash_map
 )
 
 # Internal-only target, do not depend on directly.
@@ -182,6 +183,7 @@
   DEPS
     absl::base
     absl::config
+    absl::flags_commandlineflag
     absl::flags_commandlineflag_internal
     absl::flags_config
     absl::flags_marshalling
@@ -407,9 +409,10 @@
     absl::flags_commandlineflag_internal
     absl::flags
     absl::flags_reflection
+    absl::flags_usage
     absl::memory
     absl::strings
-    gtest_main
+    gmock_main
 )
 
 absl_cc_test(
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index cdac545..a9cb2b7 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -144,11 +144,17 @@
   inline bool IsOfType() const {
     return GetImpl().template IsOfType<U>();
   }
-  T Get() const { return GetImpl().Get(); }
-  void Set(const T& v) { GetImpl().Set(v); }
+  T Get() const {
+    return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
+  }
+  void Set(const T& v) {
+    flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
+  }
   void InvokeCallback() { GetImpl().InvokeCallback(); }
 
-  const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
+  const CommandLineFlag& Reflect() const {
+    return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
+  }
 
   // The data members are logically private, but they need to be public for
   // this to be an aggregate type.
@@ -180,7 +186,7 @@
 //   std::string first_name = absl::GetFlag(FLAGS_firstname);
 template <typename T>
 ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
-  return flag.Get();
+  return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
 }
 
 // SetFlag()
@@ -192,7 +198,7 @@
 // but especially within performance-critical code.
 template <typename T>
 void SetFlag(absl::Flag<T>* flag, const T& v) {
-  flag->Set(v);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, v);
 }
 
 // Overload of `SetFlag()` to allow callers to pass in a value that is
@@ -201,7 +207,7 @@
 template <typename T, typename V>
 void SetFlag(absl::Flag<T>* flag, const V& v) {
   T value(v);
-  flag->Set(value);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, value);
 }
 
 // GetFlagReflectionHandle()
@@ -216,7 +222,7 @@
 
 template <typename T>
 const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
-  return f.Reflect();
+  return flags_internal::FlagImplPeer::InvokeReflect(f);
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc
index 7b52c9b..9982b60 100644
--- a/absl/flags/flag_benchmark.cc
+++ b/absl/flags/flag_benchmark.cc
@@ -20,6 +20,8 @@
 
 #include "absl/flags/flag.h"
 #include "absl/flags/marshalling.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
 #include "absl/types/optional.h"
@@ -103,6 +105,23 @@
 
 BENCHMARKED_TYPES(FLAG_DEF)
 
+// Register thousands of flags to bloat up the size of the registry.
+// This mimics real life production binaries.
+#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
+#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1)
+#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1)
+#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1)
+#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1)
+#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1)
+#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1)
+#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1)
+#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1)
+#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1)
+#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1)
+#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1)
+#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1)
+DEFINE_FLAG_12(bloat_flag_);
+
 namespace {
 
 #define BM_GetFlag(T)                                            \
@@ -115,6 +134,20 @@
 
 BENCHMARKED_TYPES(BM_GetFlag)
 
+void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
+  char dummy[] = "dummy";
+  char* argv[] = {dummy};
+  // We need to ensure that flags have been parsed. That is where the registry
+  // is finalized.
+  absl::ParseCommandLine(1, argv);
+
+  for (auto s : state) {
+    benchmark::DoNotOptimize(
+        absl::FindCommandLineFlag("bloat_flag_010101010101"));
+  }
+}
+BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
+
 }  // namespace
 
 #define InvokeGetFlag(T)                                               \
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 89e43ad..370d8a0 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -632,20 +632,9 @@
   std::string CurrentValue() const { return impl_.CurrentValue(); }
 
  private:
-  template <typename U, bool do_register>
+  template <typename, bool>
   friend class FlagRegistrar;
-
-#if !defined(_MSC_VER) || defined(__clang__)
-  template <typename U>
-  friend U absl::GetFlag(const flags_internal::Flag<U>& flag);
-  template <typename U>
-  friend void absl::SetFlag(flags_internal::Flag<U>* flag, const U& v);
-  template <typename U, typename V>
-  friend void absl::SetFlag(flags_internal::Flag<U>* flag, const V& v);
-#else
-  template <typename U>
-  friend class absl::Flag;
-#endif
+  friend class FlagImplPeer;
 
   T Get() const {
     // See implementation notes in CommandLineFlag::Get().
@@ -668,10 +657,6 @@
     impl_.Write(&v);
   }
 
-  template <typename U>
-  friend const CommandLineFlag& absl::GetFlagReflectionHandle(
-      const absl::Flag<U>& f);
-
   // Access to the reflection.
   const CommandLineFlag& Reflect() const { return impl_; }
 
@@ -684,6 +669,25 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+  template <typename T, typename FlagType>
+  static T InvokeGet(const FlagType& flag) {
+    return flag.Get();
+  }
+  template <typename FlagType, typename T>
+  static void InvokeSet(FlagType& flag, const T& v) {
+    flag.Set(v);
+  }
+  template <typename FlagType>
+  static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+    return f.Reflect();
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
 // Implementation of Flag value specific operations routine.
 template <typename T>
 void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index 1df2db7..a8d9eb9 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -30,9 +30,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// Executes specified visitor for each non-retired flag in the registry.
-// Requires the caller hold the registry lock.
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor);
 // Executes specified visitor for each non-retired flag in the registry. While
 // callback are executed, the registry is locked and can't be changed.
 void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
@@ -41,6 +38,8 @@
 
 bool RegisterCommandLineFlag(CommandLineFlag&);
 
+void FinalizeRegistry();
+
 //-----------------------------------------------------------------------------
 // Retired registrations:
 //
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 0805df3..7557322 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -145,7 +145,8 @@
       }
 
       // Write the token, ending the string first if necessary/possible.
-      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+      if (!new_line &&
+          (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
         EndLine();
         new_line = true;
       }
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index 0c62dc4..619ccce 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -36,7 +36,8 @@
   kHumanReadable,
 };
 
-// Outputs the help message describing specific flag.
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
 void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format = HelpFormat::kHumanReadable);
 
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 4f4bb3d..1835a83 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -611,6 +611,11 @@
                                         OnUndefinedFlag on_undef_flag) {
   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
 
+  // Once parsing has started we will not have more flag registrations.
+  // If we did, they would be missing during parsing, which is a problem on
+  // itself.
+  flags_internal::FinalizeRegistry();
+
   // This routine does not return anything since we abort on failure.
   CheckDefaultValuesParsingRoundtrip();
 
diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc
index e4145b3..c6bf8aa 100644
--- a/absl/flags/reflection.cc
+++ b/absl/flags/reflection.cc
@@ -17,6 +17,7 @@
 
 #include <assert.h>
 
+#include <atomic>
 #include <map>
 #include <string>
 
@@ -56,21 +57,23 @@
 
   // Returns the flag object for the specified name, or nullptr if not found.
   // Will emit a warning if a 'retired' flag is specified.
-  CommandLineFlag* FindFlagLocked(absl::string_view name);
+  CommandLineFlag* FindFlag(absl::string_view name);
 
   static FlagRegistry& GlobalRegistry();  // returns a singleton registry
 
  private:
   friend class flags_internal::FlagSaverImpl;  // reads all the flags in order
                                                // to copy them
-  friend void ForEachFlagUnlocked(
-      std::function<void(CommandLineFlag&)> visitor);
+  friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+  friend void FinalizeRegistry();
 
-  // The map from name to flag, for FindFlagLocked().
+  // The map from name to flag, for FindFlag().
   using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
   using FlagIterator = FlagMap::iterator;
   using FlagConstIterator = FlagMap::const_iterator;
   FlagMap flags_;
+  std::vector<CommandLineFlag*> flat_flags_;
+  std::atomic<bool> finalized_flags_{false};
 
   absl::Mutex lock_;
 
@@ -79,15 +82,6 @@
   FlagRegistry& operator=(const FlagRegistry&);
 };
 
-CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end()) {
-    return nullptr;
-  }
-
-  return i->second;
-}
-
 namespace {
 
 class FlagRegistryLock {
@@ -101,8 +95,24 @@
 
 }  // namespace
 
+CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
+  if (finalized_flags_.load(std::memory_order_acquire)) {
+    // We could save some gcus here if we make `Name()` be non-virtual.
+    // We could move the `const char*` name to the base class.
+    auto it = std::partition_point(
+        flat_flags_.begin(), flat_flags_.end(),
+        [=](CommandLineFlag* f) { return f->Name() < name; });
+    if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
+  }
+
+  FlagRegistryLock frl(*this);
+  auto it = flags_.find(name);
+  return it != flags_.end() ? it->second : nullptr;
+}
+
 void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
   FlagRegistryLock registry_lock(*this);
+
   std::pair<FlagIterator, bool> ins =
       flags_.insert(FlagMap::value_type(flag.Name(), &flag));
   if (ins.second == false) {  // means the name was already in the map
@@ -152,18 +162,15 @@
 
 // --------------------------------------------------------------------
 
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
-  FlagRegistry& registry = FlagRegistry::GlobalRegistry();
-  for (FlagRegistry::FlagConstIterator i = registry.flags_.begin();
-       i != registry.flags_.end(); ++i) {
-    visitor(*i->second);
-  }
-}
-
 void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
   FlagRegistry& registry = FlagRegistry::GlobalRegistry();
+
+  if (registry.finalized_flags_.load(std::memory_order_acquire)) {
+    for (const auto& i : registry.flat_flags_) visitor(*i);
+  }
+
   FlagRegistryLock frl(registry);
-  ForEachFlagUnlocked(visitor);
+  for (const auto& i : registry.flags_) visitor(*i.second);
 }
 
 // --------------------------------------------------------------------
@@ -173,6 +180,21 @@
   return true;
 }
 
+void FinalizeRegistry() {
+  auto& registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
+    // Was already finalized. Ignore the second time.
+    return;
+  }
+  registry.flat_flags_.reserve(registry.flags_.size());
+  for (const auto& f : registry.flags_) {
+    registry.flat_flags_.push_back(f.second);
+  }
+  registry.flags_.clear();
+  registry.finalized_flags_.store(true, std::memory_order_release);
+}
+
 // --------------------------------------------------------------------
 
 namespace {
@@ -298,9 +320,17 @@
   if (name.empty()) return nullptr;
   flags_internal::FlagRegistry& registry =
       flags_internal::FlagRegistry::GlobalRegistry();
-  flags_internal::FlagRegistryLock frl(registry);
+  return registry.FindFlag(name);
+}
 
-  return registry.FindFlagLocked(name);
+// --------------------------------------------------------------------
+
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
+  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    res.insert({flag.Name(), &flag});
+  });
+  return res;
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h
index 045f978..e6baf5d 100644
--- a/absl/flags/reflection.h
+++ b/absl/flags/reflection.h
@@ -26,6 +26,7 @@
 #include <string>
 
 #include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
 
@@ -40,7 +41,11 @@
 // Returns the reflection handle of an Abseil flag of the specified name, or
 // `nullptr` if not found. This function will emit a warning if the name of a
 // 'retired' flag is specified.
-CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
 
 //------------------------------------------------------------------------------
 // FlagSaver
@@ -59,7 +64,7 @@
 //   void MyFunc() {
 //    absl::FlagSaver fs;
 //    ...
-//    absl::SetFlag(FLAGS_myFlag, otherValue);
+//    absl::SetFlag(&FLAGS_myFlag, otherValue);
 //    ...
 //  } // scope of FlagSaver left, flags return to previous state
 //
diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc
index 2da0a0e..1a1dcb4 100644
--- a/absl/flags/reflection_test.cc
+++ b/absl/flags/reflection_test.cc
@@ -18,7 +18,9 @@
 #include <memory>
 #include <string>
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/marshalling.h"
@@ -30,6 +32,8 @@
 ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
 ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
 
+ABSL_DECLARE_FLAG(bool, help);
+
 namespace {
 
 namespace flags = absl::flags_internal;
@@ -61,6 +65,33 @@
 
 // --------------------------------------------------------------------
 
+TEST_F(ReflectionTest, TestGetAllFlags) {
+  (void)absl::GetFlag(FLAGS_help);  // Force linking of usage flags.
+
+  auto all_flags = absl::GetAllFlags();
+  EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
+  EXPECT_NE(all_flags.find("bool_retired_flag"), all_flags.end());
+  EXPECT_NE(all_flags.find("help"), all_flags.end());
+  EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
+
+  std::vector<absl::string_view> flag_names_first_attempt;
+  auto all_flags_1 = absl::GetAllFlags();
+  for (auto f : all_flags_1) {
+    flag_names_first_attempt.push_back(f.first);
+  }
+
+  std::vector<absl::string_view> flag_names_second_attempt;
+  auto all_flags_2 = absl::GetAllFlags();
+  for (auto f : all_flags_2) {
+    flag_names_second_attempt.push_back(f.first);
+  }
+
+  EXPECT_THAT(flag_names_first_attempt,
+              ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
+}
+
+// --------------------------------------------------------------------
+
 struct CustomUDT {
   CustomUDT() : a(1), b(1) {}
   CustomUDT(int a_, int b_) : a(a_), b(b_) {}
diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel
index 432546c..ebd9b99 100644
--- a/absl/functional/BUILD.bazel
+++ b/absl/functional/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "bind_front",
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index 6c77f1a..5b1e2d0 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "hash",
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index d7386f6..5de132c 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -88,7 +88,6 @@
 //  * T is an arithmetic or pointer type
 //  * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary
 //    hash state `H`.
-//  - T defines a specialization of `HASH_NAMESPACE::hash<T>`
 //  - T defines a specialization of `std::hash<T>`
 //
 // `absl::Hash` intrinsically supports the following types:
@@ -128,8 +127,6 @@
 //   * Natively supported types out of the box (see above)
 //   * Types for which an `AbslHashValue()` overload is provided (such as
 //     user-defined types). See "Adding Type Support to `absl::Hash`" below.
-//   * Types which define a `HASH_NAMESPACE::hash<T>` specialization (aka
-//     `__gnu_cxx::hash<T>` for gcc/Clang or `stdext::hash<T>` for MSVC)
 //   * Types which define a `std::hash<T>` specialization
 //
 // The fallback to legacy hash functions exists mainly for backwards
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 39ba24a..1d2e6cf 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -82,8 +82,8 @@
 }
 
 REGISTER_TYPED_TEST_CASE_P(HashValueIntTest, BasicUsage, FastPath);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
-                                uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+                                uint32_t, uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
 
 enum LegacyEnum { kValue1, kValue2, kValue3 };
@@ -819,8 +819,8 @@
 }
 
 REGISTER_TYPED_TEST_CASE_P(HashIntTest, BasicUsage);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
-                                uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+                                uint32_t, uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes);
 
 struct StructWithPadding {
diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc
index e122c18..58d4bcb 100644
--- a/absl/hash/internal/city.cc
+++ b/absl/hash/internal/city.cc
@@ -253,9 +253,8 @@
 
 // Return a 16-byte hash for 48 bytes.  Quick and dirty.
 // Callers do best to use "random-looking" values for a and b.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(uint64_t w, uint64_t x,
-                                                        uint64_t y, uint64_t z,
-                                                        uint64_t a, uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
+    uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) {
   a += w;
   b = Rotate(b + a + z, 21);
   uint64_t c = a;
@@ -266,8 +265,9 @@
 }
 
 // Return a 16-byte hash for s[0] ... s[31], a, and b.  Quick and dirty.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s, uint64_t a,
-                                                        uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s,
+                                                            uint64_t a,
+                                                            uint64_t b) {
   return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),
                                 Fetch64(s + 24), a, b);
 }
@@ -310,8 +310,10 @@
   uint64_t x = Fetch64(s + len - 40);
   uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
   uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
-  std::pair<uint64_t, uint64_t> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
-  std::pair<uint64_t, uint64_t> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
+  std::pair<uint64_t, uint64_t> v =
+      WeakHashLen32WithSeeds(s + len - 64, len, z);
+  std::pair<uint64_t, uint64_t> w =
+      WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
   x = x * k1 + Fetch64(s);
 
   // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -337,7 +339,7 @@
 }
 
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
-                           uint64_t seed1) {
+                             uint64_t seed1) {
   return HashLen16(CityHash64(s, len) - seed0, seed1);
 }
 
diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h
index 161c774..9c1e7a5 100644
--- a/absl/hash/internal/city.h
+++ b/absl/hash/internal/city.h
@@ -71,7 +71,7 @@
 // Hash function for a byte array.  For convenience, two seeds are also
 // hashed into the result.
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
-                           uint64_t seed1);
+                             uint64_t seed1);
 
 // Hash function for a byte array.  Most useful in 32-bit binaries.
 uint32_t CityHash32(const char *s, size_t len);
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 9e608f7..b0132da 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -855,7 +855,14 @@
   // On other platforms this is still going to be non-deterministic but most
   // probably per-build and not per-process.
   ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
+#if (!defined(__clang__) || __clang_major__ > 11) && \
+    !defined(__apple_build_version__)
+    return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
+#else
+    // Workaround the absence of
+    // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021.
     return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
+#endif
   }
   static const void* const kSeed;
 
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 2ba9d7c..d2824a0 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "memory",
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 513f710..2b5ff62 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -420,6 +420,9 @@
 //
 // A C++11 compatible implementation of C++17's std::allocator_traits.
 //
+#if __cplusplus >= 201703L
+using std::allocator_traits;
+#else  // __cplusplus >= 201703L
 template <typename Alloc>
 struct allocator_traits {
   using allocator_type = Alloc;
@@ -609,6 +612,7 @@
     return a;
   }
 };
+#endif  // __cplusplus >= 201703L
 
 namespace memory_internal {
 
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index 0d2e13b..1990c7b 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -555,7 +555,7 @@
   EXPECT_CALL(mock, deallocate(&x, 7));
 
   EXPECT_EQ(&x, Traits::allocate(mock, 7));
-  Traits::allocate(mock, 7, static_cast<const void*>(&hint));
+  static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   EXPECT_EQ(&x, Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   Traits::deallocate(mock, &x, 7);
 
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index c06d2d9..5585fcc 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "type_traits",
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index da3af4d..f808f5d 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -22,7 +22,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "int128",
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 000cc45..8485e28 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -30,7 +30,7 @@
     "//absl/random:__pkg__",
 ])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "traits",
diff --git a/absl/random/internal/BUILD.gn b/absl/random/internal/BUILD.gn
index 3940946..b97592c 100644
--- a/absl/random/internal/BUILD.gn
+++ b/absl/random/internal/BUILD.gn
@@ -155,7 +155,10 @@
     "randen_traits.h",
   ]
   sources = [ "randen_round_keys.cc" ]
-  deps = [ "//third_party/abseil-cpp/absl/base:config" ]
+  deps = [
+    "//build:chromeos_buildflags",
+    "//third_party/abseil-cpp/absl/base:config",
+  ]
 }
 
 absl_source_set("randen") {
diff --git a/absl/random/internal/gaussian_distribution_gentables.cc b/absl/random/internal/gaussian_distribution_gentables.cc
index a2bf039..a95333d 100644
--- a/absl/random/internal/gaussian_distribution_gentables.cc
+++ b/absl/random/internal/gaussian_distribution_gentables.cc
@@ -111,12 +111,9 @@
          "\n"
          "#include \"absl/random/gaussian_distribution.h\"\n"
          "\n"
-         // "namespace " and "absl" are broken apart so as not to conflict with
-         // script that adds the LTS inline namespace.
-         "namespace "
-         "absl {\n"
-         "namespace "
-         "random_internal {\n"
+         "namespace absl {\n"
+         "ABSL_NAMESPACE_BEGIN\n"
+         "namespace random_internal {\n"
          "\n"
          "const gaussian_distribution_base::Tables\n"
          "    gaussian_distribution_base::zg_ = {\n";
@@ -125,10 +122,9 @@
   FormatArrayContents(os, tables_.f);
   *os << "};\n"
          "\n"
-         "}  // namespace "
-         "random_internal\n"
-         "}  // namespace "
-         "absl\n"
+         "}  // namespace random_internal\n"
+         "ABSL_NAMESPACE_END\n"
+         "}  // namespace absl\n"
          "\n"
          "// clang-format on\n"
          "// END GENERATED CODE";
diff --git a/absl/random/internal/generate_real_test.cc b/absl/random/internal/generate_real_test.cc
index aa02f0c..4bdc453 100644
--- a/absl/random/internal/generate_real_test.cc
+++ b/absl/random/internal/generate_real_test.cc
@@ -419,8 +419,8 @@
   };
 
   // Rely on RandU64ToFloat generating values from greatest to least when
-  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).  Thus,
-  // this algorithm stores the previous value, and if the new value is at
+  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).
+  // Thus, this algorithm stores the previous value, and if the new value is at
   // greater than or equal to the previous value, then there is a collision in
   // the generation algorithm.
   //
diff --git a/absl/random/internal/randen_detect.cc b/absl/random/internal/randen_detect.cc
index d63230c..bbe7b96 100644
--- a/absl/random/internal/randen_detect.cc
+++ b/absl/random/internal/randen_detect.cc
@@ -1,13 +1,13 @@
 // Copyright 2017 The Abseil Authors.
 //
-// Licensed under the Apache License, Version 2.0 (the"License");
+// 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
 //
 //      https://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,
+// 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.
diff --git a/absl/status/BUILD.bazel b/absl/status/BUILD.bazel
index d164252..189bd73 100644
--- a/absl/status/BUILD.bazel
+++ b/absl/status/BUILD.bazel
@@ -26,11 +26,12 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "status",
     srcs = [
+        "internal/status_internal.h",
         "status.cc",
         "status_payload_printer.cc",
     ],
@@ -64,3 +65,39 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "statusor",
+    srcs = [
+        "internal/statusor_internal.h",
+        "statusor.cc",
+    ],
+    hdrs = [
+        "statusor.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":status",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "//absl/types:variant",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "statusor_test",
+    size = "small",
+    srcs = ["statusor_test.cc"],
+    deps = [
+        ":status",
+        ":statusor",
+        "//absl/base",
+        "//absl/memory",
+        "//absl/types:any",
+        "//absl/utility",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/status/BUILD.gn b/absl/status/BUILD.gn
index 38dbbfc..740fb19 100644
--- a/absl/status/BUILD.gn
+++ b/absl/status/BUILD.gn
@@ -10,6 +10,7 @@
     "status_payload_printer.h",
   ]
   sources = [
+    "internal/status_internal.h",
     "status.cc",
     "status_payload_printer.cc",
   ]
@@ -27,3 +28,23 @@
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
+
+absl_source_set("statusor") {
+  public = [
+    "statusor.h",
+  ]
+  sources = [
+    "internal/statusor_internal.h",
+    "statusor.cc",
+  ]
+  deps = [
+    ":status",
+    "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/base:raw_logging_internal",
+    "//third_party/abseil-cpp/absl/meta:type_traits",
+    "//third_party/abseil-cpp/absl/strings",
+    "//third_party/abseil-cpp/absl/types:variant",
+    "//third_party/abseil-cpp/absl/utility",
+  ]
+}
+
diff --git a/absl/status/CMakeLists.txt b/absl/status/CMakeLists.txt
index c041d69..f0d798a 100644
--- a/absl/status/CMakeLists.txt
+++ b/absl/status/CMakeLists.txt
@@ -19,6 +19,7 @@
   HDRS
     "status.h"
   SRCS
+    "internal/status_internal.h"
     "status.cc"
     "status_payload_printer.h"
     "status_payload_printer.cc"
@@ -51,3 +52,37 @@
     absl::strings
     gmock_main
 )
+
+absl_cc_library(
+  NAME
+    statusor
+  HDRS
+    "statusor.h"
+  SRCS
+    "statusor.cc"
+    "internal/statusor_internal.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::status
+    absl::core_headers
+    absl::raw_logging_internal
+    absl::type_traits
+    absl::strings
+    absl::utility
+    absl::variant
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    statusor_test
+  SRCS
+   "statusor_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::status
+    absl::statusor
+    gmock_main
+)
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
new file mode 100644
index 0000000..1f82b8e
--- /dev/null
+++ b/absl/status/internal/status_internal.h
@@ -0,0 +1,51 @@
+// Copyright 2019 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+
+#include <string>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/cord.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+enum class StatusCode : int;
+
+namespace status_internal {
+
+// Container for status payloads.
+struct Payload {
+  std::string type_url;
+  absl::Cord payload;
+};
+
+using Payloads = absl::InlinedVector<Payload, 1>;
+
+// Reference-counted representation of Status data.
+struct StatusRep {
+  std::atomic<int32_t> ref;
+  absl::StatusCode code;
+  std::string message;
+  std::unique_ptr<status_internal::Payloads> payloads;
+};
+
+absl::StatusCode MapToLocalCode(int value);
+}  // namespace status_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
new file mode 100644
index 0000000..7cc7625
--- /dev/null
+++ b/absl/status/internal/statusor_internal.h
@@ -0,0 +1,399 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/status/status.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+namespace internal_statusor {
+
+// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
+// StatusOr<T>()`.
+template <typename T, typename U, typename = void>
+struct HasConversionOperatorToStatusOr : std::false_type {};
+
+template <typename T, typename U>
+void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
+
+template <typename T, typename U>
+struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
+    : std::true_type {};
+
+// Detects whether `T` is constructible or convertible from `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleFromStatusOr =
+    absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
+                      std::is_constructible<T, const StatusOr<U>&>,
+                      std::is_constructible<T, StatusOr<U>&&>,
+                      std::is_constructible<T, const StatusOr<U>&&>,
+                      std::is_convertible<StatusOr<U>&, T>,
+                      std::is_convertible<const StatusOr<U>&, T>,
+                      std::is_convertible<StatusOr<U>&&, T>,
+                      std::is_convertible<const StatusOr<U>&&, T>>;
+
+// Detects whether `T` is constructible or convertible or assignable from
+// `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
+    absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
+                      std::is_assignable<T&, StatusOr<U>&>,
+                      std::is_assignable<T&, const StatusOr<U>&>,
+                      std::is_assignable<T&, StatusOr<U>&&>,
+                      std::is_assignable<T&, const StatusOr<U>&&>>;
+
+// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
+// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
+template <typename T, typename U>
+struct IsDirectInitializationAmbiguous
+    : public absl::conditional_t<
+          std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                       U>::value,
+          std::false_type,
+          IsDirectInitializationAmbiguous<
+              T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename V>
+struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
+    : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
+
+// Checks against the constraints of the direction initialization, i.e. when
+// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsDirectInitializationValid = absl::disjunction<
+    // Short circuits if T is basically U.
+    std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+    absl::negation<absl::disjunction<
+        std::is_same<absl::StatusOr<T>,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::Status,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::in_place_t,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        IsDirectInitializationAmbiguous<T, U>>>>;
+
+// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
+// is equivalent to whether all the following conditions are met:
+// 1. `U` is `StatusOr<V>`.
+// 2. `T` is constructible and assignable from `V`.
+// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
+// For example, the following code is considered ambiguous:
+// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
+//   StatusOr<bool> s1 = true;  // s1.ok() && s1.ValueOrDie() == true
+//   StatusOr<bool> s2 = false;  // s2.ok() && s2.ValueOrDie() == false
+//   s1 = s2;  // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous
+    : public absl::conditional_t<
+          std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                       U>::value,
+          std::false_type,
+          IsForwardingAssignmentAmbiguous<
+              T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
+    : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
+
+// Checks against the constraints of the forwarding assignment, i.e. whether
+// `StatusOr<T>::operator(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsForwardingAssignmentValid = absl::disjunction<
+    // Short circuits if T is basically U.
+    std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+    absl::negation<absl::disjunction<
+        std::is_same<absl::StatusOr<T>,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::Status,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::in_place_t,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        IsForwardingAssignmentAmbiguous<T, U>>>>;
+
+class Helper {
+ public:
+  // Move type-agnostic error handling to the .cc.
+  static void HandleInvalidStatusCtorArg(Status*);
+  static void Crash(const absl::Status& status);
+};
+
+// Construct an instance of T in `p` through placement new, passing Args... to
+// the constructor.
+// This abstraction is here mostly for the gcc performance fix.
+template <typename T, typename... Args>
+void PlacementNew(void* p, Args&&... args) {
+#if defined(__GNUC__) && !defined(__clang__)
+  // Teach gcc that 'p' cannot be null, fixing code size issues.
+  if (p == nullptr) __builtin_unreachable();
+#endif
+  new (p) T(std::forward<Args>(args)...);
+}
+
+// Helper base class to hold the data and all operations.
+// We move all this to a base class to allow mixing with the appropriate
+// TraitsBase specialization.
+template <typename T>
+class StatusOrData {
+  template <typename U>
+  friend class StatusOrData;
+
+ public:
+  StatusOrData() = delete;
+
+  StatusOrData(const StatusOrData& other) {
+    if (other.ok()) {
+      MakeValue(other.data_);
+      MakeStatus();
+    } else {
+      MakeStatus(other.status_);
+    }
+  }
+
+  StatusOrData(StatusOrData&& other) noexcept {
+    if (other.ok()) {
+      MakeValue(std::move(other.data_));
+      MakeStatus();
+    } else {
+      MakeStatus(std::move(other.status_));
+    }
+  }
+
+  template <typename U>
+  explicit StatusOrData(const StatusOrData<U>& other) {
+    if (other.ok()) {
+      MakeValue(other.data_);
+      MakeStatus();
+    } else {
+      MakeStatus(other.status_);
+    }
+  }
+
+  template <typename U>
+  explicit StatusOrData(StatusOrData<U>&& other) {
+    if (other.ok()) {
+      MakeValue(std::move(other.data_));
+      MakeStatus();
+    } else {
+      MakeStatus(std::move(other.status_));
+    }
+  }
+
+  template <typename... Args>
+  explicit StatusOrData(absl::in_place_t, Args&&... args)
+      : data_(std::forward<Args>(args)...) {
+    MakeStatus();
+  }
+
+  explicit StatusOrData(const T& value) : data_(value) {
+    MakeStatus();
+  }
+  explicit StatusOrData(T&& value) : data_(std::move(value)) {
+    MakeStatus();
+  }
+
+  template <typename U,
+            absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
+                              int> = 0>
+  explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
+    EnsureNotOk();
+  }
+
+  StatusOrData& operator=(const StatusOrData& other) {
+    if (this == &other) return *this;
+    if (other.ok())
+      Assign(other.data_);
+    else
+      AssignStatus(other.status_);
+    return *this;
+  }
+
+  StatusOrData& operator=(StatusOrData&& other) {
+    if (this == &other) return *this;
+    if (other.ok())
+      Assign(std::move(other.data_));
+    else
+      AssignStatus(std::move(other.status_));
+    return *this;
+  }
+
+  ~StatusOrData() {
+    if (ok()) {
+      status_.~Status();
+      data_.~T();
+    } else {
+      status_.~Status();
+    }
+  }
+
+  template <typename U>
+  void Assign(U&& value) {
+    if (ok()) {
+      data_ = std::forward<U>(value);
+    } else {
+      MakeValue(std::forward<U>(value));
+      status_ = OkStatus();
+    }
+  }
+
+  template <typename U>
+  void AssignStatus(U&& v) {
+    Clear();
+    status_ = static_cast<absl::Status>(std::forward<U>(v));
+    EnsureNotOk();
+  }
+
+  bool ok() const { return status_.ok(); }
+
+ protected:
+  // status_ will always be active after the constructor.
+  // We make it a union to be able to initialize exactly how we need without
+  // waste.
+  // Eg. in the copy constructor we use the default constructor of Status in
+  // the ok() path to avoid an extra Ref call.
+  union {
+    Status status_;
+  };
+
+  // data_ is active iff status_.ok()==true
+  struct Dummy {};
+  union {
+    // When T is const, we need some non-const object we can cast to void* for
+    // the placement new. dummy_ is that object.
+    Dummy dummy_;
+    T data_;
+  };
+
+  void Clear() {
+    if (ok()) data_.~T();
+  }
+
+  void EnsureOk() const {
+    if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
+  }
+
+  void EnsureNotOk() {
+    if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
+  }
+
+  // Construct the value (ie. data_) through placement new with the passed
+  // argument.
+  template <typename... Arg>
+  void MakeValue(Arg&&... arg) {
+    internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
+  }
+
+  // Construct the status (ie. status_) through placement new with the passed
+  // argument.
+  template <typename... Args>
+  void MakeStatus(Args&&... args) {
+    internal_statusor::PlacementNew<Status>(&status_,
+                                            std::forward<Args>(args)...);
+  }
+};
+
+// Helper base classes to allow implicitly deleted constructors and assignment
+// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
+// the copy constructor when T is not copy constructible and `StatusOr` will
+// inherit that behavior implicitly.
+template <typename T, bool = std::is_copy_constructible<T>::value>
+struct CopyCtorBase {
+  CopyCtorBase() = default;
+  CopyCtorBase(const CopyCtorBase&) = default;
+  CopyCtorBase(CopyCtorBase&&) = default;
+  CopyCtorBase& operator=(const CopyCtorBase&) = default;
+  CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T>
+struct CopyCtorBase<T, false> {
+  CopyCtorBase() = default;
+  CopyCtorBase(const CopyCtorBase&) = delete;
+  CopyCtorBase(CopyCtorBase&&) = default;
+  CopyCtorBase& operator=(const CopyCtorBase&) = default;
+  CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value>
+struct MoveCtorBase {
+  MoveCtorBase() = default;
+  MoveCtorBase(const MoveCtorBase&) = default;
+  MoveCtorBase(MoveCtorBase&&) = default;
+  MoveCtorBase& operator=(const MoveCtorBase&) = default;
+  MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T>
+struct MoveCtorBase<T, false> {
+  MoveCtorBase() = default;
+  MoveCtorBase(const MoveCtorBase&) = default;
+  MoveCtorBase(MoveCtorBase&&) = delete;
+  MoveCtorBase& operator=(const MoveCtorBase&) = default;
+  MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_copy_constructible<T>::value&&
+                          std::is_copy_assignable<T>::value>
+struct CopyAssignBase {
+  CopyAssignBase() = default;
+  CopyAssignBase(const CopyAssignBase&) = default;
+  CopyAssignBase(CopyAssignBase&&) = default;
+  CopyAssignBase& operator=(const CopyAssignBase&) = default;
+  CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T>
+struct CopyAssignBase<T, false> {
+  CopyAssignBase() = default;
+  CopyAssignBase(const CopyAssignBase&) = default;
+  CopyAssignBase(CopyAssignBase&&) = default;
+  CopyAssignBase& operator=(const CopyAssignBase&) = delete;
+  CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value&&
+                          std::is_move_assignable<T>::value>
+struct MoveAssignBase {
+  MoveAssignBase() = default;
+  MoveAssignBase(const MoveAssignBase&) = default;
+  MoveAssignBase(MoveAssignBase&&) = default;
+  MoveAssignBase& operator=(const MoveAssignBase&) = default;
+  MoveAssignBase& operator=(MoveAssignBase&&) = default;
+};
+
+template <typename T>
+struct MoveAssignBase<T, false> {
+  MoveAssignBase() = default;
+  MoveAssignBase(const MoveAssignBase&) = default;
+  MoveAssignBase(MoveAssignBase&&) = default;
+  MoveAssignBase& operator=(const MoveAssignBase&) = default;
+  MoveAssignBase& operator=(MoveAssignBase&&) = delete;
+};
+
+ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status);
+
+}  // namespace internal_statusor
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
diff --git a/absl/status/status.cc b/absl/status/status.cc
index 0a65573..a27fd8b 100644
--- a/absl/status/status.cc
+++ b/absl/status/status.cc
@@ -78,7 +78,7 @@
                                  absl::string_view type_url) {
   if (payloads == nullptr) return -1;
 
-  for (int i = 0; i < payloads->size(); ++i) {
+  for (size_t i = 0; i < payloads->size(); ++i) {
     if ((*payloads)[i].type_url == type_url) return i;
   }
 
@@ -167,7 +167,7 @@
     bool in_reverse =
         payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
 
-    for (int index = 0; index < payloads->size(); ++index) {
+    for (size_t index = 0; index < payloads->size(); ++index) {
       const auto& elem =
           (*payloads)[in_reverse ? payloads->size() - 1 - index : index];
 
diff --git a/absl/status/status.h b/absl/status/status.h
index 4253062..c4d6fce 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -11,6 +11,43 @@
 // 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.
+//
+// -----------------------------------------------------------------------------
+// File: status.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the Abseil `status` library, consisting of:
+//
+//   * An `absl::Status` class for holding error handling information
+//   * A set of canonical `absl::StatusCode` error codes, and associated
+//     utilities for generating and propagating status codes.
+//   * A set of helper functions for creating status codes and checking their
+//     values
+//
+// Within Google, `absl::Status` is the primary mechanism for gracefully
+// handling errors across API boundaries (and in particular across RPC
+// boundaries). Some of these errors may be recoverable, but others may not.
+// Most functions that can produce a recoverable error should be designed to
+// return an `absl::Status` (or `absl::StatusOr`).
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+//   ...
+//   // encounter error
+//   if (error condition) {
+//     return absl::InvalidArgumentError("bad mode");
+//   }
+//   // else, return OK
+//   return absl::OkStatus();
+// }
+//
+// An `absl::Status` is designed to either return "OK" or one of a number of
+// different error codes, corresponding to typical error conditions.
+// In almost all cases, when using `absl::Status` you should use the canonical
+// error codes (of type `absl::StatusCode`) enumerated in this header file.
+// These canonical codes are understood across the codebase and will be
+// accepted across all API and RPC boundaries.
 #ifndef ABSL_STATUS_STATUS_H_
 #define ABSL_STATUS_STATUS_H_
 
@@ -18,78 +55,132 @@
 #include <string>
 
 #include "absl/container/inlined_vector.h"
+#include "absl/status/internal/status_internal.h"
 #include "absl/strings/cord.h"
 #include "absl/types/optional.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-// Sometimes multiple error codes may apply.  Services should return
-// the most specific error code that applies.  For example, prefer
-// `kOutOfRange` over `kFailedPrecondition` if both codes apply.
-// Similarly prefer `kNotFound` or `kAlreadyExists` over `kFailedPrecondition`.
+// absl::StatusCode
+//
+// An `absl::StatusCode` is an enumerated type indicating either no error ("OK")
+// or an error condition. In most cases, an `absl::Status` indicates a
+// recoverable error, and the purpose of signalling an error is to indicate what
+// action to take in response to that error. These error codes map to the proto
+// RPC error codes indicated in https://cloud.google.com/apis/design/errors.
+//
+// The errors listed below are the canonical errors associated with
+// `absl::Status` and are used throughout the codebase. As a result, these
+// error codes are somewhat generic.
+//
+// In general, try to return the most specific error that applies if more than
+// one error may pertain. For example, prefer `kOutOfRange` over
+// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or
+// `kAlreadyExists` over `kFailedPrecondition`.
+//
+// Because these errors may travel RPC boundaries, these codes are tied to the
+// `google.rpc.Code` definitions within
+// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
+// The string value of these RPC codes is denoted within each enum below.
+//
+// If your error handling code requires more context, you can attach payloads
+// to your status. See `absl::Status::SetPayload()` and
+// `absl::Status::GetPayload()` below.
 enum class StatusCode : int {
-  // Not an error; returned on success
+  // StatusCode::kOk
+  //
+  // kOK (gRPC code "OK") does not indicate an error; this value is returned on
+  // success. It is typical to check for this value before proceeding on any
+  // given call across an API or RPC boundary. To check this value, use the
+  // `absl::Status::ok()` member function rather than inspecting the raw code.
   kOk = 0,
 
-  // The operation was cancelled, typically by the caller.
+  // StatusCode::kCancelled
+  //
+  // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
+  // typically by the caller.
   kCancelled = 1,
 
-  // Unknown error. For example, errors raised by APIs that do not return
-  // enough error information may be converted to this error.
+  // StatusCode::kUnknown
+  //
+  // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In
+  // general, more specific errors should be raised, if possible. Errors raised
+  // by APIs that do not return enough error information may be converted to
+  // this error.
   kUnknown = 2,
 
-  // The client specified an invalid argument. Note that this differs
-  // from `kFailedPrecondition`. `kInvalidArgument` indicates arguments
-  // that are problematic regardless of the state of the system
-  // (such as a malformed file name).
+  // StatusCode::kInvalidArgument
+  //
+  // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller
+  // specified an invalid argument, such a malformed filename. Note that such
+  // errors should be narrowly limited to indicate to the invalid nature of the
+  // arguments themselves. Errors with validly formed arguments that may cause
+  // errors with the state of the receiving system should be denoted with
+  // `kFailedPrecondition` instead.
   kInvalidArgument = 3,
 
-  // The deadline expired before the operation could complete. For operations
-  // that change the state of the system, this error may be returned
-  // even if the operation has completed successfully. For example, a
-  // successful response from a server could have been delayed long
-  // enough for the deadline to expire.
+  // StatusCode::kDeadlineExceeded
+  //
+  // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline
+  // expired before the operation could complete. For operations that may change
+  // state within a system, this error may be returned even if the operation has
+  // completed successfully. For example, a successful response from a server
+  // could have been delayed long enough for the deadline to expire.
   kDeadlineExceeded = 4,
 
-  // Some requested entity (such as file or directory) was not found.
+  // StatusCode::kNotFound
   //
-  // Note to server developers: if a request is denied for an entire class
-  // of users, such as gradual feature rollout or undocumented whitelist,
-  // `kNotFound` may be used. If a request is denied for some users within
-  // a class of users, such as user-based access control, `kPermissionDenied`
-  // must be used.
+  // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as
+  // a file or directory) was not found.
+  //
+  // `kNotFound` is useful if a request should be denied for an entire class of
+  // users, such as during a gradual feature rollout or undocumented allow list.
+  // If, instead, a request should be denied for specific sets of users, such as
+  // through user-based access control, use `kPermissionDenied` instead.
   kNotFound = 5,
 
-  // The entity that a client attempted to create (such as file or directory)
-  // already exists.
+  // StatusCode::kAlreadyExists
+  //
+  // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a
+  // caller attempted to create (such as file or directory) is already present.
   kAlreadyExists = 6,
 
-  // The caller does not have permission to execute the specified
-  // operation. `kPermissionDenied` must not be used for rejections
-  // caused by exhausting some resource (use `kResourceExhausted`
-  // instead for those errors). `kPermissionDenied` must not be
-  // used if the caller can not be identified (use `kUnauthenticated`
-  // instead for those errors). This error code does not imply the
-  // request is valid or the requested entity exists or satisfies
-  // other pre-conditions.
+  // StatusCode::kPermissionDenied
+  //
+  // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller
+  // does not have permission to execute the specified operation. Note that this
+  // error is different than an error due to an *un*authenticated user. This
+  // error code does not imply the request is valid or the requested entity
+  // exists or satisfies any other pre-conditions.
+  //
+  // `kPermissionDenied` must not be used for rejections caused by exhausting
+  // some resource. Instead, use `kResourceExhausted` for those errors.
+  // `kPermissionDenied` must not be used if the caller cannot be identified.
+  // Instead, use `kUnauthenticated` for those errors.
   kPermissionDenied = 7,
 
-  // Some resource has been exhausted, perhaps a per-user quota, or
-  // perhaps the entire file system is out of space.
+  // StatusCode::kResourceExhausted
+  //
+  // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource
+  // has been exhausted, perhaps a per-user quota, or perhaps the entire file
+  // system is out of space.
   kResourceExhausted = 8,
 
-  // The operation was rejected because the system is not in a state
-  // required for the operation's execution. For example, the directory
-  // to be deleted is non-empty, an rmdir operation is applied to
-  // a non-directory, etc.
+  // StatusCode::kFailedPrecondition
   //
-  // A litmus test that may help a service implementer in deciding
-  // between `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
+  // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the
+  // operation was rejected because the system is not in a state required for
+  // the operation's execution. For example, a directory to be deleted may be
+  // non-empty, an "rmdir" operation is applied to a non-directory, etc.
+  //
+  // Some guidelines that may help a service implementer in deciding between
+  // `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
+  //
   //  (a) Use `kUnavailable` if the client can retry just the failing call.
-  //  (b) Use `kAborted` if the client should retry at a higher-level
-  //      (such as when a client-specified test-and-set fails, indicating the
-  //      client should restart a read-modify-write sequence).
+  //  (b) Use `kAborted` if the client should retry at a higher transaction
+  //      level (such as when a client-specified test-and-set fails, indicating
+  //      the client should restart a read-modify-write sequence).
   //  (c) Use `kFailedPrecondition` if the client should not retry until
   //      the system state has been explicitly fixed. For example, if an "rmdir"
   //      fails because the directory is non-empty, `kFailedPrecondition`
@@ -97,15 +188,21 @@
   //      the files are deleted from the directory.
   kFailedPrecondition = 9,
 
-  // The operation was aborted, typically due to a concurrency issue such as
-  // a sequencer check failure or transaction abort.
+  // StatusCode::kAborted
   //
-  // See litmus test above for deciding between `kFailedPrecondition`,
+  // kAborted (gRPC code "ABORTED") indicates the operation was aborted,
+  // typically due to a concurrency issue such as a sequencer check failure or a
+  // failed transaction.
+  //
+  // See the guidelines above for deciding between `kFailedPrecondition`,
   // `kAborted`, and `kUnavailable`.
   kAborted = 10,
 
-  // The operation was attempted past the valid range, such as seeking or
-  // reading past end-of-file.
+  // StatusCode::kOutOfRange
+  //
+  // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
+  // attempted past the valid range, such as seeking or reading past an
+  // end-of-file.
   //
   // Unlike `kInvalidArgument`, this error indicates a problem that may
   // be fixed if the system state changes. For example, a 32-bit file
@@ -121,175 +218,314 @@
   // they are done.
   kOutOfRange = 11,
 
-  // The operation is not implemented or is not supported/enabled in this
-  // service.
+  // StatusCode::kUnimplemented
+  //
+  // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not
+  // implemented or supported in this service. In this case, the operation
+  // should not be re-attempted.
   kUnimplemented = 12,
 
-  // Internal errors. This means that some invariants expected by the
-  // underlying system have been broken. This error code is reserved
-  // for serious errors.
+  // StatusCode::kInternal
+  //
+  // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred
+  // and some invariants expected by the underlying system have not been
+  // satisfied. This error code is reserved for serious errors.
   kInternal = 13,
 
-  // The service is currently unavailable. This is most likely a
-  // transient condition, which can be corrected by retrying with
-  // a backoff. Note that it is not always safe to retry
-  // non-idempotent operations.
+  // StatusCode::kUnavailable
   //
-  // See litmus test above for deciding between `kFailedPrecondition`,
+  // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently
+  // unavailable and that this is most likely a transient condition. An error
+  // such as this can be corrected by retrying with a backoff scheme. Note that
+  // it is not always safe to retry non-idempotent operations.
+  //
+  // See the guidelines above for deciding between `kFailedPrecondition`,
   // `kAborted`, and `kUnavailable`.
   kUnavailable = 14,
 
-  // Unrecoverable data loss or corruption.
+  // StatusCode::kDataLoss
+  //
+  // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or
+  // corruption has occurred. As this error is serious, proper alerting should
+  // be attached to errors such as this.
   kDataLoss = 15,
 
-  // The request does not have valid authentication credentials for the
-  // operation.
+  // StatusCode::kUnauthenticated
+  //
+  // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request
+  // does not have valid authentication credentials for the operation. Correct
+  // the authentication and try again.
   kUnauthenticated = 16,
 
-  // An extra enum entry to prevent people from writing code that
-  // fails to compile when a new code is added.
+  // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_
   //
-  // Nobody should ever reference this enumeration entry. In particular,
-  // if you write C++ code that switches on this enumeration, add a default:
-  // case instead of a case that mentions this enumeration entry.
+  // NOTE: this error code entry should not be used and you should not rely on
+  // its value, which may change.
   //
-  // Nobody should rely on the value (currently 20) listed here.  It
-  // may change in the future.
+  // The purpose of this enumerated value is to force people who handle status
+  // codes with `switch()` statements to *not* simply enumerate all possible
+  // values, but instead provide a "default:" case. Providing such a default
+  // case ensures that code will compile when new codes are added.
   kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20
 };
 
+// StatusCodeToString()
+//
 // Returns the name for the status code, or "" if it is an unknown value.
 std::string StatusCodeToString(StatusCode code);
 
+// operator<<
+//
 // Streams StatusCodeToString(code) to `os`.
 std::ostream& operator<<(std::ostream& os, StatusCode code);
 
-namespace status_internal {
-
-// Container for status payloads.
-struct Payload {
-  std::string type_url;
-  absl::Cord payload;
-};
-
-using Payloads = absl::InlinedVector<Payload, 1>;
-
-// Reference-counted representation of Status data.
-struct StatusRep {
-  std::atomic<int32_t> ref;
-  absl::StatusCode code;
-  std::string message;
-  std::unique_ptr<status_internal::Payloads> payloads;
-};
-
-absl::StatusCode MapToLocalCode(int value);
-}  // namespace status_internal
-
+// absl::Status
+//
+// The `absl::Status` class is generally used to gracefully handle errors
+// across API boundaries (and in particular across RPC boundaries). Some of
+// these errors may be recoverable, but others may not. Most
+// functions which can produce a recoverable error should be designed to return
+// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds
+// either an object of type `T` or an error).
+//
+// API developers should construct their functions to return `absl::OkStatus()`
+// upon success, or an `absl::StatusCode` upon another type of error (e.g
+// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience
+// functions to constuct each status code.
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+//   ...
+//   // encounter error
+//   if (error condition) {
+//     // Construct an absl::StatusCode::kInvalidArgument error
+//     return absl::InvalidArgumentError("bad mode");
+//   }
+//   // else, return OK
+//   return absl::OkStatus();
+// }
+//
+// Users handling status error codes should prefer checking for an OK status
+// using the `ok()` member function. Handling multiple error codes may justify
+// use of switch statement, but only check for error codes you know how to
+// handle; do not try to exhaustively match against all canonical error codes.
+// Errors that cannot be handled should be logged and/or propagated for higher
+// levels to deal with. If you do use a switch statement, make sure that you
+// also provide a `default:` switch case, so that code does not break as other
+// canonical codes are added to the API.
+//
+// Example:
+//
+//   absl::Status result = DoSomething();
+//   if (!result.ok()) {
+//     LOG(ERROR) << result;
+//   }
+//
+//   // Provide a default if switching on multiple error codes
+//   switch (result.code()) {
+//     // The user hasn't authenticated. Ask them to reauth
+//     case absl::StatusCode::kUnauthenticated:
+//       DoReAuth();
+//       break;
+//     // The user does not have permission. Log an error.
+//     case absl::StatusCode::kPermissionDenied:
+//       LOG(ERROR) << result;
+//       break;
+//     // Propagate the error otherwise.
+//     default:
+//       return true;
+//   }
+//
+// An `absl::Status` can optionally include a payload with more information
+// about the error. Typically, this payload serves one of several purposes:
+//
+//   * It may provide more fine-grained semantic information about the error to
+//     facilitate actionable remedies.
+//   * It may provide human-readable contexual information that is more
+//     appropriate to display to an end user.
+//
+// Example:
+//
+//   absl::Status result = DoSomething();
+//   // Inform user to retry after 30 seconds
+//   // See more error details in googleapis/google/rpc/error_details.proto
+//   if (absl::IsResourceExhausted(result)) {
+//     google::rpc::RetryInfo info;
+//     info.retry_delay().seconds() = 30;
+//     // Payloads require a unique key (a URL to ensure no collisions with
+//     // other payloads), and an `absl::Cord` to hold the encoded data.
+//     absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo";
+//     result.SetPayload(url, info.SerializeAsCord());
+//     return result;
+//   }
+//
 class ABSL_MUST_USE_RESULT Status final {
  public:
-  // Creates an OK status with no message or payload.
+  // Constructors
+
+  // This default constructor creates an OK status with no message or payload.
+  // Avoid this constructor and prefer explicit construction of an OK status
+  // with `absl::OkStatus()`.
   Status();
 
-  // Create a status in the canonical error space with the specified code and
-  // error message.  If `code == absl::StatusCode::kOk`, `msg` is ignored and an
-  // object identical to an OK status is constructed.
+  // Creates a status in the canonical error space with the specified
+  // `absl::StatusCode` and error message.  If `code == absl::StatusCode::kOk`,
+  // `msg` is ignored and an object identical to an OK status is constructed.
   //
-  // `msg` must be in UTF-8. The implementation may complain (e.g.,
+  // The `msg` string must be in UTF-8. The implementation may complain (e.g.,
   // by printing a warning) if it is not.
   Status(absl::StatusCode code, absl::string_view msg);
 
   Status(const Status&);
   Status& operator=(const Status& x);
 
-  // Move operations.
+  // Move operators
+
   // The moved-from state is valid but unspecified.
   Status(Status&&) noexcept;
   Status& operator=(Status&&);
 
   ~Status();
 
-  // If `this->ok()`, stores `new_status` into *this. If `!this->ok()`,
-  // preserves the current data. May, in the future, augment the current status
-  // with additional information about `new_status`.
+  // Status::Update()
   //
-  // Convenient way of keeping track of the first error encountered.
-  // Instead of:
-  //   if (overall_status.ok()) overall_status = new_status
-  // Use:
+  // Updates the existing status with `new_status` provided that `this->ok()`.
+  // If the existing status already contains a non-OK error, this update has no
+  // effect and preserves the current data. Note that this behavior may change
+  // in the future to augment a current non-ok status with additional
+  // information about `new_status`.
+  //
+  // `Update()` provides a convenient way of keeping track of the first error
+  // encountered.
+  //
+  // Example:
+  //   // Instead of "if (overall_status.ok()) overall_status = new_status"
   //   overall_status.Update(new_status);
   //
-  // Style guide exception for rvalue reference granted in CL 153567220.
   void Update(const Status& new_status);
   void Update(Status&& new_status);
 
-  // Returns true if the Status is OK.
+  // Status::ok()
+  //
+  // Returns `true` if `this->ok()`. Prefer checking for an OK status using this
+  // member function.
   ABSL_MUST_USE_RESULT bool ok() const;
 
-  // Returns the (canonical) error code.
+  // Status::code()
+  //
+  // Returns the canonical error code of type `absl::StatusCode` of this status.
   absl::StatusCode code() const;
 
-  // Returns the raw (canonical) error code which could be out of the range of
-  // the local `absl::StatusCode` enum. NOTE: This should only be called when
-  // converting to wire format. Use `code` for error handling.
+  // Status::raw_code()
+  //
+  // Returns a raw (canonical) error code corresponding to the enum value of
+  // `google.rpc.Code` definitions within
+  // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto.
+  // These values could be out of the range of canonical `absl::StatusCode`
+  // enum values.
+  //
+  // NOTE: This function should only be called when converting to an associated
+  // wire format. Use `Status::code()` for error handling.
   int raw_code() const;
 
-  // Returns the error message.  Note: prefer ToString() for debug logging.
-  // This message rarely describes the error code.  It is not unusual for the
-  // error message to be the empty string.
+  // Status::message()
+  //
+  // Returns the error message associated with this error code, if available.
+  // Note that this message rarely describes the error code.  It is not unusual
+  // for the error message to be the empty string. As a result, prefer
+  // `Status::ToString()` for debug logging.
   absl::string_view message() const;
 
   friend bool operator==(const Status&, const Status&);
   friend bool operator!=(const Status&, const Status&);
 
-  // Returns a combination of the error code name, the message and the payloads.
-  // You can expect the code name and the message to be substrings of the
-  // result, and the payloads to be printed by the registered printer extensions
-  // if they are recognized.
-  // WARNING: Do not depend on the exact format of the result of `ToString()`
-  // which is subject to change.
+  // Status::ToString()
+  //
+  // Returns a combination of the error code name, the message and any
+  // associated payload messages. This string is designed simply to be human
+  // readable and its exact format should not be load bearing. Do not depend on
+  // the exact format of the result of `ToString()` which is subject to change.
+  //
+  // The printed code name and the message are generally substrings of the
+  // result, and the payloads to be printed use the status payload printer
+  // mechanism (which is internal).
   std::string ToString() const;
 
+  // Status::IgnoreError()
+  //
   // Ignores any errors. This method does nothing except potentially suppress
   // complaints from any tools that are checking that errors are not dropped on
   // the floor.
   void IgnoreError() const;
 
-  // Swap the contents of `a` with `b`
+  // swap()
+  //
+  // Swap the contents of one status with another.
   friend void swap(Status& a, Status& b);
 
-  // Payload management APIs
+  //----------------------------------------------------------------------------
+  // Payload Management APIs
+  //----------------------------------------------------------------------------
 
-  // Type URL should be unique and follow the naming convention below:
-  // The idea of type URL comes from `google.protobuf.Any`
-  // (https://developers.google.com/protocol-buffers/docs/proto3#any). The
-  // type URL should be globally unique and follow the format of URL
-  // (https://en.wikipedia.org/wiki/URL). The default type URL for a given
-  // protobuf message type is "type.googleapis.com/packagename.messagename". For
-  // other custom wire formats, users should define the format of type URL in a
-  // similar practice so as to minimize the chance of conflict between type
-  // URLs. Users should make sure that the type URL can be mapped to a concrete
+  // A payload may be attached to a status to provide additional context to an
+  // error that may not be satisifed by an existing `absl::StatusCode`.
+  // Typically, this payload serves one of several purposes:
+  //
+  //   * It may provide more fine-grained semantic information about the error
+  //     to facilitate actionable remedies.
+  //   * It may provide human-readable contexual information that is more
+  //     appropriate to display to an end user.
+  //
+  // A payload consists of a [key,value] pair, where the key is a string
+  // referring to a unique "type URL" and the value is an object of type
+  // `absl::Cord` to hold the contextual data.
+  //
+  // The "type URL" should be unique and follow the format of a URL
+  // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some
+  // documentation or schema on how to interpret its associated data. For
+  // example, the default type URL for a protobuf message type is
+  // "type.googleapis.com/packagename.messagename". Other custom wire formats
+  // should define the format of type URL in a similar practice so as to
+  // minimize the chance of conflict between type URLs.
+  // Users should ensure that the type URL can be mapped to a concrete
   // C++ type if they want to deserialize the payload and read it effectively.
+  //
+  // To attach a payload to a status object, call `Status::SetPayload()`,
+  // passing it the type URL and an `absl::Cord` of associated data. Similarly,
+  // to extract the payload from a status, call `Status::GetPayload()`. You
+  // may attach multiple payloads (with differing type URLs) to any given
+  // status object, provided that the status is currently exhibiting an error
+  // code (i.e. is not OK).
 
-  // Gets the payload based for `type_url` key, if it is present.
+  // Status::GetPayload()
+  //
+  // Gets the payload of a status given its unique `type_url` key, if present.
   absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
 
-  // Sets the payload for `type_url` key for a non-ok status, overwriting any
-  // existing payload for `type_url`.
+  // Status::SetPayload()
   //
-  // NOTE: Does nothing if the Status is ok.
+  // Sets the payload for a non-ok status using a `type_url` key, overwriting
+  // any existing payload for that `type_url`.
+  //
+  // NOTE: This function does nothing if the Status is ok.
   void SetPayload(absl::string_view type_url, absl::Cord payload);
 
-  // Erases the payload corresponding to the `type_url` key.  Returns true if
+  // Status::ErasePayload()
+  //
+  // Erases the payload corresponding to the `type_url` key.  Returns `true` if
   // the payload was present.
   bool ErasePayload(absl::string_view type_url);
 
-  // Iterates over the stored payloads and calls `visitor(type_key, payload)`
-  // for each one.
+  // Status::ForEachPayload()
   //
-  // NOTE: The order of calls to `visitor` is not specified and may change at
+  // Iterates over the stored payloads and calls the
+  // `visitor(type_key, payload)` callable for each one.
+  //
+  // NOTE: The order of calls to `visitor()` is not specified and may change at
   // any time.
   //
-  // NOTE: Any mutation on the same 'Status' object during visitation is
+  // NOTE: Any mutation on the same 'absl::Status' object during visitation is
   // forbidden and could result in undefined behavior.
   void ForEachPayload(
       const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
@@ -358,14 +594,93 @@
   uintptr_t rep_;
 };
 
-// Returns an OK status, equivalent to a default constructed instance.
+// OkStatus()
+//
+// Returns an OK status, equivalent to a default constructed instance. Prefer
+// usage of `absl::OkStatus()` when constructing such an OK status.
 Status OkStatus();
 
+// operator<<()
+//
 // Prints a human-readable representation of `x` to `os`.
 std::ostream& operator<<(std::ostream& os, const Status& x);
 
-// -----------------------------------------------------------------
+// IsAborted()
+// IsAlreadyExists()
+// IsCancelled()
+// IsDataLoss()
+// IsDeadlineExceeded()
+// IsFailedPrecondition()
+// IsInternal()
+// IsInvalidArgument()
+// IsNotFound()
+// IsOutOfRange()
+// IsPermissionDenied()
+// IsResourceExhausted()
+// IsUnauthenticated()
+// IsUnavailable()
+// IsUnimplemented()
+// IsUnknown()
+//
+// These convenience functions return `true` if a given status matches the
+// `absl::StatusCode` error code of its associated function.
+ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
+ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
+ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
+ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
+ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
+ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
+ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
+
+// AbortedError()
+// AlreadyExistsError()
+// CancelledError()
+// DataLossError()
+// DeadlineExceededError()
+// FailedPreconditionError()
+// InternalError()
+// InvalidArgumentError()
+// NotFoundError()
+// OutOfRangeError()
+// PermissionDeniedError()
+// ResourceExhaustedError()
+// UnauthenticatedError()
+// UnavailableError()
+// UnimplementedError()
+// UnknownError()
+//
+// These convenience functions create an `absl::Status` object with an error
+// code as indicated by the associated function name, using the error message
+// passed in `message`.
+Status AbortedError(absl::string_view message);
+Status AlreadyExistsError(absl::string_view message);
+Status CancelledError(absl::string_view message);
+Status DataLossError(absl::string_view message);
+Status DeadlineExceededError(absl::string_view message);
+Status FailedPreconditionError(absl::string_view message);
+Status InternalError(absl::string_view message);
+Status InvalidArgumentError(absl::string_view message);
+Status NotFoundError(absl::string_view message);
+Status OutOfRangeError(absl::string_view message);
+Status PermissionDeniedError(absl::string_view message);
+Status ResourceExhaustedError(absl::string_view message);
+Status UnauthenticatedError(absl::string_view message);
+Status UnavailableError(absl::string_view message);
+Status UnimplementedError(absl::string_view message);
+Status UnknownError(absl::string_view message);
+
+//------------------------------------------------------------------------------
 // Implementation details follow
+//------------------------------------------------------------------------------
 
 inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {}
 
@@ -491,50 +806,11 @@
 
 inline Status OkStatus() { return Status(); }
 
-// Each of the functions below creates a Status object with a particular error
-// code and the given message. The error code of the returned status object
-// matches the name of the function.
-Status AbortedError(absl::string_view message);
-Status AlreadyExistsError(absl::string_view message);
-Status CancelledError(absl::string_view message);
-Status DataLossError(absl::string_view message);
-Status DeadlineExceededError(absl::string_view message);
-Status FailedPreconditionError(absl::string_view message);
-Status InternalError(absl::string_view message);
-Status InvalidArgumentError(absl::string_view message);
-Status NotFoundError(absl::string_view message);
-Status OutOfRangeError(absl::string_view message);
-Status PermissionDeniedError(absl::string_view message);
-Status ResourceExhaustedError(absl::string_view message);
-Status UnauthenticatedError(absl::string_view message);
-Status UnavailableError(absl::string_view message);
-Status UnimplementedError(absl::string_view message);
-Status UnknownError(absl::string_view message);
-
 // Creates a `Status` object with the `absl::StatusCode::kCancelled` error code
 // and an empty message. It is provided only for efficiency, given that
 // message-less kCancelled errors are common in the infrastructure.
 inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
 
-// Each of the functions below returns true if the given status matches the
-// error code implied by the function's name.
-ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
-ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
-ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
-ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
-ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
-ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
-ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
-ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
-ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
-ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
-ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
-ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
-
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/status/statusor.cc b/absl/status/statusor.cc
new file mode 100644
index 0000000..b954b45
--- /dev/null
+++ b/absl/status/statusor.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/status/statusor.h"
+
+#include <cstdlib>
+#include <utility>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
+    : status_(std::move(status)) {}
+
+BadStatusOrAccess::~BadStatusOrAccess() = default;
+const char* BadStatusOrAccess::what() const noexcept {
+  return "Bad StatusOr access";
+}
+
+const absl::Status& BadStatusOrAccess::status() const { return status_; }
+
+namespace internal_statusor {
+
+void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
+  const char* kMessage =
+      "An OK status is not a valid constructor argument to StatusOr<T>";
+#ifdef NDEBUG
+  ABSL_INTERNAL_LOG(ERROR, kMessage);
+#else
+  ABSL_INTERNAL_LOG(FATAL, kMessage);
+#endif
+  // In optimized builds, we will fall back to InternalError.
+  *status = absl::InternalError(kMessage);
+}
+
+void Helper::Crash(const absl::Status& status) {
+  ABSL_INTERNAL_LOG(
+      FATAL,
+      absl::StrCat("Attempting to fetch value instead of handling error ",
+                   status.ToString()));
+}
+
+void ThrowBadStatusOrAccess(absl::Status status) {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  throw absl::BadStatusOrAccess(std::move(status));
+#else
+  ABSL_INTERNAL_LOG(
+      FATAL,
+      absl::StrCat("Attempting to fetch value instead of handling error ",
+                   status.ToString()));
+  std::abort();
+#endif
+}
+
+}  // namespace internal_statusor
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/status/statusor.h b/absl/status/statusor.h
new file mode 100644
index 0000000..469d486
--- /dev/null
+++ b/absl/status/statusor.h
@@ -0,0 +1,760 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+//
+// -----------------------------------------------------------------------------
+// File: statusor.h
+// -----------------------------------------------------------------------------
+//
+// An `absl::StatusOr<T>` represents a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` will either contain an
+// object of type `T` (indicating a successful operation), or an error (of type
+// `absl::Status`) explaining why such a value is not present.
+//
+// In general, check the success of an operation returning an
+// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()`
+// member function.
+//
+// Example:
+//
+//   StatusOr<Foo> result = Calculation();
+//   if (result.ok()) {
+//     result->DoSomethingCool();
+//   } else {
+//     LOG(ERROR) << result.status();
+//   }
+#ifndef ABSL_STATUS_STATUSOR_H_
+#define ABSL_STATUS_STATUSOR_H_
+
+#include <exception>
+#include <initializer_list>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+#include "absl/status/internal/statusor_internal.h"
+#include "absl/status/status.h"
+#include "absl/types/variant.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// BadStatusOrAccess
+//
+// This class defines the type of object to throw (if exceptions are enabled),
+// when accessing the value of an `absl::StatusOr<T>` object that does not
+// contain a value. This behavior is analogous to that of
+// `std::bad_optional_access` in the case of accessing an invalid
+// `std::optional` value.
+//
+// Example:
+//
+// try {
+//   absl::StatusOr<int> v = FetchInt();
+//   DoWork(v.value());  // Accessing value() when not "OK" may throw
+// } catch (absl::BadStatusOrAccess& ex) {
+//   LOG(ERROR) << ex.status();
+// }
+class BadStatusOrAccess : public std::exception {
+ public:
+  explicit BadStatusOrAccess(absl::Status status);
+  ~BadStatusOrAccess() override;
+
+  // BadStatusOrAccess::what()
+  //
+  // Returns the associated explanatory string of the `absl::StatusOr<T>`
+  // object's error code. This function only returns the string literal "Bad
+  // StatusOr Access" for cases when evaluating general exceptions.
+  //
+  // The pointer of this string is guaranteed to be valid until any non-const
+  // function is invoked on the exception object.
+  const char* what() const noexcept override;
+
+  // BadStatusOrAccess::status()
+  //
+  // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's
+  // error.
+  const absl::Status& status() const;
+
+ private:
+  absl::Status status_;
+};
+
+// Returned StatusOr objects may not be ignored.
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+// absl::StatusOr<T>
+//
+// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` models an object that is
+// either a usable object, or an error (of type `absl::Status`) explaining why
+// such an object is not present. An `absl::StatusOr<T>` is typically the return
+// value of a function which may fail.
+//
+// An `absl::StatusOr<T>` can never hold an "OK" status (an
+// `absl::StatusCode::kOk` value); instead, the presence of an object of type
+// `T` indicates success. Instead of checking for a `kOk` value, use the
+// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code
+// readability, that using the `ok()` function is preferred for `absl::Status`
+// as well.)
+//
+// Example:
+//
+//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+//   if (result.ok()) {
+//     result->DoSomethingCool();
+//   } else {
+//     LOG(ERROR) << result.status();
+//   }
+//
+// Accessing the object held by an `absl::StatusOr<T>` should be performed via
+// `operator*` or `operator->`, after a call to `ok()` confirms that the
+// `absl::StatusOr<T>` holds an object of type `T`:
+//
+// Example:
+//
+//   absl::StatusOr<int> i = GetCount();
+//   if (i.ok()) {
+//     updated_total += *i
+//   }
+//
+// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
+// throw an exception if exceptions are enabled or terminate the process when
+// execeptions are not enabled.
+//
+// Example:
+//
+//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+//   const Foo& foo = result.value();    // Crash/exception if no value present
+//   foo.DoSomethingCool();
+//
+// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other
+// pointer value, and the result will be that `ok()` returns `true` and
+// `value()` returns `nullptr`. Checking the value of pointer in an
+// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a
+// value is present and that value is not null:
+//
+//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+//  if (!result.ok()) {
+//    LOG(ERROR) << result.status();
+//  } else if (*result == nullptr) {
+//    LOG(ERROR) << "Unexpected null pointer";
+//  } else {
+//    (*result)->DoSomethingCool();
+//  }
+//
+// Example factory implementation returning StatusOr<T>:
+//
+//  StatusOr<Foo> FooFactory::MakeFoo(int arg) {
+//    if (arg <= 0) {
+//      return absl::Status(absl::StatusCode::kInvalidArgument,
+//                          "Arg must be positive");
+//    }
+//    return Foo(arg);
+//  }
+template <typename T>
+class StatusOr : private internal_statusor::StatusOrData<T>,
+                 private internal_statusor::CopyCtorBase<T>,
+                 private internal_statusor::MoveCtorBase<T>,
+                 private internal_statusor::CopyAssignBase<T>,
+                 private internal_statusor::MoveAssignBase<T> {
+  template <typename U>
+  friend class StatusOr;
+
+  typedef internal_statusor::StatusOrData<T> Base;
+
+ public:
+  // StatusOr<T>::value_type
+  //
+  // This instance data provides a generic `value_type` member for use within
+  // generic programming. This usage is analogous to that of
+  // `optional::value_type` in the case of `std::optional`.
+  typedef T value_type;
+
+  // Constructors
+
+  // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown`
+  // status. This constructor is marked 'explicit' to prevent usages in return
+  // values such as 'return {};', under the misconception that
+  // `absl::StatusOr<std::vector<int>>` will be initialized with an empty
+  // vector, instead of an `absl::StatusCode::kUnknown` error code.
+  explicit StatusOr();
+
+  // `StatusOr<T>` is copy constructible if `T` is copy constructible.
+  StatusOr(const StatusOr&) = default;
+  // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy
+  // assignable.
+  StatusOr& operator=(const StatusOr&) = default;
+
+  // `StatusOr<T>` is move constructible if `T` is move constructible.
+  StatusOr(StatusOr&&) = default;
+  // `StatusOr<T>` is moveAssignable if `T` is move constructible and move
+  // assignable.
+  StatusOr& operator=(StatusOr&&) = default;
+
+  // Converting Constructors
+
+  // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T`
+  // is constructible from `U`. To avoid ambiguity, these constructors are
+  // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor
+  // is explicit if and only if the corresponding construction of `T` from `U`
+  // is explicit. (This constructor inherits its explicitness from the
+  // underlying constructor.)
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              std::is_convertible<const U&, T>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  StatusOr(const StatusOr<U>& other)  // NOLINT
+      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              absl::negation<std::is_convertible<const U&, T>>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  explicit StatusOr(const StatusOr<U>& other)
+      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              std::is_convertible<U&&, T>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  StatusOr(StatusOr<U>&& other)  // NOLINT
+      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              absl::negation<std::is_convertible<U&&, T>>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  explicit StatusOr(StatusOr<U>&& other)
+      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+
+  // Converting Assignment Operators
+
+  // Creates an `absl::StatusOr<T>` through assignment from an
+  // `absl::StatusOr<U>` when:
+  //
+  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning
+  //     `U` to `T` directly.
+  //   * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error
+  //      code by destroying `absl::StatusOr<T>`'s value and assigning from
+  //      `absl::StatusOr<U>'
+  //   * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is
+  //      OK by directly initializing `T` from `U`.
+  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error
+  //     code by assigning the `Status` in `absl::StatusOr<U>` to
+  //     `absl::StatusOr<T>`
+  //
+  // These overloads only apply if `absl::StatusOr<T>` is constructible and
+  // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly
+  // assigned from `StatusOr<U>`.
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              std::is_assignable<T, const U&>,
+              absl::negation<
+                  internal_statusor::
+                      IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                          T, U>>>::value,
+          int> = 0>
+  StatusOr& operator=(const StatusOr<U>& other) {
+    this->Assign(other);
+    return *this;
+  }
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              std::is_assignable<T, U&&>,
+              absl::negation<
+                  internal_statusor::
+                      IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                          T, U>>>::value,
+          int> = 0>
+  StatusOr& operator=(StatusOr<U>&& other) {
+    this->Assign(std::move(other));
+    return *this;
+  }
+
+  // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling
+  // this constructor, `this->ok()` will be `false` and calls to `value()` will
+  // crash, or produce an exception if exceptions are enabled.
+  //
+  // The constructor also takes any type `U` that is convertible to
+  // `absl::Status`. This constructor is explicit if an only if `U` is not of
+  // type `absl::Status` and the conversion from `U` to `Status` is explicit.
+  //
+  // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.
+  // In optimized builds, passing absl::OkStatus() here will have the effect
+  // of passing absl::StatusCode::kInternal as a fallback.
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              std::is_convertible<U&&, absl::Status>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_convertible<U&&, absl::Status>>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              std::is_convertible<U&&, absl::Status>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  StatusOr& operator=(U&& v) {
+    this->AssignStatus(std::forward<U>(v));
+    return *this;
+  }
+
+  // Perfect-forwarding value assignment operator.
+
+  // If `*this` contains a `T` value before the call, the contained value is
+  // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized
+  // from `std::forward<U>(v)`.
+  // This function does not participate in overload unless:
+  // 1. `std::is_constructible_v<T, U>` is true,
+  // 2. `std::is_assignable_v<T&, U>` is true.
+  // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false.
+  // 4. Assigning `U` to `T` is not ambiguous:
+  //  If `U` is `StatusOr<V>` and `T` is constructible and assignable from
+  //  both `StatusOr<V>` and `V`, the assignment is considered bug-prone and
+  //  ambiguous thus will fail to compile. For example:
+  //    StatusOr<bool> s1 = true;  // s1.ok() && *s1 == true
+  //    StatusOr<bool> s2 = false;  // s2.ok() && *s2 == false
+  //    s1 = s2;  // ambiguous, `s1 = *s2` or `s1 = bool(s2)`?
+  template <
+      typename U = T,
+      typename = typename std::enable_if<absl::conjunction<
+          std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
+          absl::disjunction<
+              std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>,
+              absl::conjunction<
+                  absl::negation<std::is_convertible<U&&, absl::Status>>,
+                  absl::negation<internal_statusor::
+                                     HasConversionOperatorToStatusOr<T, U&&>>>>,
+          internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type>
+  StatusOr& operator=(U&& v) {
+    this->Assign(std::forward<U>(v));
+    return *this;
+  }
+
+  // Constructs the inner value `T` in-place using the provided args, using the
+  // `T(args...)` constructor.
+  template <typename... Args>
+  explicit StatusOr(absl::in_place_t, Args&&... args);
+  template <typename U, typename... Args>
+  explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+                    Args&&... args);
+
+  // Constructs the inner value `T` in-place using the provided args, using the
+  // `T(U)` (direct-initialization) constructor. This constructor is only valid
+  // if `T` can be constructed from a `U`. Can accept move or copy constructors.
+  //
+  // This constructor is explicit if `U` is not convertible to `T`. To avoid
+  // ambiguity, this constuctor is disabled if `U` is a `StatusOr<J>`, where `J`
+  // is convertible to `T`.
+  template <
+      typename U = T,
+      absl::enable_if_t<
+          absl::conjunction<
+              internal_statusor::IsDirectInitializationValid<T, U&&>,
+              std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
+              absl::disjunction<
+                  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                               T>,
+                  absl::conjunction<
+                      absl::negation<std::is_convertible<U&&, absl::Status>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>>>::value,
+          int> = 0>
+  StatusOr(U&& u)  // NOLINT
+      : StatusOr(absl::in_place, std::forward<U>(u)) {
+  }
+
+  template <
+      typename U = T,
+      absl::enable_if_t<
+          absl::conjunction<
+              internal_statusor::IsDirectInitializationValid<T, U&&>,
+              absl::disjunction<
+                  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                               T>,
+                  absl::conjunction<
+                      absl::negation<std::is_constructible<absl::Status, U&&>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>>,
+              std::is_constructible<T, U&&>,
+              absl::negation<std::is_convertible<U&&, T>>>::value,
+          int> = 0>
+  explicit StatusOr(U&& u)  // NOLINT
+      : StatusOr(absl::in_place, std::forward<U>(u)) {
+  }
+
+  // StatusOr<T>::ok()
+  //
+  // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This
+  // member function is analagous to `absl::Status::ok()` and should be used
+  // similarly to check the status of return values.
+  //
+  // Example:
+  //
+  // StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+  // if (result.ok()) {
+  //    // Handle result
+  // else {
+  //    // Handle error
+  // }
+  ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }
+
+  // StatusOr<T>::status()
+  //
+  // Returns a reference to the current `absl::Status` contained within the
+  // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this
+  // function returns `absl::OkStatus()`.
+  const Status& status() const &;
+  Status status() &&;
+
+  // StatusOr<T>::value()
+  //
+  // Returns a reference to the held value if `this->ok()`. Otherwise, throws
+  // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to
+  // terminate the process if exceptions are disabled.
+  //
+  // If you have already checked the status using `this->ok()`, you probably
+  // want to use `operator*()` or `operator->()` to access the value instead of
+  // `value`.
+  //
+  // Note: for value types that are cheap to copy, prefer simple code:
+  //
+  //   T value = statusor.value();
+  //
+  // Otherwise, if the value type is expensive to copy, but can be left
+  // in the StatusOr, simply assign to a reference:
+  //
+  //   T& value = statusor.value();  // or `const T&`
+  //
+  // Otherwise, if the value type supports an efficient move, it can be
+  // used as follows:
+  //
+  //   T value = std::move(statusor).value();
+  //
+  // The `std::move` on statusor instead of on the whole expression enables
+  // warnings about possible uses of the statusor object after the move.
+  const T& value() const&;
+  T& value() &;
+  const T&& value() const&&;
+  T&& value() &&;
+
+  // StatusOr<T>:: operator*()
+  //
+  // Returns a reference to the current value.
+  //
+  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+  //
+  // Use `this->ok()` to verify that there is a current value within the
+  // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a
+  // similar API that guarantees crashing or throwing an exception if there is
+  // no current value.
+  const T& operator*() const&;
+  T& operator*() &;
+  const T&& operator*() const&&;
+  T&& operator*() &&;
+
+  // StatusOr<T>::operator->()
+  //
+  // Returns a pointer to the current value.
+  //
+  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+  //
+  // Use `this->ok()` to verify that there is a current value.
+  const T* operator->() const;
+  T* operator->();
+
+  // StatusOr<T>::value_or()
+  //
+  // Returns the current value if `this->ok() == true`. Otherwise constructs a
+  // value using the provided `default_value`.
+  //
+  // Unlike `value`, this function returns by value, copying the current value
+  // if necessary. If the value type supports an efficient move, it can be used
+  // as follows:
+  //
+  //   T value = std::move(statusor).value_or(def);
+  //
+  // Unlike with `value`, calling `std::move()` on the result of `value_or` will
+  // still trigger a copy.
+  template <typename U>
+  T value_or(U&& default_value) const&;
+  template <typename U>
+  T value_or(U&& default_value) &&;
+
+  // StatusOr<T>::IgnoreError()
+  //
+  // Ignores any errors. This method does nothing except potentially suppress
+  // complaints from any tools that are checking that errors are not dropped on
+  // the floor.
+  void IgnoreError() const;
+
+  // StatusOr<T>::emplace()
+  //
+  // Reconstructs the inner value T in-place using the provided args, using the
+  // T(args...) constructor. Returns reference to the reconstructed `T`.
+  template <typename... Args>
+  T& emplace(Args&&... args) {
+    if (ok()) {
+      this->Clear();
+      this->MakeValue(std::forward<Args>(args)...);
+    } else {
+      this->MakeValue(std::forward<Args>(args)...);
+      this->status_ = absl::OkStatus();
+    }
+    return this->data_;
+  }
+
+  template <
+      typename U, typename... Args,
+      absl::enable_if_t<
+          std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
+          int> = 0>
+  T& emplace(std::initializer_list<U> ilist, Args&&... args) {
+    if (ok()) {
+      this->Clear();
+      this->MakeValue(ilist, std::forward<Args>(args)...);
+    } else {
+      this->MakeValue(ilist, std::forward<Args>(args)...);
+      this->status_ = absl::OkStatus();
+    }
+    return this->data_;
+  }
+
+ private:
+  using internal_statusor::StatusOrData<T>::Assign;
+  template <typename U>
+  void Assign(const absl::StatusOr<U>& other);
+  template <typename U>
+  void Assign(absl::StatusOr<U>&& other);
+};
+
+// operator==()
+//
+// This operator checks the equality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+  if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
+  return lhs.status() == rhs.status();
+}
+
+// operator!=()
+//
+// This operator checks the inequality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+  return !(lhs == rhs);
+}
+
+//------------------------------------------------------------------------------
+// Implementation details for StatusOr<T>
+//------------------------------------------------------------------------------
+
+// TODO(sbenza): avoid the string here completely.
+template <typename T>
+StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(const StatusOr<U>& other) {
+  if (other.ok()) {
+    this->Assign(*other);
+  } else {
+    this->AssignStatus(other.status());
+  }
+}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(StatusOr<U>&& other) {
+  if (other.ok()) {
+    this->Assign(*std::move(other));
+  } else {
+    this->AssignStatus(std::move(other).status());
+  }
+}
+template <typename T>
+template <typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)
+    : Base(absl::in_place, std::forward<Args>(args)...) {}
+
+template <typename T>
+template <typename U, typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+                      Args&&... args)
+    : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}
+
+template <typename T>
+const Status& StatusOr<T>::status() const & { return this->status_; }
+template <typename T>
+Status StatusOr<T>::status() && {
+  return ok() ? OkStatus() : std::move(this->status_);
+}
+
+template <typename T>
+const T& StatusOr<T>::value() const& {
+  if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+  return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::value() & {
+  if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+  return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::value() const&& {
+  if (!this->ok()) {
+    internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+  }
+  return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::value() && {
+  if (!this->ok()) {
+    internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+  }
+  return std::move(this->data_);
+}
+
+template <typename T>
+const T& StatusOr<T>::operator*() const& {
+  this->EnsureOk();
+  return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::operator*() & {
+  this->EnsureOk();
+  return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::operator*() const&& {
+  this->EnsureOk();
+  return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::operator*() && {
+  this->EnsureOk();
+  return std::move(this->data_);
+}
+
+template <typename T>
+const T* StatusOr<T>::operator->() const {
+  this->EnsureOk();
+  return &this->data_;
+}
+
+template <typename T>
+T* StatusOr<T>::operator->() {
+  this->EnsureOk();
+  return &this->data_;
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) const& {
+  if (ok()) {
+    return this->data_;
+  }
+  return std::forward<U>(default_value);
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) && {
+  if (ok()) {
+    return std::move(this->data_);
+  }
+  return std::forward<U>(default_value);
+}
+
+template <typename T>
+void StatusOr<T>::IgnoreError() const {
+  // no-op
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_STATUSOR_H_
diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc
new file mode 100644
index 0000000..c2e8fb7
--- /dev/null
+++ b/absl/status/statusor_test.cc
@@ -0,0 +1,1811 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/status/statusor.h"
+
+#include <array>
+#include <initializer_list>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+#include "absl/memory/memory.h"
+#include "absl/status/status.h"
+#include "absl/types/any.h"
+#include "absl/utility/utility.h"
+
+namespace {
+
+using ::testing::AllOf;
+using ::testing::AnyWith;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::Ne;
+using ::testing::Not;
+using ::testing::Pointee;
+using ::testing::VariantWith;
+
+#ifdef GTEST_HAS_STATUS_MATCHERS
+using ::testing::status::IsOk;
+using ::testing::status::IsOkAndHolds;
+#else  // GTEST_HAS_STATUS_MATCHERS
+inline const ::absl::Status& GetStatus(const ::absl::Status& status) {
+  return status;
+}
+
+template <typename T>
+inline const ::absl::Status& GetStatus(const ::absl::StatusOr<T>& status) {
+  return status.status();
+}
+
+// Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a
+// reference to StatusOr<T>.
+template <typename StatusOrType>
+class IsOkAndHoldsMatcherImpl
+    : public ::testing::MatcherInterface<StatusOrType> {
+ public:
+  typedef
+      typename std::remove_reference<StatusOrType>::type::value_type value_type;
+
+  template <typename InnerMatcher>
+  explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
+      : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
+            std::forward<InnerMatcher>(inner_matcher))) {}
+
+  void DescribeTo(std::ostream* os) const override {
+    *os << "is OK and has a value that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "isn't OK or has a value that ";
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+  bool MatchAndExplain(
+      StatusOrType actual_value,
+      ::testing::MatchResultListener* result_listener) const override {
+    if (!actual_value.ok()) {
+      *result_listener << "which has status " << actual_value.status();
+      return false;
+    }
+
+    ::testing::StringMatchResultListener inner_listener;
+    const bool matches =
+        inner_matcher_.MatchAndExplain(*actual_value, &inner_listener);
+    const std::string inner_explanation = inner_listener.str();
+    if (!inner_explanation.empty()) {
+      *result_listener << "which contains value "
+                       << ::testing::PrintToString(*actual_value) << ", "
+                       << inner_explanation;
+    }
+    return matches;
+  }
+
+ private:
+  const ::testing::Matcher<const value_type&> inner_matcher_;
+};
+
+// Implements IsOkAndHolds(m) as a polymorphic matcher.
+template <typename InnerMatcher>
+class IsOkAndHoldsMatcher {
+ public:
+  explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
+      : inner_matcher_(std::move(inner_matcher)) {}
+
+  // Converts this polymorphic matcher to a monomorphic matcher of the
+  // given type.  StatusOrType can be either StatusOr<T> or a
+  // reference to StatusOr<T>.
+  template <typename StatusOrType>
+  operator ::testing::Matcher<StatusOrType>() const {  // NOLINT
+    return ::testing::Matcher<StatusOrType>(
+        new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+};
+
+// Monomorphic implementation of matcher IsOk() for a given type T.
+// T can be Status, StatusOr<>, or a reference to either of them.
+template <typename T>
+class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
+ public:
+  void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "is not OK";
+  }
+  bool MatchAndExplain(T actual_value,
+                       ::testing::MatchResultListener*) const override {
+    return GetStatus(actual_value).ok();
+  }
+};
+
+// Implements IsOk() as a polymorphic matcher.
+class IsOkMatcher {
+ public:
+  template <typename T>
+  operator ::testing::Matcher<T>() const {  // NOLINT
+    return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>());
+  }
+};
+
+// Macros for testing the results of functions that return absl::Status or
+// absl::StatusOr<T> (for any type T).
+#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk())
+
+// Returns a gMock matcher that matches a StatusOr<> whose status is
+// OK and whose value matches the inner matcher.
+template <typename InnerMatcher>
+IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds(
+    InnerMatcher&& inner_matcher) {
+  return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
+      std::forward<InnerMatcher>(inner_matcher));
+}
+
+// Returns a gMock matcher that matches a Status or StatusOr<> which is OK.
+inline IsOkMatcher IsOk() { return IsOkMatcher(); }
+#endif  // GTEST_HAS_STATUS_MATCHERS
+
+struct CopyDetector {
+  CopyDetector() = default;
+  explicit CopyDetector(int xx) : x(xx) {}
+  CopyDetector(CopyDetector&& d) noexcept
+      : x(d.x), copied(false), moved(true) {}
+  CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}
+  CopyDetector& operator=(const CopyDetector& c) {
+    x = c.x;
+    copied = true;
+    moved = false;
+    return *this;
+  }
+  CopyDetector& operator=(CopyDetector&& c) noexcept {
+    x = c.x;
+    copied = false;
+    moved = true;
+    return *this;
+  }
+  int x = 0;
+  bool copied = false;
+  bool moved = false;
+};
+
+testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) {
+  return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b),
+               Field(&CopyDetector::copied, c));
+}
+
+class Base1 {
+ public:
+  virtual ~Base1() {}
+  int pad;
+};
+
+class Base2 {
+ public:
+  virtual ~Base2() {}
+  int yetotherpad;
+};
+
+class Derived : public Base1, public Base2 {
+ public:
+  virtual ~Derived() {}
+  int evenmorepad;
+};
+
+class CopyNoAssign {
+ public:
+  explicit CopyNoAssign(int value) : foo(value) {}
+  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+  int foo;
+
+ private:
+  const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {
+  // Uses implicit constructor from T&&
+  return absl::make_unique<int>(0);
+}
+
+TEST(StatusOr, ElementType) {
+  static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), "");
+  static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), "");
+}
+
+TEST(StatusOr, TestMoveOnlyInitialization) {
+  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+  ASSERT_TRUE(thing.ok());
+  EXPECT_EQ(0, **thing);
+  int* previous = thing->get();
+
+  thing = ReturnUniquePtr();
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(0, **thing);
+  EXPECT_NE(previous, thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyValueExtraction) {
+  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+  ASSERT_TRUE(thing.ok());
+  std::unique_ptr<int> ptr = *std::move(thing);
+  EXPECT_EQ(0, *ptr);
+
+  thing = std::move(ptr);
+  ptr = std::move(*thing);
+  EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {
+  std::unique_ptr<int> ptr(*ReturnUniquePtr());
+  EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) {
+  static_assert(
+      std::is_same<const int&&,
+                   decltype(
+                       std::declval<const absl::StatusOr<int>&&>().value())>(),
+      "value() for const temporaries should return const T&&");
+}
+
+TEST(StatusOr, TestMoveOnlyConversion) {
+  absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
+  EXPECT_TRUE(const_thing.ok());
+  EXPECT_EQ(0, **const_thing);
+
+  // Test rvalue converting assignment
+  const int* const_previous = const_thing->get();
+  const_thing = ReturnUniquePtr();
+  EXPECT_TRUE(const_thing.ok());
+  EXPECT_EQ(0, **const_thing);
+  EXPECT_NE(const_previous, const_thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyVector) {
+  // Sanity check that absl::StatusOr<MoveOnly> works in vector.
+  std::vector<absl::StatusOr<std::unique_ptr<int>>> vec;
+  vec.push_back(ReturnUniquePtr());
+  vec.resize(2);
+  auto another_vec = std::move(vec);
+  EXPECT_EQ(0, **another_vec[0]);
+  EXPECT_EQ(absl::UnknownError(""), another_vec[1].status());
+}
+
+TEST(StatusOr, TestDefaultCtor) {
+  absl::StatusOr<int> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+TEST(StatusOr, StatusCtorForwards) {
+  absl::Status status(absl::StatusCode::kInternal, "Some error");
+
+  EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error");
+  EXPECT_EQ(status.message(), "Some error");
+
+  EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(),
+            "Some error");
+  EXPECT_NE(status.message(), "Some error");
+}
+
+// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`,
+// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether
+// exceptions are enabled.
+#ifdef ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status_)    \
+  EXPECT_THROW(                                      \
+      {                                              \
+        try {                                        \
+          statement;                                 \
+        } catch (const absl::BadStatusOrAccess& e) { \
+          EXPECT_EQ(e.status(), status_);            \
+          throw;                                     \
+        }                                            \
+      },                                             \
+      absl::BadStatusOrAccess);
+#else  // ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status) \
+  EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString());
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+TEST(StatusOrDeathTest, TestDefaultCtorValue) {
+  absl::StatusOr<int> thing;
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+  const absl::StatusOr<int> thing2;
+  EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestValueNotOk) {
+  absl::StatusOr<int> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestValueNotOkConst) {
+  const absl::StatusOr<int> thing(absl::UnknownError(""));
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {
+  absl::StatusOr<int*> thing;
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOk) {
+  absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOkConst) {
+  const absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(StatusOrDeathTest, TestStatusCtorStatusOk) {
+  EXPECT_DEBUG_DEATH(
+      {
+        // This will DCHECK
+        absl::StatusOr<int> thing(absl::OkStatus());
+        // In optimized mode, we are actually going to get error::INTERNAL for
+        // status here, rather than crashing, so check that.
+        EXPECT_FALSE(thing.ok());
+        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+      },
+      "An OK status is not a valid constructor argument");
+}
+
+TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) {
+  EXPECT_DEBUG_DEATH(
+      {
+        absl::StatusOr<int*> thing(absl::OkStatus());
+        // In optimized mode, we are actually going to get error::INTERNAL for
+        // status here, rather than crashing, so check that.
+        EXPECT_FALSE(thing.ok());
+        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+      },
+      "An OK status is not a valid constructor argument");
+}
+#endif
+
+TEST(StatusOr, ValueAccessor) {
+  const int kIntValue = 110;
+  {
+    absl::StatusOr<int> status_or(kIntValue);
+    EXPECT_EQ(kIntValue, status_or.value());
+    EXPECT_EQ(kIntValue, std::move(status_or).value());
+  }
+  {
+    absl::StatusOr<CopyDetector> status_or(kIntValue);
+    EXPECT_THAT(status_or,
+                IsOkAndHolds(CopyDetectorHas(kIntValue, false, false)));
+    CopyDetector copy_detector = status_or.value();
+    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true));
+    copy_detector = std::move(status_or).value();
+    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false));
+  }
+}
+
+TEST(StatusOr, BadValueAccess) {
+  const absl::Status kError = absl::CancelledError("message");
+  absl::StatusOr<int> status_or(kError);
+  EXPECT_DEATH_OR_THROW(status_or.value(), kError);
+}
+
+TEST(StatusOr, TestStatusCtor) {
+  absl::StatusOr<int> thing(absl::CancelledError());
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+
+
+TEST(StatusOr, TestValueCtor) {
+  const int kI = 4;
+  const absl::StatusOr<int> thing(kI);
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(kI, *thing);
+}
+
+struct Foo {
+  const int x;
+  explicit Foo(int y) : x(y) {}
+};
+
+TEST(StatusOr, InPlaceConstruction) {
+  EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10),
+              IsOkAndHolds(Field(&Foo::x, 10)));
+}
+
+struct InPlaceHelper {
+  InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)
+      : x(xs), y(std::move(yy)) {}
+  const std::vector<int> x;
+  std::unique_ptr<int> y;
+};
+
+TEST(StatusOr, InPlaceInitListConstruction) {
+  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+                                          absl::make_unique<int>(13));
+  EXPECT_THAT(status_or, IsOkAndHolds(AllOf(
+                             Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)),
+                             Field(&InPlaceHelper::y, Pointee(13)))));
+}
+
+TEST(StatusOr, Emplace) {
+  absl::StatusOr<Foo> status_or_foo(10);
+  status_or_foo.emplace(20);
+  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+  status_or_foo = absl::InvalidArgumentError("msg");
+  EXPECT_FALSE(status_or_foo.ok());
+  EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(status_or_foo.status().message(), "msg");
+  status_or_foo.emplace(20);
+  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+}
+
+TEST(StatusOr, EmplaceInitializerList) {
+  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+                                          absl::make_unique<int>(13));
+  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+                                 Field(&InPlaceHelper::y, Pointee(4)))));
+  status_or = absl::InvalidArgumentError("msg");
+  EXPECT_FALSE(status_or.ok());
+  EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(status_or.status().message(), "msg");
+  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+                                 Field(&InPlaceHelper::y, Pointee(4)))));
+}
+
+TEST(StatusOr, TestCopyCtorStatusOk) {
+  const int kI = 4;
+  const absl::StatusOr<int> original(kI);
+  const absl::StatusOr<int> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOk) {
+  absl::StatusOr<int> original(absl::CancelledError());
+  absl::StatusOr<int> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestCopyCtorNonAssignable) {
+  const int kI = 4;
+  CopyNoAssign value(kI);
+  absl::StatusOr<CopyNoAssign> original(value);
+  absl::StatusOr<CopyNoAssign> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(original->foo, copy->foo);
+}
+
+TEST(StatusOr, TestCopyCtorStatusOKConverting) {
+  const int kI = 4;
+  absl::StatusOr<int> original(kI);
+  absl::StatusOr<double> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_DOUBLE_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
+  absl::StatusOr<int> original(absl::CancelledError());
+  absl::StatusOr<double> copy(original);
+  EXPECT_EQ(copy.status(), original.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOk) {
+  // Copy assignmment
+  {
+    const auto p = std::make_shared<int>(17);
+    absl::StatusOr<std::shared_ptr<int>> source(p);
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = source;
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(p, *source);
+  }
+
+  // Move asssignment
+  {
+    const auto p = std::make_shared<int>(17);
+    absl::StatusOr<std::shared_ptr<int>> source(p);
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = std::move(source);
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(nullptr, *source);
+  }
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOk) {
+  // Copy assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<int> target;
+    target = source;
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(expected, source.status());
+  }
+
+  // Move assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<int> target;
+    target = std::move(source);
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+  }
+}
+
+TEST(StatusOr, TestAssignmentStatusOKConverting) {
+  // Copy assignment
+  {
+    const int kI = 4;
+    absl::StatusOr<int> source(kI);
+
+    absl::StatusOr<double> target;
+    target = source;
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_DOUBLE_EQ(kI, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_DOUBLE_EQ(kI, *source);
+  }
+
+  // Move assignment
+  {
+    const auto p = new int(17);
+    absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p));
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = std::move(source);
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, target->get());
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(nullptr, source->get());
+  }
+}
+
+struct A {
+  int x;
+};
+
+struct ImplicitConstructibleFromA {
+  int x;
+  bool moved;
+  ImplicitConstructibleFromA(const A& a)  // NOLINT
+      : x(a.x), moved(false) {}
+  ImplicitConstructibleFromA(A&& a)  // NOLINT
+      : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ImplicitConvertingConstructor) {
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(
+          absl::StatusOr<A>(A{11})),
+      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11),
+                         Field(&ImplicitConstructibleFromA::moved, true))));
+  absl::StatusOr<A> a(A{12});
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a),
+      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12),
+                         Field(&ImplicitConstructibleFromA::moved, false))));
+}
+
+struct ExplicitConstructibleFromA {
+  int x;
+  bool moved;
+  explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}
+  explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ExplicitConvertingConstructor) {
+  EXPECT_FALSE(
+      (std::is_convertible<const absl::StatusOr<A>&,
+                           absl::StatusOr<ExplicitConstructibleFromA>>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::StatusOr<A>&&,
+                           absl::StatusOr<ExplicitConstructibleFromA>>::value));
+  EXPECT_THAT(
+      absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})),
+      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11),
+                         Field(&ExplicitConstructibleFromA::moved, true))));
+  absl::StatusOr<A> a(A{12});
+  EXPECT_THAT(
+      absl::StatusOr<ExplicitConstructibleFromA>(a),
+      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12),
+                         Field(&ExplicitConstructibleFromA::moved, false))));
+}
+
+struct ImplicitConstructibleFromBool {
+  ImplicitConstructibleFromBool(bool y) : x(y) {}  // NOLINT
+  bool x = false;
+};
+
+struct ConvertibleToBool {
+  explicit ConvertibleToBool(bool y) : x(y) {}
+  operator bool() const { return x; }  // NOLINT
+  bool x = false;
+};
+
+TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>(
+          absl::StatusOr<bool>(false)),
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_FALSE((std::is_convertible<
+                absl::StatusOr<ConvertibleToBool>,
+                absl::StatusOr<ImplicitConstructibleFromBool>>::value));
+}
+
+TEST(StatusOr, BooleanConstructionWithImplicitCasts) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<bool>(false)},
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<bool>(absl::InvalidArgumentError(""))},
+      Not(IsOk()));
+
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})},
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))},
+      Not(IsOk()));
+}
+
+TEST(StatusOr, ConstImplicitCast) {
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+                  absl::StatusOr<const bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+                  absl::StatusOr<const bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+                  absl::StatusOr<bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+                  absl::StatusOr<bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>(
+                  absl::StatusOr<std::string>("foo")),
+              IsOkAndHolds("foo"));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>(
+                  absl::StatusOr<const std::string>("foo")),
+              IsOkAndHolds("foo"));
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>(
+          absl::StatusOr<std::shared_ptr<std::string>>(
+              std::make_shared<std::string>("foo"))),
+      IsOkAndHolds(Pointee(std::string("foo"))));
+}
+
+TEST(StatusOr, ConstExplicitConstruction) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)),
+              IsOkAndHolds(false));
+}
+
+struct ExplicitConstructibleFromInt {
+  int x;
+  explicit ExplicitConstructibleFromInt(int y) : x(y) {}
+};
+
+TEST(StatusOr, ExplicitConstruction) {
+  EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10),
+              IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10)));
+}
+
+TEST(StatusOr, ImplicitConstruction) {
+  // Check implicit casting works.
+  auto status_or =
+      absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10);
+  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, ImplicitConstructionFromInitliazerList) {
+  // Note: dropping the explicit std::initializer_list<int> is not supported
+  // by absl::StatusOr or absl::optional.
+  auto status_or =
+      absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}});
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitConstruction) {
+  auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>(
+      absl::make_unique<Derived>());
+  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) {
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+      absl::InvalidArgumentError("foo");
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error;
+  EXPECT_THAT(a_err, Not(IsOk()));
+
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+  absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref;  // NOLINT
+  EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+  absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err;  // NOLINT
+  EXPECT_THAT(b_err, Not(IsOk()));
+
+  absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or);
+  EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error);
+  EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) {
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+      absl::InvalidArgumentError("foo");
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a;
+  a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  a = status_error;
+  EXPECT_THAT(a, Not(IsOk()));
+
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+  a = cref;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+  a = cref_err;
+  EXPECT_THAT(a, Not(IsOk()));
+  a = std::move(status_or);
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  a = std::move(status_error);
+  EXPECT_THAT(a, Not(IsOk()));
+}
+
+struct Copyable {
+  Copyable() {}
+  Copyable(const Copyable&) {}
+  Copyable& operator=(const Copyable&) { return *this; }
+};
+
+struct MoveOnly {
+  MoveOnly() {}
+  MoveOnly(MoveOnly&&) {}
+  MoveOnly& operator=(MoveOnly&&) { return *this; }
+};
+
+struct NonMovable {
+  NonMovable() {}
+  NonMovable(const NonMovable&) = delete;
+  NonMovable(NonMovable&&) = delete;
+  NonMovable& operator=(const NonMovable&) = delete;
+  NonMovable& operator=(NonMovable&&) = delete;
+};
+
+TEST(StatusOr, CopyAndMoveAbility) {
+  EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);
+  EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);
+  EXPECT_TRUE(std::is_move_constructible<Copyable>::value);
+  EXPECT_TRUE(std::is_move_assignable<Copyable>::value);
+  EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);
+  EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);
+  EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);
+  EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);
+  EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);
+  EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);
+  EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);
+  EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) {
+  absl::StatusOr<absl::any> status_or = CopyDetector(10);
+  absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+  EXPECT_THAT(
+      status_or,
+      IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::any> a = status_or;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  absl::StatusOr<absl::any> a_err = status_error;
+  EXPECT_THAT(a_err, Not(IsOk()));
+
+  const absl::StatusOr<absl::any>& cref = status_or;
+  // No lint for no-change copy.
+  absl::StatusOr<absl::any> b = cref;  // NOLINT
+  EXPECT_THAT(
+      b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::any>& cref_err = status_error;
+  // No lint for no-change copy.
+  absl::StatusOr<absl::any> b_err = cref_err;  // NOLINT
+  EXPECT_THAT(b_err, Not(IsOk()));
+
+  absl::StatusOr<absl::any> c = std::move(status_or);
+  EXPECT_THAT(
+      c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::any> c_err = std::move(status_error);
+  EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) {
+  absl::StatusOr<absl::any> status_or = CopyDetector(10);
+  absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+  absl::StatusOr<absl::any> a;
+  a = status_or;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  a = status_error;
+  EXPECT_THAT(a, Not(IsOk()));
+
+  const absl::StatusOr<absl::any>& cref = status_or;
+  a = cref;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::any>& cref_err = status_error;
+  a = cref_err;
+  EXPECT_THAT(a, Not(IsOk()));
+  a = std::move(status_or);
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  a = std::move(status_error);
+  EXPECT_THAT(a, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) {
+  absl::StatusOr<CopyDetector> status_or(10);
+  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+  absl::StatusOr<CopyDetector> a(status_or);
+  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  const absl::StatusOr<CopyDetector>& cref = status_or;
+  absl::StatusOr<CopyDetector> b(cref);  // NOLINT
+  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  absl::StatusOr<CopyDetector> c(std::move(status_or));
+  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) {
+  absl::StatusOr<CopyDetector> status_or(10);
+  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+  absl::StatusOr<CopyDetector> a;
+  a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  const absl::StatusOr<CopyDetector>& cref = status_or;
+  absl::StatusOr<CopyDetector> b;
+  b = cref;
+  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  absl::StatusOr<CopyDetector> c;
+  c = std::move(status_or);
+  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, AbslAnyAssignment) {
+  EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>,
+                                   absl::StatusOr<int>>::value));
+  absl::StatusOr<absl::any> status_or;
+  status_or = absl::InvalidArgumentError("foo");
+  EXPECT_THAT(status_or, Not(IsOk()));
+}
+
+TEST(StatusOr, ImplicitAssignment) {
+  absl::StatusOr<absl::variant<int, std::string>> status_or;
+  status_or = 10;
+  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, SelfDirectInitAssignment) {
+  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+  status_or = *status_or;
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, ImplicitCastFromInitializerList) {
+  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitAssignment) {
+  absl::StatusOr<std::unique_ptr<Base1>> status_or;
+  status_or = absl::make_unique<Derived>();
+  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, Pointer) {
+  struct A {};
+  struct B : public A {};
+  struct C : private A {};
+
+  EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value));
+  EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value));
+  EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value));
+  EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value));
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
+  // Copy assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<double> target;
+    target = source;
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(expected, source.status());
+  }
+
+  // Move assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<double> target;
+    target = std::move(source);
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+  }
+}
+
+TEST(StatusOr, SelfAssignment) {
+  // Copy-assignment, status OK
+  {
+    // A string long enough that it's likely to defeat any inline representation
+    // optimization.
+    const std::string long_str(128, 'a');
+
+    absl::StatusOr<std::string> so = long_str;
+    so = *&so;
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(long_str, *so);
+  }
+
+  // Copy-assignment, error status
+  {
+    absl::StatusOr<int> so = absl::NotFoundError("taco");
+    so = *&so;
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+
+  // Move-assignment with copyable type, status OK
+  {
+    absl::StatusOr<int> so = 17;
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(17, *so);
+  }
+
+  // Move-assignment with copyable type, error status
+  {
+    absl::StatusOr<int> so = absl::NotFoundError("taco");
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+
+  // Move-assignment with non-copyable type, status OK
+  {
+    const auto raw = new int(17);
+    absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw);
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(raw, so->get());
+  }
+
+  // Move-assignment with non-copyable type, error status
+  {
+    absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco");
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+}
+
+// These types form the overload sets of the constructors and the assignment
+// operators of `MockValue`. They distinguish construction from assignment,
+// lvalue from rvalue.
+struct FromConstructibleAssignableLvalue {};
+struct FromConstructibleAssignableRvalue {};
+struct FromImplicitConstructibleOnly {};
+struct FromAssignableOnly {};
+
+// This class is for testing the forwarding value assignments of `StatusOr`.
+// `from_rvalue` indicates whether the constructor or the assignment taking
+// rvalue reference is called. `from_assignment` indicates whether any
+// assignment is called.
+struct MockValue {
+  // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.
+  MockValue(const FromConstructibleAssignableLvalue&)  // NOLINT
+      : from_rvalue(false), assigned(false) {}
+  // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.
+  MockValue(FromConstructibleAssignableRvalue&&)  // NOLINT
+      : from_rvalue(true), assigned(false) {}
+  // Constructs `MockValue` from `FromImplicitConstructibleOnly`.
+  // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.
+  MockValue(const FromImplicitConstructibleOnly&)  // NOLINT
+      : from_rvalue(false), assigned(false) {}
+  // Assigns `FromConstructibleAssignableLvalue`.
+  MockValue& operator=(const FromConstructibleAssignableLvalue&) {
+    from_rvalue = false;
+    assigned = true;
+    return *this;
+  }
+  // Assigns `FromConstructibleAssignableRvalue` (rvalue only).
+  MockValue& operator=(FromConstructibleAssignableRvalue&&) {
+    from_rvalue = true;
+    assigned = true;
+    return *this;
+  }
+  // Assigns `FromAssignableOnly`, but not constructible from
+  // `FromAssignableOnly`.
+  MockValue& operator=(const FromAssignableOnly&) {
+    from_rvalue = false;
+    assigned = true;
+    return *this;
+  }
+  bool from_rvalue;
+  bool assigned;
+};
+
+// operator=(U&&)
+TEST(StatusOr, PerfectForwardingAssignment) {
+  // U == T
+  constexpr int kValue1 = 10, kValue2 = 20;
+  absl::StatusOr<CopyDetector> status_or;
+  CopyDetector lvalue(kValue1);
+  status_or = lvalue;
+  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true)));
+  status_or = CopyDetector(kValue2);
+  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false)));
+
+  // U != T
+  EXPECT_TRUE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromConstructibleAssignableLvalue&>::value));
+  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                  FromConstructibleAssignableLvalue&&>::value));
+  EXPECT_FALSE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromConstructibleAssignableRvalue&>::value));
+  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                  FromConstructibleAssignableRvalue&&>::value));
+  EXPECT_TRUE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromImplicitConstructibleOnly&>::value));
+  EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                   const FromAssignableOnly&>::value));
+
+  absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});
+  EXPECT_FALSE(from_lvalue->from_rvalue);
+  EXPECT_FALSE(from_lvalue->assigned);
+  from_lvalue = FromConstructibleAssignableLvalue{};
+  EXPECT_FALSE(from_lvalue->from_rvalue);
+  EXPECT_TRUE(from_lvalue->assigned);
+
+  absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});
+  EXPECT_TRUE(from_rvalue->from_rvalue);
+  EXPECT_FALSE(from_rvalue->assigned);
+  from_rvalue = FromConstructibleAssignableRvalue{};
+  EXPECT_TRUE(from_rvalue->from_rvalue);
+  EXPECT_TRUE(from_rvalue->assigned);
+
+  absl::StatusOr<MockValue> from_implicit_constructible(
+      FromImplicitConstructibleOnly{});
+  EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+  EXPECT_FALSE(from_implicit_constructible->assigned);
+  // construct a temporary `StatusOr` object and invoke the `StatusOr` move
+  // assignment operator.
+  from_implicit_constructible = FromImplicitConstructibleOnly{};
+  EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+  EXPECT_FALSE(from_implicit_constructible->assigned);
+}
+
+TEST(StatusOr, TestStatus) {
+  absl::StatusOr<int> good(4);
+  EXPECT_TRUE(good.ok());
+  absl::StatusOr<int> bad(absl::CancelledError());
+  EXPECT_FALSE(bad.ok());
+  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, OperatorStarRefQualifiers) {
+  static_assert(
+      std::is_same<const int&,
+                   decltype(*std::declval<const absl::StatusOr<int>&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<const int&&,
+                   decltype(*std::declval<const absl::StatusOr<int>&&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(),
+      "Unexpected ref-qualifiers");
+}
+
+TEST(StatusOr, OperatorStar) {
+  const absl::StatusOr<std::string> const_lvalue("hello");
+  EXPECT_EQ("hello", *const_lvalue);
+
+  absl::StatusOr<std::string> lvalue("hello");
+  EXPECT_EQ("hello", *lvalue);
+
+  // Note: Recall that std::move() is equivalent to a static_cast to an rvalue
+  // reference type.
+  const absl::StatusOr<std::string> const_rvalue("hello");
+  EXPECT_EQ("hello", *std::move(const_rvalue));  // NOLINT
+
+  absl::StatusOr<std::string> rvalue("hello");
+  EXPECT_EQ("hello", *std::move(rvalue));
+}
+
+TEST(StatusOr, OperatorArrowQualifiers) {
+  static_assert(
+      std::is_same<
+          const int*,
+          decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          const int*,
+          decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(),
+      "Unexpected qualifiers");
+}
+
+TEST(StatusOr, OperatorArrow) {
+  const absl::StatusOr<std::string> const_lvalue("hello");
+  EXPECT_EQ(std::string("hello"), const_lvalue->c_str());
+
+  absl::StatusOr<std::string> lvalue("hello");
+  EXPECT_EQ(std::string("hello"), lvalue->c_str());
+}
+
+TEST(StatusOr, RValueStatus) {
+  absl::StatusOr<int> so(absl::NotFoundError("taco"));
+  const absl::Status s = std::move(so).status();
+
+  EXPECT_EQ(s.code(), absl::StatusCode::kNotFound);
+  EXPECT_EQ(s.message(), "taco");
+
+  // Check that !ok() still implies !status().ok(), even after moving out of the
+  // object. See the note on the rvalue ref-qualified status method.
+  EXPECT_FALSE(so.ok());  // NOLINT
+  EXPECT_FALSE(so.status().ok());
+  EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal);
+  EXPECT_EQ(so.status().message(), "Status accessed after move.");
+}
+
+TEST(StatusOr, TestValue) {
+  const int kI = 4;
+  absl::StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestValueConst) {
+  const int kI = 4;
+  const absl::StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestPointerDefaultCtor) {
+  absl::StatusOr<int*> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+
+
+TEST(StatusOr, TestPointerStatusCtor) {
+  absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValueCtor) {
+  const int kI = 4;
+
+  // Construction from a non-null pointer
+  {
+    absl::StatusOr<const int*> so(&kI);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(&kI, *so);
+  }
+
+  // Construction from a null pointer constant
+  {
+    absl::StatusOr<const int*> so(nullptr);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(nullptr, *so);
+  }
+
+  // Construction from a non-literal null pointer
+  {
+    const int* const p = nullptr;
+
+    absl::StatusOr<const int*> so(p);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(nullptr, *so);
+  }
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOk) {
+  const int kI = 0;
+  absl::StatusOr<const int*> original(&kI);
+  absl::StatusOr<const int*> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
+  absl::StatusOr<int*> original(absl::CancelledError());
+  absl::StatusOr<int*> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
+  Derived derived;
+  absl::StatusOr<Derived*> original(&derived);
+  absl::StatusOr<Base2*> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(static_cast<const Base2*>(*original), *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
+  absl::StatusOr<Derived*> original(absl::CancelledError());
+  absl::StatusOr<Base2*> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOk) {
+  const int kI = 0;
+  absl::StatusOr<const int*> source(&kI);
+  absl::StatusOr<const int*> target;
+  target = source;
+  EXPECT_OK(target.status());
+  EXPECT_EQ(*source, *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
+  absl::StatusOr<int*> source(absl::CancelledError());
+  absl::StatusOr<int*> target;
+  target = source;
+  EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
+  Derived derived;
+  absl::StatusOr<Derived*> source(&derived);
+  absl::StatusOr<Base2*> target;
+  target = source;
+  EXPECT_OK(target.status());
+  EXPECT_EQ(static_cast<const Base2*>(*source), *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
+  absl::StatusOr<Derived*> source(absl::CancelledError());
+  absl::StatusOr<Base2*> target;
+  target = source;
+  EXPECT_EQ(target.status(), source.status());
+}
+
+TEST(StatusOr, TestPointerStatus) {
+  const int kI = 0;
+  absl::StatusOr<const int*> good(&kI);
+  EXPECT_TRUE(good.ok());
+  absl::StatusOr<const int*> bad(absl::CancelledError());
+  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValue) {
+  const int kI = 0;
+  absl::StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, TestPointerValueConst) {
+  const int kI = 0;
+  const absl::StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) {
+  using EvilType = std::vector<std::unique_ptr<int>>;
+  static_assert(std::is_copy_constructible<EvilType>::value, "");
+  std::vector<::absl::StatusOr<EvilType>> v(5);
+  v.reserve(v.capacity() + 10);
+  v.resize(v.capacity() + 10);
+}
+
+TEST(StatusOr, ConstPayload) {
+  // A reduced version of a problematic type found in the wild. All of the
+  // operations below should compile.
+  absl::StatusOr<const int> a;
+
+  // Copy-construction
+  absl::StatusOr<const int> b(a);
+
+  // Copy-assignment
+  EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value);
+
+  // Move-construction
+  absl::StatusOr<const int> c(std::move(a));
+
+  // Move-assignment
+  EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value);
+}
+
+TEST(StatusOr, MapToStatusOrUniquePtr) {
+  // A reduced version of a problematic type found in the wild. All of the
+  // operations below should compile.
+  using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>;
+
+  MapType a;
+
+  // Move-construction
+  MapType b(std::move(a));
+
+  // Move-assignment
+  a = std::move(b);
+}
+
+TEST(StatusOr, ValueOrOk) {
+  const absl::StatusOr<int> status_or = 0;
+  EXPECT_EQ(status_or.value_or(-1), 0);
+}
+
+TEST(StatusOr, ValueOrDefault) {
+  const absl::StatusOr<int> status_or = absl::CancelledError();
+  EXPECT_EQ(status_or.value_or(-1), -1);
+}
+
+TEST(StatusOr, MoveOnlyValueOrOk) {
+  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
+                  .value_or(absl::make_unique<int>(-1)),
+              Pointee(0));
+}
+
+TEST(StatusOr, MoveOnlyValueOrDefault) {
+  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError())
+                  .value_or(absl::make_unique<int>(-1)),
+              Pointee(-1));
+}
+
+static absl::StatusOr<int> MakeStatus() { return 100; }
+
+TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); }
+
+TEST(StatusOr, EqualityOperator) {
+  constexpr int kNumCases = 4;
+  std::array<absl::StatusOr<int>, kNumCases> group1 = {
+      absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+      absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+      absl::StatusOr<int>(absl::InternalError("msg"))};
+  std::array<absl::StatusOr<int>, kNumCases> group2 = {
+      absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+      absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+      absl::StatusOr<int>(absl::InternalError("msg"))};
+  for (int i = 0; i < kNumCases; ++i) {
+    for (int j = 0; j < kNumCases; ++j) {
+      if (i == j) {
+        EXPECT_TRUE(group1[i] == group2[j]);
+        EXPECT_FALSE(group1[i] != group2[j]);
+      } else {
+        EXPECT_FALSE(group1[i] == group2[j]);
+        EXPECT_TRUE(group1[i] != group2[j]);
+      }
+    }
+  }
+}
+
+struct MyType {
+  bool operator==(const MyType&) const { return true; }
+};
+
+enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };
+
+// This class has conversion operator to `StatusOr<T>` based on value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusOrConversionBase {};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kImplicit> {
+  operator absl::StatusOr<T>() const& {  // NOLINT
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+  operator absl::StatusOr<T>() && {  // NOLINT
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kExplicit> {
+  explicit operator absl::StatusOr<T>() const& {
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+  explicit operator absl::StatusOr<T>() && {
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+};
+
+// This class has conversion operator to `T` based on the value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct ConversionBase {};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kImplicit> {
+  operator T() const& { return t; }         // NOLINT
+  operator T() && { return std::move(t); }  // NOLINT
+  T t;
+};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kExplicit> {
+  explicit operator T() const& { return t; }
+  explicit operator T() && { return std::move(t); }
+  T t;
+};
+
+// This class has conversion operator to `absl::Status` based on the value of
+// `conv_traits`.
+template <ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusConversionBase {};
+
+template <>
+struct StatusConversionBase<ConvTraits::kImplicit> {
+  operator absl::Status() const& {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+  operator absl::Status() && {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+};
+
+template <>
+struct StatusConversionBase<ConvTraits::kExplicit> {
+  explicit operator absl::Status() const& {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+  explicit operator absl::Status() && {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+};
+
+static constexpr int kConvToStatus = 1;
+static constexpr int kConvToStatusOr = 2;
+static constexpr int kConvToT = 4;
+static constexpr int kConvExplicit = 8;
+
+constexpr ConvTraits GetConvTraits(int bit, int config) {
+  return (config & bit) == 0
+             ? ConvTraits::kNone
+             : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit
+                                              : ConvTraits::kExplicit);
+}
+
+// This class conditionally has conversion operator to `absl::Status`, `T`,
+// `StatusOr<T>`, based on values of the template parameters.
+template <typename T, int config>
+struct CustomType
+    : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>,
+      ConversionBase<T, GetConvTraits(kConvToT, config)>,
+      StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};
+
+struct ConvertibleToAnyStatusOr {
+  template <typename T>
+  operator absl::StatusOr<T>() const {  // NOLINT
+    return absl::InvalidArgumentError("Conversion to absl::StatusOr");
+  }
+};
+
+// Test the rank of overload resolution for `StatusOr<T>` constructor and
+// assignment, from highest to lowest:
+// 1. T/Status
+// 2. U that has conversion operator to absl::StatusOr<T>
+// 3. U that is convertible to Status
+// 4. U that is convertible to T
+TEST(StatusOr, ConstructionFromT) {
+  // Construct absl::StatusOr<T> from T when T is convertible to
+  // absl::StatusOr<T>
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+  // Construct absl::StatusOr<T> from T when T is explicitly convertible to
+  // Status
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(
+        v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor =
+        v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+// Construct absl::StatusOr<T> from U when U is explicitly convertible to T
+TEST(StatusOr, ConstructionFromTypeConvertibleToT) {
+  {
+    CustomType<MyType, kConvToT | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    CustomType<MyType, kConvToT> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+// Construct absl::StatusOr<T> from U when U has explicit conversion operator to
+// absl::StatusOr<T>
+TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) {
+  {
+    CustomType<MyType, kConvToStatusOr | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType,
+               kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit>
+        v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+}
+
+TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) {
+  // Construction fails because conversion to `Status` is explicit.
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+}
+
+TEST(StatusOr, AssignmentFromT) {
+  // Assign to absl::StatusOr<T> from T when T is convertible to
+  // absl::StatusOr<T>
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+  // Assign to absl::StatusOr<T> from T when T is convertible to Status
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToT) {
+  // Assign to absl::StatusOr<T> from U when U is convertible to T
+  {
+    CustomType<MyType, kConvToT> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) {
+  // Assign to absl::StatusOr<T> from U when U has conversion operator to
+  // absl::StatusOr<T>
+  {
+    CustomType<MyType, kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) {
+  // Assign to absl::StatusOr<T> from U when U is convertible to Status
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+}
+
+}  // namespace
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 64a13ce..30a8dd2 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -54,6 +54,7 @@
         "ascii.h",
         "charconv.h",
         "escaping.h",
+        "internal/string_constant.h",
         "match.h",
         "numbers.h",
         "str_cat.h",
@@ -223,6 +224,19 @@
 )
 
 cc_test(
+    name = "string_constant_test",
+    size = "small",
+    srcs = ["internal/string_constant_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strings",
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "string_view_benchmark",
     srcs = ["string_view_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
diff --git a/absl/strings/BUILD.gn b/absl/strings/BUILD.gn
index 327ee49..4495790 100644
--- a/absl/strings/BUILD.gn
+++ b/absl/strings/BUILD.gn
@@ -31,6 +31,7 @@
     "ascii.h",
     "charconv.h",
     "escaping.h",
+    "internal/string_constant.h",
     "match.h",
     "numbers.h",
     "str_cat.h",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index d6c2126..2b994a7 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -21,6 +21,7 @@
     "ascii.h"
     "charconv.h"
     "escaping.h"
+    "internal/string_constant.h"
     "match.h"
     "numbers.h"
     "str_cat.h"
@@ -160,6 +161,19 @@
 
 absl_cc_test(
   NAME
+    string_constant_test
+  SRCS
+    "internal/string_constant_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
     string_view_test
   SRCS
     "string_view_test.cc"
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 763dcc4..9efd135 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -50,16 +50,10 @@
 using ::absl::cord_internal::CordRepExternal;
 using ::absl::cord_internal::CordRepSubstring;
 
-// Various representations that we allow
-enum CordRepKind {
-  CONCAT        = 0,
-  EXTERNAL      = 1,
-  SUBSTRING     = 2,
-
-  // We have different tags for different sized flat arrays,
-  // starting with FLAT
-  FLAT          = 3,
-};
+using ::absl::cord_internal::CONCAT;
+using ::absl::cord_internal::EXTERNAL;
+using ::absl::cord_internal::FLAT;
+using ::absl::cord_internal::SUBSTRING;
 
 namespace cord_internal {
 
@@ -247,6 +241,7 @@
 
   absl::InlinedVector<CordRep*, kInlinedVectorSize> pending;
   while (true) {
+    assert(!rep->refcount.IsImmortal());
     if (rep->tag == CONCAT) {
       CordRepConcat* rep_concat = rep->concat();
       CordRep* right = rep_concat->right;
@@ -262,6 +257,7 @@
       }
     } else if (rep->tag == EXTERNAL) {
       CordRepExternal* rep_external = rep->external();
+      assert(rep_external->releaser_invoker != nullptr);
       rep_external->releaser_invoker(rep_external);
       rep = nullptr;
     } else if (rep->tag == SUBSTRING) {
@@ -447,48 +443,49 @@
                                       bool nullify_tail) {
   static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
 
-  cord_internal::SmallMemmove(data_, data, n, nullify_tail);
-  data_[kMaxInline] = static_cast<char>(n);
+  cord_internal::SmallMemmove(data_.as_chars, data, n, nullify_tail);
+  set_tagged_size(static_cast<char>(n));
 }
 
 inline char* Cord::InlineRep::set_data(size_t n) {
   assert(n <= kMaxInline);
-  memset(data_, 0, sizeof(data_));
-  data_[kMaxInline] = static_cast<char>(n);
-  return data_;
+  ResetToEmpty();
+  set_tagged_size(static_cast<char>(n));
+  return data_.as_chars;
 }
 
 inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) {
-  size_t len = data_[kMaxInline];
-  CordRep* result;
+  size_t len = tagged_size();
   if (len > kMaxInline) {
-    memcpy(&result, data_, sizeof(result));
-  } else {
-    result = NewFlat(len + extra_hint);
-    result->length = len;
-    memcpy(result->data, data_, len);
-    set_tree(result);
+    return data_.as_tree.rep;
   }
+
+  CordRep* result = NewFlat(len + extra_hint);
+  result->length = len;
+  static_assert(kMinFlatLength >= sizeof(data_.as_chars), "");
+  memcpy(result->data, data_.as_chars, sizeof(data_.as_chars));
+  set_tree(result);
   return result;
 }
 
 inline void Cord::InlineRep::reduce_size(size_t n) {
-  size_t tag = data_[kMaxInline];
+  size_t tag = tagged_size();
   assert(tag <= kMaxInline);
   assert(tag >= n);
   tag -= n;
-  memset(data_ + tag, 0, n);
-  data_[kMaxInline] = static_cast<char>(tag);
+  memset(data_.as_chars + tag, 0, n);
+  set_tagged_size(static_cast<char>(tag));
 }
 
 inline void Cord::InlineRep::remove_prefix(size_t n) {
-  cord_internal::SmallMemmove(data_, data_ + n, data_[kMaxInline] - n);
+  cord_internal::SmallMemmove(data_.as_chars, data_.as_chars + n,
+                              tagged_size() - n);
   reduce_size(n);
 }
 
 void Cord::InlineRep::AppendTree(CordRep* tree) {
   if (tree == nullptr) return;
-  size_t len = data_[kMaxInline];
+  size_t len = tagged_size();
   if (len == 0) {
     set_tree(tree);
   } else {
@@ -498,7 +495,7 @@
 
 void Cord::InlineRep::PrependTree(CordRep* tree) {
   assert(tree != nullptr);
-  size_t len = data_[kMaxInline];
+  size_t len = tagged_size();
   if (len == 0) {
     set_tree(tree);
   } else {
@@ -554,11 +551,11 @@
   }
 
   // Try to fit in the inline buffer if possible.
-  size_t inline_length = data_[kMaxInline];
+  size_t inline_length = tagged_size();
   if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) {
-    *region = data_ + inline_length;
+    *region = data_.as_chars + inline_length;
     *size = max_length;
-    data_[kMaxInline] = static_cast<char>(inline_length + max_length);
+    set_tagged_size(static_cast<char>(inline_length + max_length));
     return;
   }
 
@@ -582,11 +579,11 @@
   const size_t max_length = std::numeric_limits<size_t>::max();
 
   // Try to fit in the inline buffer if possible.
-  size_t inline_length = data_[kMaxInline];
+  size_t inline_length = tagged_size();
   if (inline_length < kMaxInline) {
-    *region = data_ + inline_length;
+    *region = data_.as_chars + inline_length;
     *size = kMaxInline - inline_length;
-    data_[kMaxInline] = kMaxInline;
+    set_tagged_size(kMaxInline);
     return;
   }
 
@@ -621,7 +618,7 @@
 void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
   ClearSlow();
 
-  memcpy(data_, src.data_, sizeof(data_));
+  data_ = src.data_;
   if (is_tree()) {
     Ref(tree());
   }
@@ -631,7 +628,7 @@
   if (is_tree()) {
     Unref(tree());
   }
-  memset(data_, 0, sizeof(data_));
+  ResetToEmpty();
 }
 
 // --------------------------------------------------------------------
@@ -735,11 +732,11 @@
 void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
   if (src_size == 0) return;  // memcpy(_, nullptr, 0) is undefined.
   // Try to fit in the inline buffer if possible.
-  size_t inline_length = data_[kMaxInline];
+  size_t inline_length = tagged_size();
   if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) {
     // Append new data to embedded array
-    data_[kMaxInline] = static_cast<char>(inline_length + src_size);
-    memcpy(data_ + inline_length, src_data, src_size);
+    set_tagged_size(static_cast<char>(inline_length + src_size));
+    memcpy(data_.as_chars + inline_length, src_data, src_size);
     return;
   }
 
@@ -762,7 +759,7 @@
     const size_t size2 = inline_length + src_size / 10;
     root = NewFlat(std::max<size_t>(size1, size2));
     appended = std::min(src_size, TagToLength(root->tag) - inline_length);
-    memcpy(root->data, data_, inline_length);
+    memcpy(root->data, data_.as_chars, inline_length);
     memcpy(root->data + inline_length, src_data, appended);
     root->length = inline_length + appended;
     set_tree(root);
@@ -1071,7 +1068,7 @@
   } else if (new_size <= InlineRep::kMaxInline) {
     Cord::ChunkIterator it = chunk_begin();
     it.AdvanceBytes(pos);
-    char* dest = sub_cord.contents_.data_;
+    char* dest = sub_cord.contents_.data_.as_chars;
     size_t remaining_size = new_size;
     while (remaining_size > it->size()) {
       cord_internal::SmallMemmove(dest, it->data(), it->size());
@@ -1080,7 +1077,7 @@
       ++it;
     }
     cord_internal::SmallMemmove(dest, it->data(), remaining_size);
-    sub_cord.contents_.data_[InlineRep::kMaxInline] = new_size;
+    sub_cord.contents_.set_tagged_size(new_size);
   } else {
     sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size));
   }
@@ -1269,9 +1266,9 @@
 // Helper routine. Locates the first flat chunk of the Cord without
 // initializing the iterator.
 inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
-  size_t n = data_[kMaxInline];
+  size_t n = tagged_size();
   if (n <= kMaxInline) {
-    return absl::string_view(data_, n);
+    return absl::string_view(data_.as_chars, n);
   }
 
   CordRep* node = tree();
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index b8b251b..5d5c897 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -79,6 +79,7 @@
 #include "absl/meta/type_traits.h"
 #include "absl/strings/internal/cord_internal.h"
 #include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/internal/string_constant.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 
@@ -624,6 +625,14 @@
     return c.HashFragmented(std::move(hash_state));
   }
 
+  // Create a Cord with the contents of StringConstant<T>::value.
+  // No allocations will be done and no data will be copied.
+  // This is an INTERNAL API and subject to change or removal. This API can only
+  // be used by spelling absl::strings_internal::MakeStringConstant, which is
+  // also an internal API.
+  template <typename T>
+  explicit constexpr Cord(strings_internal::StringConstant<T>);
+
  private:
   friend class CordTestPeer;
   friend bool operator==(const Cord& lhs, const Cord& rhs);
@@ -644,19 +653,19 @@
   // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
   class InlineRep {
    public:
-    static constexpr unsigned char kMaxInline = 15;
+    static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
     static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
-    // Tag byte & kMaxInline means we are storing a pointer.
-    static constexpr unsigned char kTreeFlag = 1 << 4;
-    // Tag byte & kProfiledFlag means we are profiling the Cord.
-    static constexpr unsigned char kProfiledFlag = 1 << 5;
+    static constexpr unsigned char kTreeFlag = cord_internal::kTreeFlag;
+    static constexpr unsigned char kProfiledFlag = cord_internal::kProfiledFlag;
 
-    constexpr InlineRep() : data_{} {}
+    constexpr InlineRep() : data_() {}
     InlineRep(const InlineRep& src);
     InlineRep(InlineRep&& src);
     InlineRep& operator=(const InlineRep& src);
     InlineRep& operator=(InlineRep&& src) noexcept;
 
+    explicit constexpr InlineRep(cord_internal::InlineData data);
+
     void Swap(InlineRep* rhs);
     bool empty() const;
     size_t size() const;
@@ -684,16 +693,16 @@
     void GetAppendRegion(char** region, size_t* size, size_t max_length);
     void GetAppendRegion(char** region, size_t* size);
     bool IsSame(const InlineRep& other) const {
-      return memcmp(data_, other.data_, sizeof(data_)) == 0;
+      return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
     }
     int BitwiseCompare(const InlineRep& other) const {
       uint64_t x, y;
-      // Use memcpy to avoid anti-aliasing issues.
-      memcpy(&x, data_, sizeof(x));
-      memcpy(&y, other.data_, sizeof(y));
+      // Use memcpy to avoid aliasing issues.
+      memcpy(&x, &data_, sizeof(x));
+      memcpy(&y, &other.data_, sizeof(y));
       if (x == y) {
-        memcpy(&x, data_ + 8, sizeof(x));
-        memcpy(&y, other.data_ + 8, sizeof(y));
+        memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
+        memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
         if (x == y) return 0;
       }
       return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
@@ -706,16 +715,16 @@
       // to 15 bytes does not cause a memory allocation.
       absl::strings_internal::STLStringResizeUninitialized(dst,
                                                            sizeof(data_) - 1);
-      memcpy(&(*dst)[0], data_, sizeof(data_) - 1);
+      memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
       // erase is faster than resize because the logic for memory allocation is
       // not needed.
-      dst->erase(data_[kMaxInline]);
+      dst->erase(tagged_size());
     }
 
     // Copies the inline contents into `dst`. Assumes the cord is not empty.
     void CopyToArray(char* dst) const;
 
-    bool is_tree() const { return data_[kMaxInline] > kMaxInline; }
+    bool is_tree() const { return tagged_size() > kMaxInline; }
 
    private:
     friend class Cord;
@@ -724,10 +733,18 @@
     // Unrefs the tree, stops profiling, and zeroes the contents
     void ClearSlow();
 
-    // If the data has length <= kMaxInline, we store it in data_[0..len-1],
-    // and store the length in data_[kMaxInline].  Else we store it in a tree
-    // and store a pointer to that tree in data_[0..sizeof(CordRep*)-1].
-    alignas(absl::cord_internal::CordRep*) char data_[kMaxInline + 1];
+    void ResetToEmpty() { data_ = {}; }
+
+    // This uses reinterpret_cast instead of the union to avoid accessing the
+    // inactive union element. The tagged size is not a common prefix.
+    void set_tagged_size(char new_tag) {
+      reinterpret_cast<char*>(&data_)[kMaxInline] = new_tag;
+    }
+    char tagged_size() const {
+      return reinterpret_cast<const char*>(&data_)[kMaxInline];
+    }
+
+    cord_internal::InlineData data_;
   };
   InlineRep contents_;
 
@@ -878,13 +895,16 @@
   return cord;
 }
 
+constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
+    : data_(data) {}
+
 inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) {
-  cord_internal::SmallMemmove(data_, src.data_, sizeof(data_));
+  data_ = src.data_;
 }
 
 inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) {
-  memcpy(data_, src.data_, sizeof(data_));
-  memset(src.data_, 0, sizeof(data_));
+  data_ = src.data_;
+  src.ResetToEmpty();
 }
 
 inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
@@ -892,7 +912,7 @@
     return *this;
   }
   if (!is_tree() && !src.is_tree()) {
-    cord_internal::SmallMemmove(data_, src.data_, sizeof(data_));
+    data_ = src.data_;
     return *this;
   }
   AssignSlow(src);
@@ -904,8 +924,8 @@
   if (is_tree()) {
     ClearSlow();
   }
-  memcpy(data_, src.data_, sizeof(data_));
-  memset(src.data_, 0, sizeof(data_));
+  data_ = src.data_;
+  src.ResetToEmpty();
   return *this;
 }
 
@@ -914,43 +934,39 @@
     return;
   }
 
-  Cord::InlineRep tmp;
-  cord_internal::SmallMemmove(tmp.data_, data_, sizeof(data_));
-  cord_internal::SmallMemmove(data_, rhs->data_, sizeof(data_));
-  cord_internal::SmallMemmove(rhs->data_, tmp.data_, sizeof(data_));
+  std::swap(data_, rhs->data_);
 }
 
 inline const char* Cord::InlineRep::data() const {
-  return is_tree() ? nullptr : data_;
+  return is_tree() ? nullptr : data_.as_chars;
 }
 
 inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
   if (is_tree()) {
-    absl::cord_internal::CordRep* rep;
-    memcpy(&rep, data_, sizeof(rep));
-    return rep;
+    return data_.as_tree.rep;
   } else {
     return nullptr;
   }
 }
 
-inline bool Cord::InlineRep::empty() const { return data_[kMaxInline] == 0; }
+inline bool Cord::InlineRep::empty() const { return tagged_size() == 0; }
 
 inline size_t Cord::InlineRep::size() const {
-  const char tag = data_[kMaxInline];
+  const char tag = tagged_size();
   if (tag <= kMaxInline) return tag;
   return static_cast<size_t>(tree()->length);
 }
 
 inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) {
   if (rep == nullptr) {
-    memset(data_, 0, sizeof(data_));
+    ResetToEmpty();
   } else {
     bool was_tree = is_tree();
-    memcpy(data_, &rep, sizeof(rep));
-    memset(data_ + sizeof(rep), 0, sizeof(data_) - sizeof(rep) - 1);
+    data_.as_tree = {rep, {}, tagged_size()};
     if (!was_tree) {
-      data_[kMaxInline] = kTreeFlag;
+      // If we were not a tree already, set the tag.
+      // Otherwise, leave it alone because it might have the profile bit on.
+      set_tagged_size(kTreeFlag);
     }
   }
 }
@@ -961,29 +977,36 @@
     set_tree(rep);
     return;
   }
-  memcpy(data_, &rep, sizeof(rep));
-  memset(data_ + sizeof(rep), 0, sizeof(data_) - sizeof(rep) - 1);
+  data_.as_tree = {rep, {}, tagged_size()};
 }
 
 inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
-  const char tag = data_[kMaxInline];
-  absl::cord_internal::CordRep* result = nullptr;
-  if (tag > kMaxInline) {
-    memcpy(&result, data_, sizeof(result));
-  }
-  memset(data_, 0, sizeof(data_));  // Clear the cord
+  absl::cord_internal::CordRep* result = tree();
+  ResetToEmpty();
   return result;
 }
 
 inline void Cord::InlineRep::CopyToArray(char* dst) const {
   assert(!is_tree());
-  size_t n = data_[kMaxInline];
+  size_t n = tagged_size();
   assert(n != 0);
-  cord_internal::SmallMemmove(dst, data_, n);
+  cord_internal::SmallMemmove(dst, data_.as_chars, n);
 }
 
 constexpr inline Cord::Cord() noexcept {}
 
+template <typename T>
+constexpr Cord::Cord(strings_internal::StringConstant<T>)
+    : contents_(strings_internal::StringConstant<T>::value.size() <=
+                        cord_internal::kMaxInline
+                    ? cord_internal::InlineData(
+                          strings_internal::StringConstant<T>::value)
+                    : cord_internal::InlineData(cord_internal::AsTree{
+                          &cord_internal::ConstInitExternalStorage<
+                              strings_internal::StringConstant<T>>::value,
+                          {},
+                          cord_internal::kTreeFlag})) {}
+
 inline Cord& Cord::operator=(const Cord& x) {
   contents_ = x.contents_;
   return *this;
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index 4443c82..7942bfc 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/cord.h"
 
 #include <algorithm>
@@ -167,6 +181,8 @@
       const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
     c.ForEachChunk(callback);
   }
+
+  static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
 };
 
 ABSL_NAMESPACE_END
@@ -1613,3 +1629,83 @@
   EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
   EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
 }
+
+class AfterExitCordTester {
+ public:
+  bool Set(absl::Cord* cord, absl::string_view expected) {
+    cord_ = cord;
+    expected_ = expected;
+    return true;
+  }
+
+  ~AfterExitCordTester() {
+    EXPECT_EQ(*cord_, expected_);
+  }
+ private:
+  absl::Cord* cord_;
+  absl::string_view expected_;
+};
+
+template <typename Str>
+void TestConstinitConstructor(Str) {
+  const auto expected = Str::value;
+  // Defined before `cord` to be destroyed after it.
+  static AfterExitCordTester exit_tester;  // NOLINT
+  ABSL_CONST_INIT static absl::Cord cord(Str{});  // NOLINT
+  static bool init_exit_tester = exit_tester.Set(&cord, expected);
+  (void)init_exit_tester;
+
+  EXPECT_EQ(cord, expected);
+  // Copy the object and test the copy, and the original.
+  {
+    absl::Cord copy = cord;
+    EXPECT_EQ(copy, expected);
+  }
+  // The original still works
+  EXPECT_EQ(cord, expected);
+
+  // Try making adding more structure to the tree.
+  {
+    absl::Cord copy = cord;
+    std::string expected_copy(expected);
+    for (int i = 0; i < 10; ++i) {
+      copy.Append(cord);
+      absl::StrAppend(&expected_copy, expected);
+      EXPECT_EQ(copy, expected_copy);
+    }
+  }
+
+  // Make sure we are using the right branch during constant evaluation.
+  EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
+
+  for (int i = 0; i < 10; ++i) {
+    // Make a few more Cords from the same global rep.
+    // This tests what happens when the refcount for it gets below 1.
+    EXPECT_EQ(expected, absl::Cord(Str{}));
+  }
+}
+
+constexpr int SimpleStrlen(const char* p) {
+  return *p ? 1 + SimpleStrlen(p + 1) : 0;
+}
+
+struct ShortView {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("SSO string", SimpleStrlen("SSO string"));
+  }
+};
+
+struct LongView {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("String that does not fit SSO.",
+                             SimpleStrlen("String that does not fit SSO."));
+  }
+};
+
+
+TEST(Cord, ConstinitConstructor) {
+  TestConstinitConstructor(
+      absl::strings_internal::MakeStringConstant(ShortView{}));
+  TestConstinitConstructor(
+      absl::strings_internal::MakeStringConstant(LongView{}));
+}
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc
index 363bcb0..a8b9945 100644
--- a/absl/strings/internal/charconv_bigint_test.cc
+++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -69,6 +69,61 @@
     // And we should have fully rotated all bits off by now:
     EXPECT_EQ(a, BigUnsigned<84>(0u));
   }
+  {
+    // Bit shifting large and small numbers by large and small offsets.
+    // Intended to exercise bounds-checking corner on ShiftLeft() (directly
+    // and under asan).
+
+    // 2**(32*84)-1
+    const BigUnsigned<84> all_bits_one(
+        "1474444211396924248063325089479706787923460402125687709454567433186613"
+        "6228083464060749874845919674257665016359189106695900028098437021384227"
+        "3285029708032466536084583113729486015826557532750465299832071590813090"
+        "2011853039837649252477307070509704043541368002938784757296893793903797"
+        "8180292336310543540677175225040919704702800559606097685920595947397024"
+        "8303316808753252115729411497720357971050627997031988036134171378490368"
+        "6008000778741115399296162550786288457245180872759047016734959330367829"
+        "5235612397427686310674725251378116268607113017720538636924549612987647"
+        "5767411074510311386444547332882472126067840027882117834454260409440463"
+        "9345147252664893456053258463203120637089916304618696601333953616715125"
+        "2115882482473279040772264257431663818610405673876655957323083702713344"
+        "4201105427930770976052393421467136557055");
+    const BigUnsigned<84> zero(0u);
+    const BigUnsigned<84> one(1u);
+    // in bounds shifts
+    for (int i = 1; i < 84*32; ++i) {
+      // shifting all_bits_one to the left should result in a smaller number,
+      // since the high bits rotate off and the low bits are replaced with
+      // zeroes.
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(i);
+      EXPECT_GT(all_bits_one, big_shifted);
+      // Shifting 1 to the left should instead result in a larger number.
+      BigUnsigned<84> small_shifted = one;
+      small_shifted.ShiftLeft(i);
+      EXPECT_LT(one, small_shifted);
+    }
+    // Shifting by zero or a negative number has no effect
+    for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) {
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(no_op_shift);
+      EXPECT_EQ(all_bits_one, big_shifted);
+      BigUnsigned<84> small_shifted = one;
+      big_shifted.ShiftLeft(no_op_shift);
+      EXPECT_EQ(one, small_shifted);
+    }
+    // Shifting by an amount greater than the number of bits should result in
+    // zero.
+    for (int out_of_bounds_shift :
+         {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) {
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(out_of_bounds_shift);
+      EXPECT_EQ(zero, big_shifted);
+      BigUnsigned<84> small_shifted = one;
+      small_shifted.ShiftLeft(out_of_bounds_shift);
+      EXPECT_EQ(zero, small_shifted);
+    }
+  }
 }
 
 TEST(BigUnsigned, MultiplyByUint32) {
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index fd6d948..8b11868 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -246,8 +246,8 @@
 // ConsumeDigits does not protect against overflow on *out; max_digits must
 // be chosen with respect to type T to avoid the possibility of overflow.
 template <int base, typename T>
-std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
-                          T* out, bool* dropped_nonzero_digit) {
+int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
+                  bool* dropped_nonzero_digit) {
   if (base == 10) {
     assert(max_digits <= std::numeric_limits<T>::digits10);
   } else if (base == 16) {
@@ -282,7 +282,7 @@
     *dropped_nonzero_digit = true;
   }
   *out = accumulator;
-  return begin - original_begin;
+  return static_cast<int>(begin - original_begin);
 }
 
 // Returns true if `v` is one of the chars allowed inside parentheses following
@@ -372,7 +372,7 @@
 
   int exponent_adjustment = 0;
   bool mantissa_is_inexact = false;
-  std::size_t pre_decimal_digits = ConsumeDigits<base>(
+  int pre_decimal_digits = ConsumeDigits<base>(
       begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
   begin += pre_decimal_digits;
   int digits_left;
@@ -398,14 +398,14 @@
       while (begin < end && *begin == '0') {
         ++begin;
       }
-      std::size_t zeros_skipped = begin - begin_zeros;
+      int zeros_skipped = static_cast<int>(begin - begin_zeros);
       if (zeros_skipped >= DigitLimit<base>()) {
         // refuse to parse pathological inputs
         return result;
       }
       exponent_adjustment -= static_cast<int>(zeros_skipped);
     }
-    std::size_t post_decimal_digits = ConsumeDigits<base>(
+    int post_decimal_digits = ConsumeDigits<base>(
         begin, end, digits_left, &mantissa, &mantissa_is_inexact);
     begin += post_decimal_digits;
 
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index d456eef..aa91a69 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -33,14 +33,17 @@
 // Wraps std::atomic for reference counting.
 class Refcount {
  public:
-  Refcount() : count_{1} {}
-  ~Refcount() {}
+  constexpr Refcount() : count_{kRefIncrement} {}
+  struct Immortal {};
+  explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {}
 
-  // Increments the reference count by 1. Imposes no memory ordering.
-  inline void Increment() { count_.fetch_add(1, std::memory_order_relaxed); }
+  // Increments the reference count. Imposes no memory ordering.
+  inline void Increment() {
+    count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
+  }
 
   // Asserts that the current refcount is greater than 0. If the refcount is
-  // greater than 1, decrements the reference count by 1.
+  // greater than 1, decrements the reference count.
   //
   // Returns false if there are no references outstanding; true otherwise.
   // Inserts barriers to ensure that state written before this method returns
@@ -48,19 +51,24 @@
   // false.
   inline bool Decrement() {
     int32_t refcount = count_.load(std::memory_order_acquire);
-    assert(refcount > 0);
-    return refcount != 1 && count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
+    assert(refcount > 0 || refcount & kImmortalTag);
+    return refcount != kRefIncrement &&
+           count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=
+               kRefIncrement;
   }
 
   // Same as Decrement but expect that refcount is greater than 1.
   inline bool DecrementExpectHighRefcount() {
-    int32_t refcount = count_.fetch_sub(1, std::memory_order_acq_rel);
-    assert(refcount > 0);
-    return refcount != 1;
+    int32_t refcount =
+        count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);
+    assert(refcount > 0 || refcount & kImmortalTag);
+    return refcount != kRefIncrement;
   }
 
   // Returns the current reference count using acquire semantics.
-  inline int32_t Get() const { return count_.load(std::memory_order_acquire); }
+  inline int32_t Get() const {
+    return count_.load(std::memory_order_acquire) >> kImmortalShift;
+  }
 
   // Returns whether the atomic integer is 1.
   // If the reference count is used in the conventional way, a
@@ -70,9 +78,27 @@
   // performs the memory barrier needed for the owning thread
   // to act on the object, knowing that it has exclusive access to the
   // object.
-  inline bool IsOne() { return count_.load(std::memory_order_acquire) == 1; }
+  inline bool IsOne() {
+    return count_.load(std::memory_order_acquire) == kRefIncrement;
+  }
+
+  bool IsImmortal() const {
+    return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0;
+  }
 
  private:
+  // We reserve the bottom bit to tag a reference count as immortal.
+  // By making it `1` we ensure that we never reach `0` when adding/subtracting
+  // `2`, thus it never looks as if it should be destroyed.
+  // These are used for the StringConstant constructor where we do not increase
+  // the refcount at construction time (due to constinit requirements) but we
+  // will still decrease it at destruction time to avoid branching on Unref.
+  enum {
+    kImmortalShift = 1,
+    kRefIncrement = 1 << kImmortalShift,
+    kImmortalTag = kRefIncrement - 1
+  };
+
   std::atomic<int32_t> count_;
 };
 
@@ -85,7 +111,22 @@
 struct CordRepSubstring;
 struct CordRepExternal;
 
+// Various representations that we allow
+enum CordRepKind {
+  CONCAT        = 0,
+  EXTERNAL      = 1,
+  SUBSTRING     = 2,
+
+  // We have different tags for different sized flat arrays,
+  // starting with FLAT
+  FLAT          = 3,
+};
+
 struct CordRep {
+  CordRep() = default;
+  constexpr CordRep(Refcount::Immortal immortal, size_t l)
+      : length(l), refcount(immortal), tag(EXTERNAL), data{} {}
+
   // The following three fields have to be less than 32 bytes since
   // that is the smallest supported flat node size.
   size_t length;
@@ -124,6 +165,12 @@
 // External CordReps are allocated together with a type erased releaser. The
 // releaser is stored in the memory directly following the CordRepExternal.
 struct CordRepExternal : public CordRep {
+  CordRepExternal() = default;
+  explicit constexpr CordRepExternal(absl::string_view str)
+      : CordRep(Refcount::Immortal{}, str.size()),
+        base(str.data()),
+        releaser_invoker(nullptr) {}
+
   const char* base;
   // Pointer to function that knows how to call and destroy the releaser.
   ExternalReleaserInvoker releaser_invoker;
@@ -167,6 +214,56 @@
   }
 };
 
+template <typename Str>
+struct ConstInitExternalStorage {
+  ABSL_CONST_INIT static CordRepExternal value;
+};
+
+template <typename Str>
+CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
+
+enum {
+  kMaxInline = 15,
+  // Tag byte & kMaxInline means we are storing a pointer.
+  kTreeFlag = 1 << 4,
+  // Tag byte & kProfiledFlag means we are profiling the Cord.
+  kProfiledFlag = 1 << 5
+};
+
+// If the data has length <= kMaxInline, we store it in `as_chars`, and
+// store the size in `tagged_size`.
+// Else we store it in a tree and store a pointer to that tree in
+// `as_tree.rep` and store a tag in `tagged_size`.
+struct AsTree {
+  absl::cord_internal::CordRep* rep;
+  char padding[kMaxInline + 1 - sizeof(absl::cord_internal::CordRep*) - 1];
+  char tagged_size;
+};
+
+constexpr char GetOrNull(absl::string_view data, size_t pos) {
+  return pos < data.size() ? data[pos] : '\0';
+}
+
+union InlineData {
+  constexpr InlineData() : as_chars{} {}
+  explicit constexpr InlineData(AsTree tree) : as_tree(tree) {}
+  explicit constexpr InlineData(absl::string_view chars)
+      : as_chars{GetOrNull(chars, 0),  GetOrNull(chars, 1),
+                 GetOrNull(chars, 2),  GetOrNull(chars, 3),
+                 GetOrNull(chars, 4),  GetOrNull(chars, 5),
+                 GetOrNull(chars, 6),  GetOrNull(chars, 7),
+                 GetOrNull(chars, 8),  GetOrNull(chars, 9),
+                 GetOrNull(chars, 10), GetOrNull(chars, 11),
+                 GetOrNull(chars, 12), GetOrNull(chars, 13),
+                 GetOrNull(chars, 14), static_cast<char>(chars.size())} {}
+
+  AsTree as_tree;
+  char as_chars[kMaxInline + 1];
+};
+static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+static_assert(sizeof(AsTree) == sizeof(InlineData), "");
+static_assert(offsetof(AsTree, tagged_size) == kMaxInline, "");
+
 }  // namespace cord_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index 9feb224..e28a29b 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
 //
 // POSIX spec:
 //   http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 3dbc152..7040c86 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
 
diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index f53fd6b..1261937 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/absl/strings/internal/str_format/arg_test.cc
@@ -6,6 +6,12 @@
 //
 //      https://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 "absl/strings/internal/str_format/arg.h"
 
 #include <ostream>
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index 6980ed1..4e68b90 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/internal/str_format/bind.h"
 
 #include <cerrno>
@@ -221,7 +235,7 @@
     errno = sink.error();
     return -1;
   }
-  if (sink.count() > std::numeric_limits<int>::max()) {
+  if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
     errno = EFBIG;
     return -1;
   }
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 585246e..267cc0e 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 
@@ -119,10 +133,11 @@
 
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
-  template <FormatConversionCharSet... C,
-            typename = typename std::enable_if<
-                AllOf(sizeof...(C) == sizeof...(Args), Contains(Args,
-                                                                C)...)>::type>
+  template <
+      FormatConversionCharSet... C,
+      typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
+      typename = typename std::enable_if<AllOf(Contains(Args,
+                                                        C)...)>::type>
   FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT
       : Base(&pc) {}
 };
diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc
index 64790a8..1eef9c4 100644
--- a/absl/strings/internal/str_format/bind_test.cc
+++ b/absl/strings/internal/str_format/bind_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/internal/str_format/bind.h"
 
 #include <string.h>
diff --git a/absl/strings/internal/str_format/checker.h b/absl/strings/internal/str_format/checker.h
index 424c51f..2a2601e 100644
--- a/absl/strings/internal/str_format/checker.h
+++ b/absl/strings/internal/str_format/checker.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 
diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc
index a76d70b..7c70f47 100644
--- a/absl/strings/internal/str_format/checker_test.cc
+++ b/absl/strings/internal/str_format/checker_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 <string>
 
 #include "gmock/gmock.h"
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 634ee78..375db0a 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index cafa479..0ded0a6 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/internal/str_format/float_conversion.h"
 
 #include <string.h>
@@ -120,7 +134,7 @@
     assert(exp > 0);
     assert(exp <= std::numeric_limits<long double>::max_exponent);
     static_assert(
-        StackArray::kMaxCapacity >=
+        static_cast<int>(StackArray::kMaxCapacity) >=
             ChunksNeeded(std::numeric_limits<long double>::max_exponent),
         "");
 
@@ -205,7 +219,7 @@
   }
 
  private:
-  static constexpr size_t kDigitsPerChunk = 9;
+  static constexpr int kDigitsPerChunk = 9;
 
   int decimal_start_;
   int decimal_end_;
@@ -442,8 +456,10 @@
 };
 
 Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
-  if (state.conv.width() < 0 || state.conv.width() <= total_size)
+  if (state.conv.width() < 0 ||
+      static_cast<size_t>(state.conv.width()) <= total_size) {
     return {0, 0, 0};
+  }
   int missing_chars = state.conv.width() - total_size;
   if (state.conv.has_left_flag()) {
     return {0, 0, missing_chars};
@@ -685,9 +701,7 @@
   // i.e., if the nibble_index is out of range. So therefore we check for this
   // and if we are out of range we just add 0 which leaves *n unchanged, which
   // seems like the reasonable thing to do in that case.
-  *n +=
-      ((nibble_index * 4 >= sizeof(Int) * 8) ? 0
-                                             : (Int{1} << (nibble_index * 4)));
+  *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
   Int after = *n >> kShift;
   return (before && !after) || (nibble_index >= kNumNibbles);
 }
diff --git a/absl/strings/internal/str_format/float_conversion.h b/absl/strings/internal/str_format/float_conversion.h
index e78bc19..71100e7 100644
--- a/absl/strings/internal/str_format/float_conversion.h
+++ b/absl/strings/internal/str_format/float_conversion.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 
diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc
index cc55dfa..f308d02 100644
--- a/absl/strings/internal/str_format/parser.cc
+++ b/absl/strings/internal/str_format/parser.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/internal/str_format/parser.h"
 
 #include <assert.h>
diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h
index fffed04..6504dd3 100644
--- a/absl/strings/internal/str_format/parser.h
+++ b/absl/strings/internal/str_format/parser.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
 
diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc
index 5aced98..a5fa1c7 100644
--- a/absl/strings/internal/str_format/parser_test.cc
+++ b/absl/strings/internal/str_format/parser_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/internal/str_format/parser.h"
 
 #include <string.h>
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 6f5bc09..7692477 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -66,41 +66,56 @@
 
   // Matches rvalue strings and moves their data to a member.
   ConvertibleToStringView(std::string&& s)  // NOLINT(runtime/explicit)
-      : copy_(std::move(s)), value_(copy_) {}
+      : copy_(std::move(s)), value_(copy_), self_referential_(true) {}
 
   ConvertibleToStringView(const ConvertibleToStringView& other)
-      : copy_(other.copy_),
-        value_(other.IsSelfReferential() ? copy_ : other.value_) {}
+      : value_(other.value_), self_referential_(other.self_referential_) {
+    if (other.self_referential_) {
+      new (&copy_) std::string(other.copy_);
+      value_ = copy_;
+    }
+  }
 
-  ConvertibleToStringView(ConvertibleToStringView&& other) {
-    StealMembers(std::move(other));
+  ConvertibleToStringView(ConvertibleToStringView&& other)
+      : value_(other.value_), self_referential_(other.self_referential_) {
+    if (other.self_referential_) {
+      new (&copy_) std::string(std::move(other.copy_));
+      value_ = copy_;
+    }
   }
 
   ConvertibleToStringView& operator=(ConvertibleToStringView other) {
-    StealMembers(std::move(other));
+    this->~ConvertibleToStringView();
+    new (this) ConvertibleToStringView(std::move(other));
     return *this;
   }
 
   absl::string_view value() const { return value_; }
 
- private:
-  // Returns true if ctsp's value refers to its internal copy_ member.
-  bool IsSelfReferential() const { return value_.data() == copy_.data(); }
+  ~ConvertibleToStringView() { MaybeReleaseCopy(); }
 
-  void StealMembers(ConvertibleToStringView&& other) {
-    if (other.IsSelfReferential()) {
-      copy_ = std::move(other.copy_);
-      value_ = copy_;
-      other.value_ = other.copy_;
-    } else {
-      value_ = other.value_;
+ private:
+  void MaybeReleaseCopy() {
+    if (self_referential_) {
+      // An explicit destructor call cannot be a qualified name such as
+      // std::string. The "using" declaration works around this
+      // issue by creating an unqualified name for the destructor.
+      using string_type = std::string;
+      copy_.~string_type();
     }
   }
-
+  struct Unused {  // MSVC disallows unions with only 1 member.
+  };
   // Holds the data moved from temporary std::string arguments. Declared first
   // so that 'value' can refer to 'copy_'.
-  std::string copy_;
+  union {
+    std::string copy_;
+    Unused unused_;
+  };
+
   absl::string_view value_;
+  // true if value_ refers to the internal copy_ member.
+  bool self_referential_ = false;
 };
 
 // An iterator that enumerates the parts of a string from a Splitter. The text
@@ -336,7 +351,7 @@
     Container operator()(const Splitter& splitter) const {
       Container c;
       auto it = std::inserter(c, c.end());
-      for (const auto sp : splitter) {
+      for (const auto& sp : splitter) {
         *it++ = ValueType(sp);
       }
       return c;
@@ -401,7 +416,7 @@
       Container m;
       typename Container::iterator it;
       bool insert = true;
-      for (const auto sp : splitter) {
+      for (const auto& sp : splitter) {
         if (insert) {
           it = Inserter<Container>::Insert(&m, First(sp), Second());
         } else {
diff --git a/absl/strings/internal/string_constant.h b/absl/strings/internal/string_constant.h
new file mode 100644
index 0000000..b15f1d9
--- /dev/null
+++ b/absl/strings/internal/string_constant.h
@@ -0,0 +1,70 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+
+#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+// StringConstant<T> represents a compile time string constant.
+// It can be accessed via its `absl::string_view value` static member.
+// It is guaranteed that the `string_view` returned has constant `.data()`,
+// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
+//
+// The `T` is an opaque type. It is guaranteed that different string constants
+// will have different values of `T`. This allows users to associate the string
+// constant with other static state at compile time.
+//
+// Instances should be made using the `MakeStringConstant()` factory function
+// below.
+template <typename T>
+struct StringConstant {
+ private:
+  // Returns true if `view` points to constant data.
+  // Otherwise, it can't be constant evaluated.
+  static constexpr bool ValidateConstant(absl::string_view view) {
+    return view.empty() || 2 * view[0] != 1;
+  }
+
+ public:
+  static constexpr absl::string_view value = T{}();
+  constexpr absl::string_view operator()() const { return value; }
+
+  static_assert(ValidateConstant(value),
+                "The input string_view must point to constant data.");
+};
+
+template <typename T>
+constexpr absl::string_view StringConstant<T>::value;  // NOLINT
+
+// Factory function for `StringConstant` instances.
+// It supports callables that have a constexpr default constructor and a
+// constexpr operator().
+// It must return an `absl::string_view` or `const char*` pointing to constant
+// data. This is validated at compile time.
+template <typename T>
+constexpr StringConstant<T> MakeStringConstant(T) {
+  return {};
+}
+
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
diff --git a/absl/strings/internal/string_constant_test.cc b/absl/strings/internal/string_constant_test.cc
new file mode 100644
index 0000000..392833c
--- /dev/null
+++ b/absl/strings/internal/string_constant_test.cc
@@ -0,0 +1,60 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/internal/string_constant.h"
+
+#include "absl/meta/type_traits.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::strings_internal::MakeStringConstant;
+
+struct Callable {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("Callable", 8);
+  }
+};
+
+TEST(StringConstant, Traits) {
+  constexpr auto str = MakeStringConstant(Callable{});
+  using T = decltype(str);
+
+  EXPECT_TRUE(std::is_empty<T>::value);
+  EXPECT_TRUE(std::is_trivial<T>::value);
+  EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_destructible<T>::value);
+}
+
+TEST(StringConstant, MakeFromCallable) {
+  constexpr auto str = MakeStringConstant(Callable{});
+  using T = decltype(str);
+  EXPECT_EQ(Callable{}(), T::value);
+  EXPECT_EQ(Callable{}(), str());
+}
+
+TEST(StringConstant, MakeFromStringConstant) {
+  // We want to make sure the StringConstant itself is a valid input to the
+  // factory function.
+  constexpr auto str = MakeStringConstant(Callable{});
+  constexpr auto str2 = MakeStringConstant(str);
+  using T = decltype(str2);
+  EXPECT_EQ(Callable{}(), T::value);
+  EXPECT_EQ(Callable{}(), str2());
+}
+
+}  // namespace
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 68c26dd..3da1059 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -736,9 +736,18 @@
         X / 35, X / 36,                                                   \
   }
 
+// This kVmaxOverBase is generated with
+//  for (int base = 2; base < 37; ++base) {
+//    absl::uint128 max = std::numeric_limits<absl::uint128>::max();
+//    auto result = max / base;
+//    std::cout << "    MakeUint128(" << absl::Uint128High64(result) << "u, "
+//              << absl::Uint128Low64(result) << "u),\n";
+//  }
+// See https://godbolt.org/z/aneYsb
+//
 // uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
 // array to avoid a static initializer.
-template <>
+template<>
 const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
     0,
     0,
@@ -779,6 +788,111 @@
     MakeUint128(512409557603043100u, 8198552921648689607u),
 };
 
+// This kVmaxOverBase generated with
+//   for (int base = 2; base < 37; ++base) {
+//    absl::int128 max = std::numeric_limits<absl::int128>::max();
+//    auto result = max / base;
+//    std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+//              << absl::Int128Low64(result) << "u),\n";
+//  }
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVmaxOverBase[] = {
+    0,
+    0,
+    MakeInt128(4611686018427387903, 18446744073709551615u),
+    MakeInt128(3074457345618258602, 12297829382473034410u),
+    MakeInt128(2305843009213693951, 18446744073709551615u),
+    MakeInt128(1844674407370955161, 11068046444225730969u),
+    MakeInt128(1537228672809129301, 6148914691236517205u),
+    MakeInt128(1317624576693539401, 2635249153387078802u),
+    MakeInt128(1152921504606846975, 18446744073709551615u),
+    MakeInt128(1024819115206086200, 16397105843297379214u),
+    MakeInt128(922337203685477580, 14757395258967641292u),
+    MakeInt128(838488366986797800, 13415813871788764811u),
+    MakeInt128(768614336404564650, 12297829382473034410u),
+    MakeInt128(709490156681136600, 11351842506898185609u),
+    MakeInt128(658812288346769700, 10540996613548315209u),
+    MakeInt128(614891469123651720, 9838263505978427528u),
+    MakeInt128(576460752303423487, 18446744073709551615u),
+    MakeInt128(542551296285575047, 9765923333140350855u),
+    MakeInt128(512409557603043100, 8198552921648689607u),
+    MakeInt128(485440633518672410, 17475862806672206794u),
+    MakeInt128(461168601842738790, 7378697629483820646u),
+    MakeInt128(439208192231179800, 7027331075698876806u),
+    MakeInt128(419244183493398900, 6707906935894382405u),
+    MakeInt128(401016175515425035, 2406097053092550210u),
+    MakeInt128(384307168202282325, 6148914691236517205u),
+    MakeInt128(368934881474191032, 5902958103587056517u),
+    MakeInt128(354745078340568300, 5675921253449092804u),
+    MakeInt128(341606371735362066, 17763531330238827482u),
+    MakeInt128(329406144173384850, 5270498306774157604u),
+    MakeInt128(318047311615681924, 7633135478776366185u),
+    MakeInt128(307445734561825860, 4919131752989213764u),
+    MakeInt128(297528130221121800, 4760450083537948804u),
+    MakeInt128(288230376151711743, 18446744073709551615u),
+    MakeInt128(279496122328932600, 4471937957262921603u),
+    MakeInt128(271275648142787523, 14106333703424951235u),
+    MakeInt128(263524915338707880, 4216398645419326083u),
+    MakeInt128(256204778801521550, 4099276460824344803u),
+};
+
+// This kVminOverBase generated with
+//  for (int base = 2; base < 37; ++base) {
+//    absl::int128 min = std::numeric_limits<absl::int128>::min();
+//    auto result = min / base;
+//    std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+//              << absl::Int128Low64(result) << "u),\n";
+//  }
+//
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVminOverBase[] = {
+    0,
+    0,
+    MakeInt128(-4611686018427387904, 0u),
+    MakeInt128(-3074457345618258603, 6148914691236517206u),
+    MakeInt128(-2305843009213693952, 0u),
+    MakeInt128(-1844674407370955162, 7378697629483820647u),
+    MakeInt128(-1537228672809129302, 12297829382473034411u),
+    MakeInt128(-1317624576693539402, 15811494920322472814u),
+    MakeInt128(-1152921504606846976, 0u),
+    MakeInt128(-1024819115206086201, 2049638230412172402u),
+    MakeInt128(-922337203685477581, 3689348814741910324u),
+    MakeInt128(-838488366986797801, 5030930201920786805u),
+    MakeInt128(-768614336404564651, 6148914691236517206u),
+    MakeInt128(-709490156681136601, 7094901566811366007u),
+    MakeInt128(-658812288346769701, 7905747460161236407u),
+    MakeInt128(-614891469123651721, 8608480567731124088u),
+    MakeInt128(-576460752303423488, 0u),
+    MakeInt128(-542551296285575048, 8680820740569200761u),
+    MakeInt128(-512409557603043101, 10248191152060862009u),
+    MakeInt128(-485440633518672411, 970881267037344822u),
+    MakeInt128(-461168601842738791, 11068046444225730970u),
+    MakeInt128(-439208192231179801, 11419412998010674810u),
+    MakeInt128(-419244183493398901, 11738837137815169211u),
+    MakeInt128(-401016175515425036, 16040647020617001406u),
+    MakeInt128(-384307168202282326, 12297829382473034411u),
+    MakeInt128(-368934881474191033, 12543785970122495099u),
+    MakeInt128(-354745078340568301, 12770822820260458812u),
+    MakeInt128(-341606371735362067, 683212743470724134u),
+    MakeInt128(-329406144173384851, 13176245766935394012u),
+    MakeInt128(-318047311615681925, 10813608594933185431u),
+    MakeInt128(-307445734561825861, 13527612320720337852u),
+    MakeInt128(-297528130221121801, 13686293990171602812u),
+    MakeInt128(-288230376151711744, 0u),
+    MakeInt128(-279496122328932601, 13974806116446630013u),
+    MakeInt128(-271275648142787524, 4340410370284600381u),
+    MakeInt128(-263524915338707881, 14230345428290225533u),
+    MakeInt128(-256204778801521551, 14347467612885206813u),
+};
+
 template <typename IntType>
 const IntType LookupTables<IntType>::kVmaxOverBase[] =
     X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
@@ -948,6 +1062,10 @@
   return safe_int_internal<int64_t>(text, value, base);
 }
 
+bool safe_strto128_base(absl::string_view text, int128* value, int base) {
+  return safe_int_internal<absl::int128>(text, value, base);
+}
+
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) {
   return safe_uint_internal<uint32_t>(text, value, base);
 }
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index d872cca..2e004b4 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -127,6 +127,8 @@
 // safe_strto?() functions for implementing SimpleAtoi()
 bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
 bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
+bool safe_strto128_base(absl::string_view text, absl::int128* value,
+                         int base);
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base);
 bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base);
 bool safe_strtou128_base(absl::string_view text, absl::uint128* value,
@@ -256,6 +258,11 @@
 }
 
 ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+                                            absl::int128* out) {
+  return numbers_internal::safe_strto128_base(str, out, 10);
+}
+
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
                                             absl::uint128* out) {
   return numbers_internal::safe_strtou128_base(str, out, 10);
 }
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index c2f03b6..4ab67fb 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -251,7 +251,7 @@
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
   std::string s;
-  // uint128 can be streamed but not StrCat'd
+  // (u)int128 can be streamed but not StrCat'd.
   absl::strings_internal::OStringStream(&s) << in_value;
   int_type x = static_cast<int_type>(~exp_value);
   EXPECT_TRUE(SimpleAtoi(s, &x))
@@ -264,7 +264,9 @@
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiBad(in_val_type in_value) {
-  std::string s = absl::StrCat(in_value);
+  std::string s;
+  // (u)int128 can be streamed but not StrCat'd.
+  absl::strings_internal::OStringStream(&s) << in_value;
   int_type x;
   EXPECT_FALSE(SimpleAtoi(s, &x));
   EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
@@ -347,6 +349,31 @@
       std::numeric_limits<absl::uint128>::max(),
       std::numeric_limits<absl::uint128>::max());
 
+  // SimpleAtoi(absl::string_view, absl::int128)
+  VerifySimpleAtoiGood<absl::int128>(0, 0);
+  VerifySimpleAtoiGood<absl::int128>(42, 42);
+  VerifySimpleAtoiGood<absl::int128>(-42, -42);
+
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),
+                                      std::numeric_limits<int32_t>::min());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),
+                                      std::numeric_limits<int32_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),
+                                      std::numeric_limits<uint32_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),
+                                      std::numeric_limits<int64_t>::min());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),
+                                      std::numeric_limits<int64_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),
+                                      std::numeric_limits<uint64_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(
+      std::numeric_limits<absl::int128>::min(),
+      std::numeric_limits<absl::int128>::min());
+  VerifySimpleAtoiGood<absl::int128>(
+      std::numeric_limits<absl::int128>::max(),
+      std::numeric_limits<absl::int128>::max());
+  VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
+
   // Some other types
   VerifySimpleAtoiGood<int>(-42, -42);
   VerifySimpleAtoiGood<int32_t>(-42, -42);
@@ -725,6 +752,51 @@
     EXPECT_FALSE(parse_func(s, &parsed_value, base));
   }
 }
+TEST(stringtest, safe_strto128_random) {
+  // random number generators don't work for int128, and
+  // int128 can be streamed but not StrCat'd, so this code must be custom
+  // implemented for int128, but is generally the same as what's above.
+  // test_random_integer_parse_base<absl::int128>(
+  //     &absl::numbers_internal::safe_strto128_base);
+  using RandomEngine = std::minstd_rand0;
+  using IntType = absl::int128;
+  constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
+
+  std::random_device rd;
+  RandomEngine rng(rd());
+  std::uniform_int_distribution<int64_t> random_int64(
+      std::numeric_limits<int64_t>::min());
+  std::uniform_int_distribution<uint64_t> random_uint64(
+      std::numeric_limits<uint64_t>::min());
+  std::uniform_int_distribution<int> random_base(2, 35);
+
+  for (size_t i = 0; i < kNumRandomTests; ++i) {
+    int64_t high = random_int64(rng);
+    uint64_t low = random_uint64(rng);
+    IntType value = absl::MakeInt128(high, low);
+
+    int base = random_base(rng);
+    std::string str_value;
+    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+    IntType parsed_value;
+
+    // Test successful parse
+    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+    EXPECT_EQ(parsed_value, value);
+
+    // Test overflow
+    std::string s;
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::max() << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+
+    // Test underflow
+    s.clear();
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::min() << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+  }
+}
 
 TEST(stringtest, safe_strtou32_base) {
   for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index ee4ad11..02c4dbe 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -137,4 +137,51 @@
 }
 BENCHMARK(BM_DoubleToString_By_SixDigits);
 
+template <typename... Chunks>
+void BM_StrAppendImpl(benchmark::State& state, size_t total_bytes,
+                      Chunks... chunks) {
+  for (auto s : state) {
+    std::string result;
+    while (result.size() < total_bytes) {
+      absl::StrAppend(&result, chunks...);
+      benchmark::DoNotOptimize(result);
+    }
+  }
+}
+
+void BM_StrAppend(benchmark::State& state) {
+  const int total_bytes = state.range(0);
+  const int chunks_at_a_time = state.range(1);
+  const absl::string_view kChunk = "0123456789";
+
+  switch (chunks_at_a_time) {
+    case 1:
+      return BM_StrAppendImpl(state, total_bytes, kChunk);
+    case 2:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk);
+    case 4:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+                              kChunk);
+    case 8:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+                              kChunk, kChunk, kChunk, kChunk, kChunk);
+    default:
+      std::abort();
+  }
+}
+
+template <typename B>
+void StrAppendConfig(B* benchmark) {
+  for (int bytes : {10, 100, 1000, 10000}) {
+    for (int chunks : {1, 2, 4, 8}) {
+      // Only add the ones that divide properly. Otherwise we are over counting.
+      if (bytes % (10 * chunks) == 0) {
+        benchmark->Args({bytes, chunks});
+      }
+    }
+  }
+}
+
+BENCHMARK(BM_StrAppend)->Apply(StrAppendConfig);
+
 }  // namespace
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index d9fb25a..c60027a 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -1,3 +1,16 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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 "absl/strings/str_format.h"
 
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index b5ce68d..7f7c097 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -367,7 +367,7 @@
 TEST(Splitter, RangeIterators) {
   auto splitter = absl::StrSplit("a,b,c", ',');
   std::vector<absl::string_view> output;
-  for (const absl::string_view p : splitter) {
+  for (const absl::string_view& p : splitter) {
     output.push_back(p);
   }
   EXPECT_THAT(output, ElementsAre("a", "b", "c"));
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 8a9db8c..5260b5b 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -111,6 +111,11 @@
 // example, when splitting a string, `std::vector<absl::string_view>` is a
 // natural data type for the output.
 //
+// For another example, a Cord is a non-contiguous, potentially very
+// long string-like object.  The Cord class has an interface that iteratively
+// provides string_view objects that point to the successive pieces of a Cord
+// object.
+//
 // When constructed from a source which is NUL-terminated, the `string_view`
 // itself will not include the NUL-terminator unless a specific size (including
 // the NUL) is passed to the constructor. As a result, common idioms that work
@@ -382,6 +387,7 @@
   // Returns a "substring" of the `string_view` (at offset `pos` and length
   // `n`) as another string_view. This function throws `std::out_of_bounds` if
   // `pos > size`.
+  // Use absl::ClippedSubstr if you need a truncating substr operation.
   constexpr string_view substr(size_type pos, size_type n = npos) const {
     return ABSL_PREDICT_FALSE(pos > length_)
                ? (base_internal::ThrowStdOutOfRange(
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 1a5c02a..cd4009a 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 # Internal data structure for efficiently detecting mutex dependency cycles
 cc_library(
@@ -73,15 +73,14 @@
         "internal/create_thread_identity.cc",
         "internal/per_thread_sem.cc",
         "internal/waiter.cc",
+        "mutex.cc",
         "notification.cc",
-    ] + select({
-        "//conditions:default": ["mutex.cc"],
-    }),
+    ],
     hdrs = [
         "barrier.h",
         "blocking_counter.h",
         "internal/create_thread_identity.h",
-        "internal/mutex_nonprod.inc",
+        "internal/futex.h",
         "internal/per_thread_sem.h",
         "internal/waiter.h",
         "mutex.h",
diff --git a/absl/synchronization/BUILD.gn b/absl/synchronization/BUILD.gn
index 37ab3f9..78f64cd 100644
--- a/absl/synchronization/BUILD.gn
+++ b/absl/synchronization/BUILD.gn
@@ -42,7 +42,7 @@
     "barrier.h",
     "blocking_counter.h",
     "internal/create_thread_identity.h",
-    "internal/mutex_nonprod.inc",
+    "internal/futex.h",
     "internal/per_thread_sem.h",
     "internal/waiter.h",
     "mutex.h",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index e5bc52f..e633d0b 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -52,7 +52,7 @@
     "barrier.h"
     "blocking_counter.h"
     "internal/create_thread_identity.h"
-    "internal/mutex_nonprod.inc"
+    "internal/futex.h"
     "internal/per_thread_sem.h"
     "internal/waiter.h"
     "mutex.h"
diff --git a/absl/synchronization/internal/futex.h b/absl/synchronization/internal/futex.h
new file mode 100644
index 0000000..06fbd6d
--- /dev/null
+++ b/absl/synchronization/internal/futex.h
@@ -0,0 +1,154 @@
+// Copyright 2020 The Abseil Authors.
+//
+// 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
+//
+//      https://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.
+#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#ifdef __linux__
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/optimization.h"
+#include "absl/synchronization/internal/kernel_timeout.h"
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+#error ABSL_INTERNAL_HAVE_FUTEX may not be set on the command line
+#elif defined(__BIONIC__)
+// Bionic supports all the futex operations we need even when some of the futex
+// definitions are missing.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
+// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace synchronization_internal {
+
+// Some Android headers are missing these definitions even though they
+// support these futex operations.
+#ifdef __BIONIC__
+#ifndef SYS_futex
+#define SYS_futex __NR_futex
+#endif
+#ifndef FUTEX_WAIT_BITSET
+#define FUTEX_WAIT_BITSET 9
+#endif
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG 128
+#endif
+#ifndef FUTEX_CLOCK_REALTIME
+#define FUTEX_CLOCK_REALTIME 256
+#endif
+#ifndef FUTEX_BITSET_MATCH_ANY
+#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
+#endif
+#endif
+
+#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
+#define SYS_futex_time64 __NR_futex_time64
+#endif
+
+#if defined(SYS_futex_time64) && !defined(SYS_futex)
+#define SYS_futex SYS_futex_time64
+#endif
+
+class FutexImpl {
+ public:
+  static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
+                       KernelTimeout t) {
+    int err = 0;
+    if (t.has_timeout()) {
+      // https://locklessinc.com/articles/futex_cheat_sheet/
+      // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
+      struct timespec abs_timeout = t.MakeAbsTimespec();
+      // Atomically check that the futex value is still 0, and if it
+      // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
+      err = syscall(
+          SYS_futex, reinterpret_cast<int32_t *>(v),
+          FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
+          &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
+    } else {
+      // Atomically check that the futex value is still 0, and if it
+      // is, sleep until woken by FUTEX_WAKE.
+      err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                    FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
+    }
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  static int WaitBitsetAbsoluteTimeout(std::atomic<int32_t> *v, int32_t val,
+                                       int32_t bits,
+                                       const struct timespec *abstime) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime,
+                      nullptr, bits);
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  static int Wake(std::atomic<int32_t> *v, int32_t count) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
+    if (ABSL_PREDICT_FALSE(err < 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  // FUTEX_WAKE_BITSET
+  static int WakeBitset(std::atomic<int32_t> *v, int32_t count, int32_t bits) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr,
+                      nullptr, bits);
+    if (ABSL_PREDICT_FALSE(err < 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+};
+
+class Futex : public FutexImpl {};
+
+}  // namespace synchronization_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_INTERNAL_HAVE_FUTEX
+
+#endif  // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc
index 19f9aab..27fec21 100644
--- a/absl/synchronization/internal/graphcycles.cc
+++ b/absl/synchronization/internal/graphcycles.cc
@@ -37,6 +37,7 @@
 
 #include <algorithm>
 #include <array>
+#include <limits>
 #include "absl/base/internal/hide_ptr.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index d6ac5db..bbd4d2d 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -26,6 +26,7 @@
 #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
 
 #include <time.h>
+
 #include <algorithm>
 #include <limits>
 
@@ -57,6 +58,10 @@
 
   bool has_timeout() const { return ns_ != 0; }
 
+  // Convert to parameter for sem_timedwait/futex/similar.  Only for approved
+  // users.  Do not call if !has_timeout.
+  struct timespec MakeAbsTimespec();
+
  private:
   // internal rep, not user visible: ns after unix epoch.
   // zero = no timeout.
@@ -82,34 +87,6 @@
     return x;
   }
 
-  // Convert to parameter for sem_timedwait/futex/similar.  Only for approved
-  // users.  Do not call if !has_timeout.
-  struct timespec MakeAbsTimespec() {
-    int64_t n = ns_;
-    static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
-    if (n == 0) {
-      ABSL_RAW_LOG(
-          ERROR,
-          "Tried to create a timespec from a non-timeout; never do this.");
-      // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
-      n = (std::numeric_limits<int64_t>::max)();
-    }
-
-    // Kernel APIs validate timespecs as being at or after the epoch,
-    // despite the kernel time type being signed.  However, no one can
-    // tell the difference between a timeout at or before the epoch (since
-    // all such timeouts have expired!)
-    if (n < 0) n = 0;
-
-    struct timespec abstime;
-    int64_t seconds = (std::min)(n / kNanosPerSecond,
-                               int64_t{(std::numeric_limits<time_t>::max)()});
-    abstime.tv_sec = static_cast<time_t>(seconds);
-    abstime.tv_nsec =
-        static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
-    return abstime;
-  }
-
 #ifdef _WIN32
   // Converts to milliseconds from now, or INFINITE when
   // !has_timeout(). For use by SleepConditionVariableSRW on
@@ -148,6 +125,30 @@
   friend class Waiter;
 };
 
+inline struct timespec KernelTimeout::MakeAbsTimespec() {
+  int64_t n = ns_;
+  static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
+  if (n == 0) {
+    ABSL_RAW_LOG(
+        ERROR, "Tried to create a timespec from a non-timeout; never do this.");
+    // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
+    n = (std::numeric_limits<int64_t>::max)();
+  }
+
+  // Kernel APIs validate timespecs as being at or after the epoch,
+  // despite the kernel time type being signed.  However, no one can
+  // tell the difference between a timeout at or before the epoch (since
+  // all such timeouts have expired!)
+  if (n < 0) n = 0;
+
+  struct timespec abstime;
+  int64_t seconds = (std::min)(n / kNanosPerSecond,
+                               int64_t{(std::numeric_limits<time_t>::max)()});
+  abstime.tv_sec = static_cast<time_t>(seconds);
+  abstime.tv_nsec = static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
+  return abstime;
+}
+
 }  // namespace synchronization_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc
deleted file mode 100644
index 334c3bc..0000000
--- a/absl/synchronization/internal/mutex_nonprod.cc
+++ /dev/null
@@ -1,325 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// 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
-//
-//      https://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.
-
-// Implementation of a small subset of Mutex and CondVar functionality
-// for platforms where the production implementation hasn't been fully
-// ported yet.
-
-#include "absl/synchronization/mutex.h"
-
-#if defined(_WIN32)
-#include <chrono>  // NOLINT(build/c++11)
-#else
-#include <sys/time.h>
-#include <time.h>
-#endif
-
-#include <algorithm>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/time/time.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-void SetMutexDeadlockDetectionMode(OnDeadlockCycle) {}
-void EnableMutexInvariantDebugging(bool) {}
-
-namespace synchronization_internal {
-
-namespace {
-
-// Return the current time plus the timeout.
-absl::Time DeadlineFromTimeout(absl::Duration timeout) {
-  return absl::Now() + timeout;
-}
-
-// Limit the deadline to a positive, 32-bit time_t value to accommodate
-// implementation restrictions.  This also deals with InfinitePast and
-// InfiniteFuture.
-absl::Time LimitedDeadline(absl::Time deadline) {
-  deadline = std::max(absl::FromTimeT(0), deadline);
-  deadline = std::min(deadline, absl::FromTimeT(0x7fffffff));
-  return deadline;
-}
-
-}  // namespace
-
-#if defined(_WIN32)
-
-MutexImpl::MutexImpl() {}
-
-MutexImpl::~MutexImpl() {
-  if (locked_) {
-    std_mutex_.unlock();
-  }
-}
-
-void MutexImpl::Lock() {
-  std_mutex_.lock();
-  locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
-  bool locked = std_mutex_.try_lock();
-  if (locked) locked_ = true;
-  return locked;
-}
-
-void MutexImpl::Unlock() {
-  locked_ = false;
-  released_.SignalAll();
-  std_mutex_.unlock();
-}
-
-CondVarImpl::CondVarImpl() {}
-
-CondVarImpl::~CondVarImpl() {}
-
-void CondVarImpl::Signal() { std_cv_.notify_one(); }
-
-void CondVarImpl::SignalAll() { std_cv_.notify_all(); }
-
-void CondVarImpl::Wait(MutexImpl* mu) {
-  mu->released_.SignalAll();
-  std_cv_.wait(mu->std_mutex_);
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
-  mu->released_.SignalAll();
-  time_t when = ToTimeT(deadline);
-  int64_t nanos = ToInt64Nanoseconds(deadline - absl::FromTimeT(when));
-  std::chrono::system_clock::time_point deadline_tp =
-      std::chrono::system_clock::from_time_t(when) +
-      std::chrono::duration_cast<std::chrono::system_clock::duration>(
-          std::chrono::nanoseconds(nanos));
-  auto deadline_since_epoch =
-      std::chrono::duration_cast<std::chrono::duration<double>>(
-          deadline_tp - std::chrono::system_clock::from_time_t(0));
-  return std_cv_.wait_until(mu->std_mutex_, deadline_tp) ==
-         std::cv_status::timeout;
-}
-
-#else  // ! _WIN32
-
-MutexImpl::MutexImpl() {
-  ABSL_RAW_CHECK(pthread_mutex_init(&pthread_mutex_, nullptr) == 0,
-                 "pthread error");
-}
-
-MutexImpl::~MutexImpl() {
-  if (locked_) {
-    ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-  }
-  ABSL_RAW_CHECK(pthread_mutex_destroy(&pthread_mutex_) == 0, "pthread error");
-}
-
-void MutexImpl::Lock() {
-  ABSL_RAW_CHECK(pthread_mutex_lock(&pthread_mutex_) == 0, "pthread error");
-  locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
-  bool locked = (0 == pthread_mutex_trylock(&pthread_mutex_));
-  if (locked) locked_ = true;
-  return locked;
-}
-
-void MutexImpl::Unlock() {
-  locked_ = false;
-  released_.SignalAll();
-  ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-}
-
-CondVarImpl::CondVarImpl() {
-  ABSL_RAW_CHECK(pthread_cond_init(&pthread_cv_, nullptr) == 0,
-                 "pthread error");
-}
-
-CondVarImpl::~CondVarImpl() {
-  ABSL_RAW_CHECK(pthread_cond_destroy(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Signal() {
-  ABSL_RAW_CHECK(pthread_cond_signal(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::SignalAll() {
-  ABSL_RAW_CHECK(pthread_cond_broadcast(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Wait(MutexImpl* mu) {
-  mu->released_.SignalAll();
-  ABSL_RAW_CHECK(pthread_cond_wait(&pthread_cv_, &mu->pthread_mutex_) == 0,
-                 "pthread error");
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
-  mu->released_.SignalAll();
-  struct timespec ts = ToTimespec(deadline);
-  int rc = pthread_cond_timedwait(&pthread_cv_, &mu->pthread_mutex_, &ts);
-  if (rc == ETIMEDOUT) return true;
-  ABSL_RAW_CHECK(rc == 0, "pthread error");
-  return false;
-}
-
-#endif  // ! _WIN32
-
-void MutexImpl::Await(const Condition& cond) {
-  if (cond.Eval()) return;
-  released_.SignalAll();
-  do {
-    released_.Wait(this);
-  } while (!cond.Eval());
-}
-
-bool MutexImpl::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
-  if (cond.Eval()) return true;
-  released_.SignalAll();
-  while (true) {
-    if (released_.WaitWithDeadline(this, deadline)) return false;
-    if (cond.Eval()) return true;
-  }
-}
-
-}  // namespace synchronization_internal
-
-Mutex::Mutex() {}
-
-Mutex::~Mutex() {}
-
-void Mutex::Lock() { impl()->Lock(); }
-
-void Mutex::Unlock() { impl()->Unlock(); }
-
-bool Mutex::TryLock() { return impl()->TryLock(); }
-
-void Mutex::ReaderLock() { Lock(); }
-
-void Mutex::ReaderUnlock() { Unlock(); }
-
-void Mutex::Await(const Condition& cond) { impl()->Await(cond); }
-
-void Mutex::LockWhen(const Condition& cond) {
-  Lock();
-  Await(cond);
-}
-
-bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
-  return impl()->AwaitWithDeadline(
-      cond, synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
-  return AwaitWithDeadline(
-      cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) {
-  Lock();
-  return AwaitWithDeadline(cond, deadline);
-}
-
-bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
-  return LockWhenWithDeadline(
-      cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-void Mutex::ReaderLockWhen(const Condition& cond) {
-  ReaderLock();
-  Await(cond);
-}
-
-bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
-                                      absl::Duration timeout) {
-  return LockWhenWithTimeout(cond, timeout);
-}
-bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond,
-                                       absl::Time deadline) {
-  return LockWhenWithDeadline(cond, deadline);
-}
-
-void Mutex::EnableDebugLog(const char*) {}
-void Mutex::EnableInvariantDebugging(void (*)(void*), void*) {}
-void Mutex::ForgetDeadlockInfo() {}
-void Mutex::AssertHeld() const {}
-void Mutex::AssertReaderHeld() const {}
-void Mutex::AssertNotHeld() const {}
-
-CondVar::CondVar() {}
-
-CondVar::~CondVar() {}
-
-void CondVar::Signal() { impl()->Signal(); }
-
-void CondVar::SignalAll() { impl()->SignalAll(); }
-
-void CondVar::Wait(Mutex* mu) { return impl()->Wait(mu->impl()); }
-
-bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) {
-  return impl()->WaitWithDeadline(
-      mu->impl(), synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
-  return WaitWithDeadline(mu, absl::Now() + timeout);
-}
-
-void CondVar::EnableDebugLog(const char*) {}
-
-#ifdef ABSL_HAVE_THREAD_SANITIZER
-extern "C" void __tsan_read1(void *addr);
-#else
-#define __tsan_read1(addr)  // do nothing if TSan not enabled
-#endif
-
-// A function that just returns its argument, dereferenced
-static bool Dereference(void *arg) {
-  // ThreadSanitizer does not instrument this file for memory accesses.
-  // This function dereferences a user variable that can participate
-  // in a data race, so we need to manually tell TSan about this memory access.
-  __tsan_read1(arg);
-  return *(static_cast<bool *>(arg));
-}
-
-Condition::Condition() {}   // null constructor, used for kTrue only
-const Condition Condition::kTrue;
-
-Condition::Condition(bool (*func)(void *), void *arg)
-    : eval_(&CallVoidPtrFunction),
-      function_(func),
-      method_(nullptr),
-      arg_(arg) {}
-
-bool Condition::CallVoidPtrFunction(const Condition *c) {
-  return (*c->function_)(c->arg_);
-}
-
-Condition::Condition(const bool *cond)
-    : eval_(CallVoidPtrFunction),
-      function_(Dereference),
-      method_(nullptr),
-      // const_cast is safe since Dereference does not modify arg
-      arg_(const_cast<bool *>(cond)) {}
-
-bool Condition::Eval() const {
-  // eval_ == null for kTrue
-  return (this->eval_ == nullptr) || (*this->eval_)(this);
-}
-
-void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
-
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
deleted file mode 100644
index d83bc8a..0000000
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ /dev/null
@@ -1,249 +0,0 @@
-// Do not include.  This is an implementation detail of base/mutex.h.
-//
-// Declares three classes:
-//
-// base::internal::MutexImpl - implementation helper for Mutex
-// base::internal::CondVarImpl - implementation helper for CondVar
-// base::internal::SynchronizationStorage<T> - implementation helper for
-//                                             Mutex, CondVar
-
-#include <type_traits>
-
-#if defined(_WIN32)
-#include <condition_variable>
-#include <mutex>
-#else
-#include <pthread.h>
-#endif
-
-#include "absl/base/call_once.h"
-#include "absl/time/time.h"
-
-// Declare that Mutex::ReaderLock is actually Lock().  Intended primarily
-// for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
-#error ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE cannot be directly set
-#else
-#define ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE 1
-#endif
-
-// Declare that Mutex::EnableInvariantDebugging is not implemented.
-// Intended primarily for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED
-#error ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED cannot be directly set
-#else
-#define ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED 1
-#endif
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-class Condition;
-
-namespace synchronization_internal {
-
-class MutexImpl;
-
-// Do not use this implementation detail of CondVar. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class CondVarImpl {
- public:
-  CondVarImpl();
-  CondVarImpl(const CondVarImpl&) = delete;
-  CondVarImpl& operator=(const CondVarImpl&) = delete;
-  ~CondVarImpl();
-
-  void Signal();
-  void SignalAll();
-  void Wait(MutexImpl* mutex);
-  bool WaitWithDeadline(MutexImpl* mutex, absl::Time deadline);
-
- private:
-#if defined(_WIN32)
-  std::condition_variable_any std_cv_;
-#else
-  pthread_cond_t pthread_cv_;
-#endif
-};
-
-// Do not use this implementation detail of Mutex. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class MutexImpl {
- public:
-  MutexImpl();
-  MutexImpl(const MutexImpl&) = delete;
-  MutexImpl& operator=(const MutexImpl&) = delete;
-  ~MutexImpl();
-
-  void Lock();
-  bool TryLock();
-  void Unlock();
-  void Await(const Condition& cond);
-  bool AwaitWithDeadline(const Condition& cond, absl::Time deadline);
-
- private:
-  friend class CondVarImpl;
-
-#if defined(_WIN32)
-  std::mutex std_mutex_;
-#else
-  pthread_mutex_t pthread_mutex_;
-#endif
-
-  // True if the underlying mutex is locked.  If the destructor is entered
-  // while locked_, the underlying mutex is unlocked.  Mutex supports
-  // destruction while locked, but the same is undefined behavior for both
-  // pthread_mutex_t and std::mutex.
-  bool locked_ = false;
-
-  // Signaled before releasing the lock, in support of Await.
-  CondVarImpl released_;
-};
-
-// Do not use this implementation detail of CondVar and Mutex.  A storage
-// space for T that supports a LinkerInitialized constructor. T must
-// have a default constructor, which is called by the first call to
-// get(). T's destructor is never called if the LinkerInitialized
-// constructor is called.
-//
-// Objects constructed with the default constructor are constructed and
-// destructed like any other object, and should never be allocated in
-// static storage.
-//
-// Objects constructed with the LinkerInitialized constructor should
-// always be in static storage. For such objects, calls to get() are always
-// valid, except from signal handlers.
-//
-// Note that this implementation relies on undefined language behavior that
-// are known to hold for the set of supported compilers. An analysis
-// follows.
-//
-// From the C++11 standard:
-//
-// [basic.life] says an object has non-trivial initialization if it is of
-// class type and it is initialized by a constructor other than a trivial
-// default constructor.  (the LinkerInitialized constructor is
-// non-trivial)
-//
-// [basic.life] says the lifetime of an object with a non-trivial
-// constructor begins when the call to the constructor is complete.
-//
-// [basic.life] says the lifetime of an object with non-trivial destructor
-// ends when the call to the destructor begins.
-//
-// [basic.life] p5 specifies undefined behavior when accessing non-static
-// members of an instance outside its
-// lifetime. (SynchronizationStorage::get() access non-static members)
-//
-// So, LinkerInitialized object of SynchronizationStorage uses a
-// non-trivial constructor, which is called at some point during dynamic
-// initialization, and is therefore subject to order of dynamic
-// initialization bugs, where get() is called before the object's
-// constructor is, resulting in undefined behavior.
-//
-// Similarly, a LinkerInitialized SynchronizationStorage object has a
-// non-trivial destructor, and so its lifetime ends at some point during
-// destruction of objects with static storage duration [basic.start.term]
-// p4. There is a window where other exit code could call get() after this
-// occurs, resulting in undefined behavior.
-//
-// Combined, these statements imply that LinkerInitialized instances
-// of SynchronizationStorage<T> rely on undefined behavior.
-//
-// However, in practice, the implementation works on all supported
-// compilers. Specifically, we rely on:
-//
-// a) zero-initialization being sufficient to initialize
-// LinkerInitialized instances for the purposes of calling
-// get(), regardless of when the constructor is called. This is
-// because the is_dynamic_ boolean is correctly zero-initialized to
-// false.
-//
-// b) the LinkerInitialized constructor is a NOP, and immaterial to
-// even to concurrent calls to get().
-//
-// c) the destructor being a NOP for LinkerInitialized objects
-// (guaranteed by a check for !is_dynamic_), and so any concurrent and
-// subsequent calls to get() functioning as if the destructor were not
-// called, by virtue of the instances' storage remaining valid after the
-// destructor runs.
-//
-// d) That a-c apply transitively when SynchronizationStorage<T> is the
-// only member of a class allocated in static storage.
-//
-// Nothing in the language standard guarantees that a-d hold.  In practice,
-// these hold in all supported compilers.
-//
-// Future direction:
-//
-// Ideally, we would simply use std::mutex or a similar class, which when
-// allocated statically would support use immediately after static
-// initialization up until static storage is reclaimed (i.e. the properties
-// we require of all "linker initialized" instances).
-//
-// Regarding construction in static storage, std::mutex is required to
-// provide a constexpr default constructor [thread.mutex.class], which
-// ensures the instance's lifetime begins with static initialization
-// [basic.start.init], and so is immune to any problems caused by the order
-// of dynamic initialization. However, as of this writing Microsoft's
-// Visual Studio does not provide a constexpr constructor for std::mutex.
-// See
-// https://blogs.msdn.microsoft.com/vcblog/2015/06/02/constexpr-complete-for-vs-2015-rtm-c11-compiler-c17-stl/
-//
-// Regarding destruction of instances in static storage, [basic.life] does
-// say an object ends when storage in which the occupies is released, in
-// the case of non-trivial destructor. However, std::mutex is not specified
-// to have a trivial destructor.
-//
-// So, we would need a class with a constexpr default constructor and a
-// trivial destructor. Today, we can achieve neither desired property using
-// std::mutex directly.
-template <typename T>
-class SynchronizationStorage {
- public:
-  // Instances allocated on the heap or on the stack should use the default
-  // constructor.
-  SynchronizationStorage()
-      : destruct_(true), once_() {}
-
-  constexpr explicit SynchronizationStorage(absl::ConstInitType)
-      : destruct_(false), once_(), space_{{0}} {}
-
-  SynchronizationStorage(SynchronizationStorage&) = delete;
-  SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
-
-  ~SynchronizationStorage() {
-    if (destruct_) {
-      get()->~T();
-    }
-  }
-
-  // Retrieve the object in storage. This is fast and thread safe, but does
-  // incur the cost of absl::call_once().
-  T* get() {
-    absl::call_once(once_, SynchronizationStorage::Construct, this);
-    return reinterpret_cast<T*>(&space_);
-  }
-
- private:
-  static void Construct(SynchronizationStorage<T>* self) {
-    new (&self->space_) T();
-  }
-
-  // When true, T's destructor is run when this is destructed.
-  const bool destruct_;
-
-  absl::once_flag once_;
-
-  // An aligned space for the T.
-  alignas(T) unsigned char space_[sizeof(T)];
-};
-
-}  // namespace synchronization_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index b6150b9..2123be6 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -48,6 +48,7 @@
 #include "absl/base/optimization.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
@@ -66,71 +67,6 @@
 
 #if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX
 
-// Some Android headers are missing these definitions even though they
-// support these futex operations.
-#ifdef __BIONIC__
-#ifndef SYS_futex
-#define SYS_futex __NR_futex
-#endif
-#ifndef FUTEX_WAIT_BITSET
-#define FUTEX_WAIT_BITSET 9
-#endif
-#ifndef FUTEX_PRIVATE_FLAG
-#define FUTEX_PRIVATE_FLAG 128
-#endif
-#ifndef FUTEX_CLOCK_REALTIME
-#define FUTEX_CLOCK_REALTIME 256
-#endif
-#ifndef FUTEX_BITSET_MATCH_ANY
-#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
-#endif
-#endif
-
-#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
-#define SYS_futex_time64 __NR_futex_time64
-#endif
-
-#if defined(SYS_futex_time64) && !defined(SYS_futex)
-#define SYS_futex SYS_futex_time64
-#endif
-
-class Futex {
- public:
-  static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
-                       KernelTimeout t) {
-    int err = 0;
-    if (t.has_timeout()) {
-      // https://locklessinc.com/articles/futex_cheat_sheet/
-      // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
-      struct timespec abs_timeout = t.MakeAbsTimespec();
-      // Atomically check that the futex value is still 0, and if it
-      // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
-      err = syscall(
-          SYS_futex, reinterpret_cast<int32_t *>(v),
-          FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
-          &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
-    } else {
-      // Atomically check that the futex value is still 0, and if it
-      // is, sleep until woken by FUTEX_WAKE.
-      err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
-                    FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
-    }
-    if (err != 0) {
-      err = -errno;
-    }
-    return err;
-  }
-
-  static int Wake(std::atomic<int32_t> *v, int32_t count) {
-    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
-                      FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
-    if (ABSL_PREDICT_FALSE(err < 0)) {
-      err = -errno;
-    }
-    return err;
-  }
-};
-
 Waiter::Waiter() {
   futex_.store(0, std::memory_order_relaxed);
 }
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index 887f9b1..be3df18 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -36,6 +36,7 @@
 #include <cstdint>
 
 #include "absl/base/internal/thread_identity.h"
+#include "absl/synchronization/internal/futex.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
 // May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index>
@@ -48,12 +49,7 @@
 #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
 #elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
-#elif defined(__BIONIC__)
-// Bionic supports all the futex operations we need even when some of the futex
-// definitions are missing.
-#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
-#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
-// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
+#elif defined(ABSL_INTERNAL_HAVE_FUTEX)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
 #elif defined(ABSL_HAVE_SEMAPHORE_H)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 9b7f088..9e01393 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -50,6 +50,7 @@
 #include "absl/base/internal/spinlock.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/base/internal/thread_identity.h"
+#include "absl/base/internal/tsan_mutex_interface.h"
 #include "absl/base/port.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/symbolize.h"
@@ -88,8 +89,8 @@
 ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);
 
 ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
-    absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
-        submit_profile_data;
+absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
+    submit_profile_data;
 ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
     const char *msg, const void *obj, int64_t wait_cycles)>
     mutex_tracer;
@@ -491,7 +492,7 @@
   std::atomic<intptr_t> *cv_word;
 
   int64_t contention_start_cycles;  // Time (in cycles) when this thread started
-                                  // to contend for the mutex.
+                                    // to contend for the mutex.
 };
 
 struct SynchLocksHeld {
@@ -705,7 +706,7 @@
 static constexpr bool kDebugMode = true;
 #endif
 
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
 static unsigned TsanFlags(Mutex::MuHow how) {
   return how == kShared ? __tsan_mutex_read_lock : 0;
 }
@@ -1767,7 +1768,7 @@
   // All memory accesses are ignored inside of mutex operations + for unlock
   // operation tsan considers that we've already released the mutex.
   bool res = false;
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
   const int flags = read_lock ? __tsan_mutex_read_lock : 0;
   const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
 #endif
@@ -2311,7 +2312,8 @@
     if (!cond_waiter) {
       // Sample lock contention events only if the (first) waiter was trying to
       // acquire the lock, not waiting on a condition variable or Condition.
-      int64_t wait_cycles = base_internal::CycleClock::Now() - enqueue_timestamp;
+      int64_t wait_cycles =
+          base_internal::CycleClock::Now() - enqueue_timestamp;
       mutex_tracer("slow release", this, wait_cycles);
       ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
       submit_profile_data(enqueue_timestamp);
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index 52401fe..598d1e0 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -31,22 +31,23 @@
 //
 //  MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/
 //              write access within the current scope.
+//
 //  ReaderMutexLock
 //            - An RAII wrapper to acquire and release a `Mutex` for shared/read
 //              access within the current scope.
 //
 //  WriterMutexLock
-//            - Alias for `MutexLock` above, designed for use in distinguishing
-//              reader and writer locks within code.
+//            - Effectively an alias for `MutexLock` above, designed for use in
+//              distinguishing reader and writer locks within code.
 //
 // In addition to simple mutex locks, this file also defines ways to perform
 // locking under certain conditions.
 //
-//  Condition   - (Preferred) Used to wait for a particular predicate that
-//                depends on state protected by the `Mutex` to become true.
-//  CondVar     - A lower-level variant of `Condition` that relies on
-//                application code to explicitly signal the `CondVar` when
-//                a condition has been met.
+//  Condition - (Preferred) Used to wait for a particular predicate that
+//              depends on state protected by the `Mutex` to become true.
+//  CondVar   - A lower-level variant of `Condition` that relies on
+//              application code to explicitly signal the `CondVar` when
+//              a condition has been met.
 //
 // See below for more information on using `Condition` or `CondVar`.
 //
@@ -72,15 +73,6 @@
 #include "absl/synchronization/internal/per_thread_sem.h"
 #include "absl/time/time.h"
 
-// Decide if we should use the non-production implementation because
-// the production implementation hasn't been fully ported yet.
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-#error ABSL_INTERNAL_USE_NONPROD_MUTEX cannot be directly set
-#elif defined(ABSL_LOW_LEVEL_ALLOC_MISSING)
-#define ABSL_INTERNAL_USE_NONPROD_MUTEX 1
-#include "absl/synchronization/internal/mutex_nonprod.inc"
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -461,15 +453,6 @@
   static void InternalAttemptToUseMutexInFatalSignalHandler();
 
  private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-  friend class CondVar;
-
-  synchronization_internal::MutexImpl *impl() { return impl_.get(); }
-
-  synchronization_internal::SynchronizationStorage<
-      synchronization_internal::MutexImpl>
-      impl_;
-#else
   std::atomic<intptr_t> mu_;  // The Mutex state.
 
   // Post()/Wait() versus associated PerThreadSem; in class for required
@@ -504,7 +487,6 @@
   void Trans(MuHow how);  // used for CondVar->Mutex transfer
   void Fer(
       base_internal::PerThreadSynch *w);  // used for CondVar->Mutex transfer
-#endif
 
   // Catch the error of writing Mutex when intending MutexLock.
   Mutex(const volatile Mutex * /*ignored*/) {}  // NOLINT(runtime/explicit)
@@ -525,22 +507,36 @@
 // Example:
 //
 // Class Foo {
-//
+//  public:
 //   Foo::Bar* Baz() {
-//     MutexLock l(&lock_);
+//     MutexLock lock(&mu_);
 //     ...
 //     return bar;
 //   }
 //
 // private:
-//   Mutex lock_;
+//   Mutex mu_;
 // };
 class ABSL_SCOPED_LOCKABLE MutexLock {
  public:
+  // Constructors
+
+  // Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is
+  // guaranteed to be locked when this object is constructed. Requires that
+  // `mu` be dereferenceable.
   explicit MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
     this->mu_->Lock();
   }
 
+  // Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to
+  // the above, the condition given by `cond` is also guaranteed to hold when
+  // this object is constructed.
+  explicit MutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    this->mu_->LockWhen(cond);
+  }
+
   MutexLock(const MutexLock &) = delete;  // NOLINT(runtime/mutex)
   MutexLock(MutexLock&&) = delete;  // NOLINT(runtime/mutex)
   MutexLock& operator=(const MutexLock&) = delete;
@@ -562,6 +558,12 @@
     mu->ReaderLock();
   }
 
+  explicit ReaderMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_SHARED_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    mu->ReaderLockWhen(cond);
+  }
+
   ReaderMutexLock(const ReaderMutexLock&) = delete;
   ReaderMutexLock(ReaderMutexLock&&) = delete;
   ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
@@ -584,6 +586,12 @@
     mu->WriterLock();
   }
 
+  explicit WriterMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    mu->WriterLockWhen(cond);
+  }
+
   WriterMutexLock(const WriterMutexLock&) = delete;
   WriterMutexLock(WriterMutexLock&&) = delete;
   WriterMutexLock& operator=(const WriterMutexLock&) = delete;
@@ -622,16 +630,26 @@
 // `noexcept`; until then this requirement cannot be enforced in the
 // type system.)
 //
-// Note: to use a `Condition`, you need only construct it and pass it within the
-// appropriate `Mutex' member function, such as `Mutex::Await()`.
+// Note: to use a `Condition`, you need only construct it and pass it to a
+// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
+// constructor of one of the scope guard classes.
 //
-// Example:
+// Example using LockWhen/Unlock:
 //
 //   // assume count_ is not internal reference count
 //   int count_ ABSL_GUARDED_BY(mu_);
+//   Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
 //
-//   mu_.LockWhen(Condition(+[](int* count) { return *count == 0; },
-//         &count_));
+//   mu_.LockWhen(count_is_zero);
+//   // ...
+//   mu_.Unlock();
+//
+// Example using a scope guard:
+//
+//   {
+//     MutexLock lock(&mu_, count_is_zero);
+//     // ...
+//   }
 //
 // When multiple threads are waiting on exactly the same condition, make sure
 // that they are constructed with the same parameters (same pointer to function
@@ -686,10 +704,10 @@
   //   };
   //   mu_.Await(Condition(&reached));
   //
-  // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReadHeld()" in the
-  // lambda as it may be called when the mutex is being unlocked from a scope
-  // holding only a reader lock, which will make the assertion not fulfilled and
-  // crash the binary.
+  // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in
+  // the lambda as it may be called when the mutex is being unlocked from a
+  // scope holding only a reader lock, which will make the assertion not
+  // fulfilled and crash the binary.
 
   // See class comment for performance advice. In particular, if there
   // might be more than one waiter for the same condition, make sure
@@ -838,17 +856,10 @@
   void EnableDebugLog(const char *name);
 
  private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-  synchronization_internal::CondVarImpl *impl() { return impl_.get(); }
-  synchronization_internal::SynchronizationStorage<
-      synchronization_internal::CondVarImpl>
-      impl_;
-#else
   bool WaitCommon(Mutex *mutex, synchronization_internal::KernelTimeout t);
   void Remove(base_internal::PerThreadSynch *s);
   void Wakeup(base_internal::PerThreadSynch *w);
   std::atomic<intptr_t> cv_;  // Condition variable state.
-#endif
   CondVar(const CondVar&) = delete;
   CondVar& operator=(const CondVar&) = delete;
 };
@@ -870,6 +881,15 @@
       this->mu_->Lock();
     }
   }
+
+  explicit MutexLockMaybe(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    if (this->mu_ != nullptr) {
+      this->mu_->LockWhen(cond);
+    }
+  }
+
   ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
     if (this->mu_ != nullptr) { this->mu_->Unlock(); }
   }
@@ -892,6 +912,13 @@
       : mu_(mu) {
     this->mu_->Lock();
   }
+
+  explicit ReleasableMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    this->mu_->LockWhen(cond);
+  }
+
   ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
     if (this->mu_ != nullptr) { this->mu_->Unlock(); }
   }
@@ -906,12 +933,6 @@
   ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;
 };
 
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-
-inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
-
-#else
-
 inline Mutex::Mutex() : mu_(0) {
   ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
 }
@@ -920,8 +941,6 @@
 
 inline CondVar::CondVar() : cv_(0) {}
 
-#endif  // ABSL_INTERNAL_USE_NONPROD_MUTEX
-
 // static
 template <typename T>
 bool Condition::CastAndCallMethod(const Condition *c) {
@@ -988,7 +1007,7 @@
 //
 // This has the same memory ordering concerns as RegisterMutexProfiler() above.
 void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
-                              int64_t wait_cycles));
+                                    int64_t wait_cycles));
 
 // TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer()
 // into a single interface, since they are only ever called in pairs.
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index 307d0e3..058f757 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -707,6 +707,40 @@
   t.join();
 }
 
+TEST(Mutex, LockWhenGuard) {
+  absl::Mutex mu;
+  int n = 30;
+  bool done = false;
+
+  // We don't inline the lambda because the conversion is ambiguous in MSVC.
+  bool (*cond_eq_10)(int *) = [](int *p) { return *p == 10; };
+  bool (*cond_lt_10)(int *) = [](int *p) { return *p < 10; };
+
+  std::thread t1([&mu, &n, &done, cond_eq_10]() {
+    absl::ReaderMutexLock lock(&mu, absl::Condition(cond_eq_10, &n));
+    done = true;
+  });
+
+  std::thread t2[10];
+  for (std::thread &t : t2) {
+    t = std::thread([&mu, &n, cond_lt_10]() {
+      absl::WriterMutexLock lock(&mu, absl::Condition(cond_lt_10, &n));
+      ++n;
+    });
+  }
+
+  {
+    absl::MutexLock lock(&mu);
+    n = 0;
+  }
+
+  for (std::thread &t : t2) t.join();
+  t1.join();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(n, 10);
+}
+
 // --------------------------------------------------------
 // The following test requires Mutex::ReaderLock to be a real shared
 // lock, which is not the case in all builds.
@@ -1002,9 +1036,6 @@
   x.mu0.Unlock();
 }
 
-// The deadlock detector is not part of non-prod builds, so do not test it.
-#if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
-
 TEST(Mutex, DeadlockDetector) {
   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
 
@@ -1102,7 +1133,7 @@
 // annotation-based static thread-safety analysis is not currently
 // predicate-aware and cannot tell if the two for-loops that acquire and
 // release the locks have the same predicates.
-TEST(Mutex, DeadlockDetectorStessTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
   // Stress test: Here we create a large number of locks and use all of them.
   // If a deadlock detector keeps a full graph of lock acquisition order,
   // it will likely be too slow for this test to pass.
@@ -1158,7 +1189,6 @@
   c.Lock();
   c.Unlock();
 }
-#endif  // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
 
 // --------------------------------------------------------
 // Test for timeouts/deadlines on condition waits that are specified using
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 1d69f59..991241a 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "time",
diff --git a/absl/time/clock.cc b/absl/time/clock.cc
index e5c423c..6862e01 100644
--- a/absl/time/clock.cc
+++ b/absl/time/clock.cc
@@ -74,9 +74,7 @@
 #if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
 namespace absl {
 ABSL_NAMESPACE_BEGIN
-int64_t GetCurrentTimeNanos() {
-  return GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
-}
+int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); }
 ABSL_NAMESPACE_END
 }  // namespace absl
 #else  // Use the cyclecounter-based implementation below.
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 952cc09..4443109 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -356,7 +356,7 @@
 // the remainder.  If it does not saturate, the remainder remain accurate,
 // but the returned quotient will over/underflow int64_t and should not be used.
 int64_t IDivDuration(bool satq, const Duration num, const Duration den,
-                   Duration* rem) {
+                     Duration* rem) {
   int64_t q = 0;
   if (IDivFastPath(num, den, &q, rem)) {
     return q;
@@ -763,7 +763,8 @@
 //   form "72h3m0.5s". Leading zero units are omitted.  As a special
 //   case, durations less than one second format use a smaller unit
 //   (milli-, micro-, or nanoseconds) to ensure that the leading digit
-//   is non-zero.  The zero duration formats as 0, with no unit.
+//   is non-zero.
+// Unlike Go, we format the zero duration as 0, with no unit.
 std::string FormatDuration(Duration d) {
   const Duration min_duration = Seconds(kint64min);
   if (d == min_duration) {
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 7a53c81..45a9529 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -16,7 +16,7 @@
 
 package(features = ["-parse_headers"])
 
-licenses(["notice"])  # Apache License
+licenses(["notice"])
 
 filegroup(
     name = "zoneinfo",
@@ -92,6 +92,11 @@
 
 ### tests
 
+test_suite(
+    name = "all_tests",
+    visibility = ["//visibility:public"],
+)
+
 cc_test(
     name = "civil_time_test",
     size = "small",
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index d1b4222..8aadde5 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -416,16 +416,10 @@
 
   // Assigning arithmetic.
   CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
-    f_ = step(T{}, f_, n);
-    return *this;
+    return *this = *this + n;
   }
   CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
-    if (n != (std::numeric_limits<diff_t>::min)()) {
-      f_ = step(T{}, f_, -n);
-    } else {
-      f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
-    }
-    return *this;
+    return *this = *this - n;
   }
   CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
   CONSTEXPR_M civil_time operator++(int) noexcept {
@@ -442,13 +436,15 @@
 
   // Binary arithmetic operators.
   friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
-    return a += n;
+    return civil_time(step(T{}, a.f_, n));
   }
   friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {
-    return a += n;
+    return a + n;
   }
   friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
-    return a -= n;
+    return n != (std::numeric_limits<diff_t>::min)()
+               ? civil_time(step(T{}, a.f_, -n))
+               : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
   }
   friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
     return difference(T{}, lhs.f_, rhs.f_);
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 53641bf..9a1a8d6 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -1007,7 +1007,11 @@
     const time_zone cut = LoadZone("libc:UTC");
     const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;
     tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut);
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+    // The BSD gmtime_r() fails on extreme positive tm_year values.
+#else
     EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut));
+#endif
     const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;
     tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut);
     EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut));
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index 7f680ee..b4410dc 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2020a
+2020d
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
index 697b993..9ca907b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
index ae04342..56a4dd2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
index 82ea5aa..0da1d1e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
index d3f8196..ea38c97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
index d39016b..0263c90 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
index 850c8f0..a461dce 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
index 066fbed..772e23c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
index 625b1ac..36b0522 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
index 8ee8cb9..3f8e44b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
index 6d68850..8377809 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
index a968845..ecbc096 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
index 59f3759..425ad3f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
index 07b393b..e0c8997 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
index 427fa56..ca324cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
index abecd13..0edc52b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Adak b/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
index 4323649..b1497bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage b/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
index 9bbb2fd..cdf0572 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla b/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua b/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina b/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
index 49381b4..f66c9f7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
index 260f86a..d6f999b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
index 0ae222a..1dcc8d8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
index 0ae222a..1dcc8d8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
index da4c23a..35a52e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
index 604b856..b275f27 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
index 2218e36..23fca12 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
index f9e677f..691c569 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
index c36587e..991d1fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
index 0e797f2..58863e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
index 2698495..7eba33c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
index fe50f62..0a81cbd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
index c954000..10556d5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
index 3643628..e031750 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba b/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
index 2f3bbda..6225036 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan b/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
index 629ed42..c828715 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Atka b/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
index 4323649..b1497bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
index 15808d3..7969e30 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
index 896af3f..cbe22a7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados b/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
index 9b90e30..9d3afa6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Belem b/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
index 60b5924..e0d7653 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Belize b/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
index 851051a..de99b84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon b/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
index f9f13a1..7096b69 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista b/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
index 978c331..fca9720 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota b/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
index b2647d7..6cb53d4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Boise b/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
index f8d54e2..72fec9e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires b/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
index 260f86a..d6f999b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
index f8db4b6..0a22252 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande b/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
index 8120624..6855e4e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
index f907f0a..640b259 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas b/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
index eedf725..8dbe6ff 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca b/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
index 0ae222a..1dcc8d8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
index e5bc06f..cd49f05 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
index 9964b9a..9154643 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago b/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
index a5b1617..b016880 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
index 8ed5f93..e1780a5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour b/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
index 629ed42..c828715 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba b/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
index da4c23a..35a52e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica b/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
index 37cb85e..08f0128 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Creston b/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
index ca64857..9d69a0a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba b/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
index 9bea3d4..c09a875 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao b/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn b/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
index 9549adc..8718efc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
index 2b6c3ee..07e4c5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
index db9e339..761d1d9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Denver b/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit b/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
index e104faa..6eb3ac4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica b/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton b/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
index cd78a6f..645ee94 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe b/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
index 39d6dae..7da4b98 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador b/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
index e2f2230..4348411 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
index 5a0b7f1..2a49c6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza b/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
index be57dc2..092e40d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
index 48412a4..f85eb34 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab b/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
index 0160308..4ddc99d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
index a3f2990..820e0dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk b/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
index b9bb063..062fcae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe b/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala b/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
index 407138c..8aa8e58 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil b/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
index 0559a7a..381ae6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana b/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
index d5dab14..ebd85d0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax b/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
index 756099a..9fa850a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Havana b/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
index b69ac45..e06629d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
index 791a9fa..8283239 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
index fcd408d..b187d5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
index 1abf75e..a730fe6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
index 0133548..341a023 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
index 7bbb653..76e1f62 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
index d236b7c..f2acf6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
index c818929..c255f89 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
index 630935c..8700ed9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis b/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik b/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
index 87bb355..af3107d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit b/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
index c8138bd..eb2c99c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica b/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
index 2a9b7fd..be6b1b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy b/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
index 604b856..b275f27 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau b/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
index 451f349..e347b36 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
index 177836e..f2136d6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
index 438e3ea..d9f54a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN b/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
index fcd408d..b187d5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk b/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz b/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
index a101372..68ddaae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Lima b/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
index 3c6529b..b643c55 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles b/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
index 9dad4f4..aaf0778 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville b/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
index 177836e..f2136d6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes b/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio b/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
index bc8b951..dbb8d57 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Managua b/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
index e0242bf..86ef76b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus b/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
index 63d58f8..59c952e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot b/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique b/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
index 8df43dc..25c0232 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros b/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
index 047968d..722751b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
index e4a7857..4c819fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza b/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
index f9e677f..691c569 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee b/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
index 3146138..28d2c56 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
index ea852da..d3b0ca1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla b/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
index 1e94be3..9fefee3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
index e7fb6f2..ffcf8be 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon b/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
index b924b71..3b62585 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton b/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
index 9df8d0f..ecb69ef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
index a8928c8..dea9e3f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo b/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
index 2f357bc..4b2fb3e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal b/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
index 6752c5b..fe6be8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat b/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau b/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
index 33cc6c6..cf1e92d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/New_York b/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
index 2f75480..2b6c2ee 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon b/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
index f6a856e..b9f67a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nome b/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
index 10998df..23ead1c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha b/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
index f140726..9e74745 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
index 246345d..becf438 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
index 1fa0703..d03bda0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
index 123f2ae..ecefc15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk b/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
index 0160308..4ddc99d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
index fc4a03e..da0909c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Panama b/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
index 9964b9a..9154643 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung b/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
index 3e4e0db..5be6f9b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo b/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
index bc8a6ed..24f925a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix b/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
index ac6bb0c..c2bd2f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince b/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
index 287f143..3e75731 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain b/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
index a374cb4..fb5185c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
index 2e873a5..7f8047d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico b/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
index a662a57..47b4dc3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas b/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
index a5a8af5..5c9a20b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River b/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
index ea66099..d6ddda4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet b/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
index 3a70587..92e2ed2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Recife b/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
index d7abb16..305abcb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Regina b/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
index 20c9c84..a3f8217 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute b/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
index 0a73b75..a84d1df 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco b/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
index a374cb4..fb5185c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario b/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
index da4c23a..35a52e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem b/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
index c28f360..f81d144 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago b/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
index 816a042..8d60322 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo b/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
index 4fe36fd..3e07850 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo b/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
index 13ff083..a16da2c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund b/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
index e20e9e1..6db4912 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock b/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka b/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
index 31f7061..36681ed 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
index 65a5b0c..e5f2aec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current b/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
index 8e9ef25..bdbb494 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa b/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
index 2adacb2..38036a3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Thule b/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
index 6f802f1..f38dc56 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
index e504c9a..fcb0328 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto b/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
index 6752c5b..fe6be8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola b/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver b/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
index bb60cbc..c998491 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin b/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse b/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
index 062b58c..878b6a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg b/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
index ac40299..7e646d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat b/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
index da209f9..773feba 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife b/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
index e6afa39..c779cef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
index f100f47..30315cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
index 916f2c2..3ec3222 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
index a71b39c..c0cfc85 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
index 616afd9..232717b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
index b32e7fd..05e4c6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
index 3dd85f8..32c1941 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
index 8b2430a..ea49c00 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
index 254af7d..97d80d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
index 5e565da..4e31aff 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
index 7283053..6e32907 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen b/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
index 15a34c3..dfc5095 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
index 2aea25f..01c47cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
index a4b0077..3ec4fc8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
index c9e8707..1bd09fe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
index 6ed8b7c..551884d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
index e2d0f91..3a40d11 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
index 06f0a13..62c5840 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
index 73891af..8482167 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
index 73891af..8482167 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
index 8b5153e..cb2c82f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
index f7162ed..a3ce975 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
index 63188b2..7409d74 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
index a0de74b..96203d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
index c292ac5..ed687d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
index 759592a..ff976dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
index fb266ed..55dce57 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
index f6e20dd..fe7832c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
index 3dab0ab..e67b411 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
index 0014046..00bc80a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
index c4149c0..9d49cd3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
index e48daa8..0a948c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
index 91f6f8b..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
index 91f6f8b..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
index 62c64d8..3eeb1b7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
index b11c928..2813680 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
index d9104a7..168ef9b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
index b11c928..2813680 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
index 30943bb..bb7be9f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
index fc0a589..58d75bc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
index 82d85b8..d83fb07 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
index 653b146..cc44179 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
index 592b632..4278ffa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
index 91f6f8b..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
index ae82f9b..e55318a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
index e2934e3..7ca9972 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
index 23d0375..c80e364 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
index 4cb800a..6e08a26 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
index 4dcbbb7..550e2a0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
index 508446b..c891866 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
index 5baa3a8..c9752d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
index 3002c82..7c22f53 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
index 440ef06..e6e6cc6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
index d19b9bd..660ce4c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
index 3e80b4e..c651554 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
index ba65c0e..e56d5af 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
index faa14d9..69ff7f6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
index a5d5107..3a0d330 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
index a5d5107..3a0d330 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
index 72bea64..aeb7332 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
index 0014046..00bc80a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
index 30c6f16..e0d4fcb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
index 612b01e..e93dd51 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
index c86750c..59bc6e4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
index 2aea25f..01c47cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
index cac6506..c22f75e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
index cac6506..c22f75e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
index b4fcac1..16bac84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
index 556ba86..5990010 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
index f4f4b04..3c3584e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
index fc0a589..58d75bc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
index f7f10ab..c210d0a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
index d983276..9378d50 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
index e0ee5fc..65a9fa2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
index b29b769..dc0ed42 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
index ad1f9ca..25a63ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
index c292ac5..ed687d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
index 12ce24c..285bed2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
index 7ad7e0b..57240cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
index 63188b2..7409d74 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
index 73b9d96..ff6fe61 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
index c2fe4c1..fe4d6c6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
index dd77395..14b2ad0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
index 2aea25f..01c47cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
index e2934e3..7ca9972 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
index 485459c..69f0faa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
index 030d47c..c43e27c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
index 96199e7..1755147 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
index 91f6f8b..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
index 2364b21..350d77e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
index 261a983..7fdee5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
index 24c4344..35d89d0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
index 32a9d7d..65ee428 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
index b608d79..166e434 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
index 8cec5ad..f1555f0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
index 440ef06..e6e6cc6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
index fe409c7..0edc72c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
index fe409c7..0edc72c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
index 26f4d34..1aa066c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
index 670e2ad..c3c307d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
index 556ba86..5990010 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
index 2e20cc3..6f5d3a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
index 2e20cc3..6f5d3a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
index faa14d9..69ff7f6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
index 9e4a78f..c39331e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
index c292ac5..ed687d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
index 8ab253c..72a3d4e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
index c815e99..336f932 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
index dd77395..14b2ad0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
index 6958d7e..a3bf7f2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
index 250bfe0..6dd927c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
index 56593db..b7f75a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
index 419c660..aa33014 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
index f319215..5ab3243 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
index e2a49d2..8f7de1c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
index 4dab7ef..9558bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
index 4dab7ef..9558bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
index 15a34c3..dfc5095 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
index 5213761..7c3a49c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
index 10e0fc8..2451aca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
index 4466608..7fa5f46 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
index 88077f1..1a4c8ea 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT b/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
index 0b1252a..f397b3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
index 3021bdb..c7915db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
index 1ac3fc8..ed0d17a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
index f65a990..55ceaef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
index 1cf5029..7114153 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
index 98ae557..9fbc01f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
index 02b07ca..21ef2d3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI b/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
index 9e04a80..4d4ec8c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
index eab0fb9..e271d5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
index 9e04a80..4d4ec8c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
index ba45733..c7160da 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW b/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/North b/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
index 1cf5029..7114153 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
index a876b9e..e449b03 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
index 3021bdb..c7915db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/South b/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
index 0b1252a..f397b3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
index 02b07ca..21ef2d3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
index ba45733..c7160da 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/West b/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
index a876b9e..e449b03 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
index 1ac3fc8..ed0d17a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
index a374cb4..fb5185c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
index f140726..9e74745 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
index 13ff083..a16da2c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
index 63d58f8..59c952e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CET b/absl/time/internal/cctz/testdata/zoneinfo/CET
index 122e934..546748d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
index ca67929..d931558 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
index 756099a..9fa850a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
index ac40299..7e646d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
index 6752c5b..fe6be8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
index cd78a6f..645ee94 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
index 65a5b0c..e5f2aec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
index bb60cbc..c998491 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
index 20c9c84..a3f8217 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
index 062b58c..878b6a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental b/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
index 816a042..8d60322 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland b/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
index cae3744..d29bcd6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Cuba b/absl/time/internal/cctz/testdata/zoneinfo/Cuba
index b69ac45..e06629d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Cuba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Cuba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EET b/absl/time/internal/cctz/testdata/zoneinfo/EET
index cbdb71d..378919e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST b/absl/time/internal/cctz/testdata/zoneinfo/EST
index 21ebc00..3ae9691 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
index 9bce500..50c95e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Egypt b/absl/time/internal/cctz/testdata/zoneinfo/Egypt
index d3f8196..ea38c97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Egypt
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Egypt
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Eire b/absl/time/internal/cctz/testdata/zoneinfo/Eire
index 1d99490..4a45ea8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Eire
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Eire
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
index 4dab6f9..98d5dcf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
index c749290..ecb287e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
index d969982..e941412 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
index cdeec90..9c95bd0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
index fbd2a94..6d5ce3d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
index ee246ef..5ef7be7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
index 5a25ff2..75f1621 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
index c0b745f..589990a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
index 06e777d..fcb60ca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
index 4e0b53a..c0427a4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
index 714b0c5..9bdc228 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
index 78b9daa..ca7a81f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
index a838beb..cb45601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
index 68ff77d..11d988e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
index 66af5a4..f4c5d5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
index 17ba505..cd397b0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
index 5f3706c..8fad7c6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
index 7e9f9c4..a595e60 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
index fcef6d9..97b44a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
index 27973bc..4eb17ff 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
index 1efd841..13aef80 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
index 1f76184..83a2816 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
index 952681e..79a983e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
index cefc912..e136690 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
index afb093d..bc70fe4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
index 9265fb7..d18cedd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
index c3ff07b..4a6fa1d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
index 5962550..38685d4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
index 73a4d01..aff8d82 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
index 9f3a067..231bf9c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
index 7f6d958..465546b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
index ce8f433..fb7c145 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
index 40d7124..3197327 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
index 4303b90..efa689b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
index 6b94a4f..940be46 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
index ad6cf59..388df29 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
index 5ee23fe..6970b14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
index 776be6e..45984a7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
index 1d99490..4a45ea8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
index 117aadb..017bb2e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
index b4f8f9c..ff5e565 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
index 508446b..c891866 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
index cc99bea..0ec4756 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
index 9337c9e..8f83cef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
index a3b5320..d1c93c5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
index 355817b..6484166 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/London b/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
index c4ca733..682bcbf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
index 16f6420..60bdf4d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
index bf2452d..27539c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
index b4f8f9c..ff5e565 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
index 453306c..30d3a67 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
index 686ae88..f30dfc7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
index ddb3f4e..5e6b6de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
index f7f10ab..c210d0a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
index 15a34c3..dfc5095 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
index ca85435..00a2726 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
index ce8f433..fb7c145 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
index 8db477d..26af4c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
index ac4c163..639ca3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
index 97d5dd9..8d0c26e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino b/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
index ac4c163..639ca3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
index 8fd5f6d..2684d8f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
index 432e831..88a6f3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
index 0e4d879..eabc972 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
index f3e0c7f..dd3eb32 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
index b5acca3..5321bbd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
index 0b86017..743a733 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
index 5ee23fe..6970b14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
index 7b61bdc..bb842cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
index 66ae8d6..a575568 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
index ad6cf59..388df29 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
index ac4c163..639ca3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
index 3582bb1..75339e9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
index 7abd63f..75b2eeb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
index d1cfac0..a486ad4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
index e33cf67..efe1a40 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
index e42edfc..4ea8dae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
index ad6cf59..388df29 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Factory b/absl/time/internal/cctz/testdata/zoneinfo/Factory
index 60aa2a0..b4dd773 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Factory
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Factory
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GB b/absl/time/internal/cctz/testdata/zoneinfo/GB
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GB
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GB
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire b/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT b/absl/time/internal/cctz/testdata/zoneinfo/GMT
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT+0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT-0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Greenwich b/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/HST b/absl/time/internal/cctz/testdata/zoneinfo/HST
index cccd45e..160a53e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/HST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/HST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Hongkong b/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
index 23d0375..c80e364 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iceland b/absl/time/internal/cctz/testdata/zoneinfo/Iceland
index 10e0fc8..2451aca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iceland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iceland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
index 93d6dda..8b8ce22 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
index d18c381..766024b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
index f8116e7..1175034 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
index cde4cf7..8ce93e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
index cba7dfe..75362bb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
index 7c839cf..58a82e4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
index 17f2616..7c11134 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
index dfe0831..248a7c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iran b/absl/time/internal/cctz/testdata/zoneinfo/Iran
index 8cec5ad..f1555f0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Israel b/absl/time/internal/cctz/testdata/zoneinfo/Israel
index 440ef06..e6e6cc6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Israel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Israel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Jamaica b/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
index 2a9b7fd..be6b1b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Japan b/absl/time/internal/cctz/testdata/zoneinfo/Japan
index 26f4d34..1aa066c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Japan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Japan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein b/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
index 1a7975f..9416d52 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Libya b/absl/time/internal/cctz/testdata/zoneinfo/Libya
index 07b393b..e0c8997 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Libya
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Libya
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MET b/absl/time/internal/cctz/testdata/zoneinfo/MET
index 4a826bb..6f0558c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST b/absl/time/internal/cctz/testdata/zoneinfo/MST
index c93a58e..a0953d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
index 4506a6e..137867c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
index e4a7857..4c819fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
index e7fb6f2..ffcf8be 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/NZ b/absl/time/internal/cctz/testdata/zoneinfo/NZ
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/NZ
+++ b/absl/time/internal/cctz/testdata/zoneinfo/NZ
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT b/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
index c004109..f06065e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Navajo b/absl/time/internal/cctz/testdata/zoneinfo/Navajo
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Navajo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Navajo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PRC b/absl/time/internal/cctz/testdata/zoneinfo/PRC
index 91f6f8b..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PRC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PRC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
index 99d246b..fde4833 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
index dab1f3f..244af26 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
index 2892d26..7c66709 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
index c004109..f06065e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
index 07c84b7..ea3fb5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
index cae3744..d29bcd6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
index 6015017..906971e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
index f0b8252..b22ab14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
index e40307f..b7b3021 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
index d39bf53..e3934e4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
index ea72863..78ab35b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
index 31f0921..a9403ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
index e1fc3da..ddfc34f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
index 7e9d10a..720c679 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
index 66490d2..bf9a2d9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
index c7cd060..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
index c7cd060..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
index 7cae0cb..2f676d3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
index a584aae..f5d5824 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
index 1a7975f..9416d52 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
index 9ef8374..9228ee0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
index 74d6792..6ea24b7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
index acec042..ae13aac 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
index 684b010..7b35793 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
index 53c1aad..79e2a94 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
index 931a1a3..824f814 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
index 146b351..bc8eb7a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
index ef91b06..8a4ba4d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
index c298ddd..b92b254 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
index c298ddd..b92b254 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
index 920ad27..5d8fc3a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
index da6b0fa..143a188 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
index 66490d2..bf9a2d9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
index 442b8eb..50a064f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
index 3db6c75..6bc2168 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
index 5553c60..54aeb0f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
index 07c84b7..ea3fb5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
index c9e3106..71cca88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
index b35344b..4bce893 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
index 07c84b7..ea3fb5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Poland b/absl/time/internal/cctz/testdata/zoneinfo/Poland
index e33cf67..efe1a40 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Poland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Poland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Portugal b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
index 355817b..6484166 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Portugal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/ROC b/absl/time/internal/cctz/testdata/zoneinfo/ROC
index 24c4344..35d89d0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/ROC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/ROC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/ROK b/absl/time/internal/cctz/testdata/zoneinfo/ROK
index 96199e7..1755147 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/ROK
+++ b/absl/time/internal/cctz/testdata/zoneinfo/ROK
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Singapore b/absl/time/internal/cctz/testdata/zoneinfo/Singapore
index 2364b21..350d77e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Singapore
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Singapore
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Turkey b/absl/time/internal/cctz/testdata/zoneinfo/Turkey
index 508446b..c891866 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Turkey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Turkey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/UCT b/absl/time/internal/cctz/testdata/zoneinfo/UCT
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/UCT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/UCT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska b/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
index 9bbb2fd..cdf0572 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian b/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
index 4323649..b1497bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona b/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
index ac6bb0c..c2bd2f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Central b/absl/time/internal/cctz/testdata/zoneinfo/US/Central
index a5b1617..b016880 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Central
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Central
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana b/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern b/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
index 2f75480..2b6c2ee 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii b/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
index c7cd060..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke b/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
index fcd408d..b187d5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan b/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
index e104faa..6eb3ac4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain b/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific b/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
index 9dad4f4..aaf0778 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa b/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/UTC b/absl/time/internal/cctz/testdata/zoneinfo/UTC
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/UTC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/UTC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Universal b/absl/time/internal/cctz/testdata/zoneinfo/Universal
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Universal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Universal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/W-SU b/absl/time/internal/cctz/testdata/zoneinfo/W-SU
index ddb3f4e..5e6b6de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/W-SU
+++ b/absl/time/internal/cctz/testdata/zoneinfo/W-SU
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/WET b/absl/time/internal/cctz/testdata/zoneinfo/WET
index c27390b..423c6c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/WET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/WET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Zulu b/absl/time/internal/cctz/testdata/zoneinfo/Zulu
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Zulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Zulu
Binary files differ
diff --git a/absl/time/time.cc b/absl/time/time.cc
index 6bb36cb..1ec2026 100644
--- a/absl/time/time.cc
+++ b/absl/time/time.cc
@@ -60,9 +60,10 @@
 inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
   absl::Duration rem;
   int64_t q = absl::IDivDuration(d, unit, &rem);
-  return (q > 0 ||
-          rem >= ZeroDuration() ||
-          q == std::numeric_limits<int64_t>::min()) ? q : q - 1;
+  return (q > 0 || rem >= ZeroDuration() ||
+          q == std::numeric_limits<int64_t>::min())
+             ? q
+             : q - 1;
 }
 
 inline absl::Time::Breakdown InfiniteFutureBreakdown() {
diff --git a/absl/time/time.h b/absl/time/time.h
index 37f6131..7250803 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -639,7 +639,7 @@
   // Deprecated. Use `absl::TimeZone::CivilInfo`.
   struct
       Breakdown {
-    int64_t year;          // year (e.g., 2013)
+    int64_t year;        // year (e.g., 2013)
     int month;           // month of year [1:12]
     int day;             // day of month [1:31]
     int hour;            // hour of day [0:23]
@@ -1494,12 +1494,10 @@
 constexpr bool operator<(Duration lhs, Duration rhs) {
   return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)
              ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)
-             : time_internal::GetRepHi(lhs) ==
-                       (std::numeric_limits<int64_t>::min)()
-                   ? time_internal::GetRepLo(lhs) + 1 <
-                         time_internal::GetRepLo(rhs) + 1
-                   : time_internal::GetRepLo(lhs) <
-                         time_internal::GetRepLo(rhs);
+         : time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)()
+             ? time_internal::GetRepLo(lhs) + 1 <
+                   time_internal::GetRepLo(rhs) + 1
+             : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
 }
 
 constexpr bool operator==(Duration lhs, Duration rhs) {
diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc
index b28a99f..cde9423 100644
--- a/absl/time/time_test.cc
+++ b/absl/time/time_test.cc
@@ -1070,7 +1070,8 @@
   EXPECT_EQ("292277026596-12-04T15:30:07+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),
+      t);
 
   // Checks that we can also get the maximal Time value for a far-east zone.
   const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60);
@@ -1078,7 +1079,8 @@
   EXPECT_EQ("292277026596-12-05T05:30:07+14:00",
             absl::FormatTime(absl::RFC3339_full, t, plus14));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),
+      t);
 
   // One second later should push us to infinity.
   t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc);
@@ -1092,7 +1094,8 @@
   EXPECT_EQ("-292277022657-01-27T08:29:52+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),
+      t);
 
   // Checks that we can also get the minimal Time value for a far-west zone.
   const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60);
@@ -1101,7 +1104,8 @@
   EXPECT_EQ("-292277022657-01-26T20:29:52-12:00",
             absl::FormatTime(absl::RFC3339_full, t, minus12));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),
+      t);
 
   // One second before should push us to -infinity.
   t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc);
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index 102affa..83be936 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -23,7 +23,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "any",
diff --git a/absl/types/BUILD.gn b/absl/types/BUILD.gn
index f9f1515..61ce7f4 100644
--- a/absl/types/BUILD.gn
+++ b/absl/types/BUILD.gn
@@ -7,7 +7,7 @@
 
 absl_source_set("any") {
   public = [ "any.h" ]
-  deps = [
+  public_deps = [
     ":bad_any_cast",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
@@ -21,6 +21,8 @@
   public = [ "bad_any_cast.h" ]
   deps = [
     ":bad_any_cast_impl",
+  ]
+  public_deps = [
     "//third_party/abseil-cpp/absl/base:config",
   ]
 }
@@ -28,8 +30,10 @@
 absl_source_set("bad_any_cast_impl") {
   sources = [ "bad_any_cast.cc" ]
   public = [ "bad_any_cast.h" ]
-  deps = [
+  public_deps = [
     "//third_party/abseil-cpp/absl/base:config",
+  ]
+  deps = [
     "//third_party/abseil-cpp/absl/base:raw_logging_internal",
   ]
   visibility = [ ":*" ]
@@ -38,7 +42,7 @@
 absl_source_set("span") {
   public = [ "span.h" ]
   sources = [ "internal/span.h" ]
-  deps = [
+  public_deps = [
     "//third_party/abseil-cpp/absl/algorithm",
     "//third_party/abseil-cpp/absl/base:core_headers",
     "//third_party/abseil-cpp/absl/base:throw_delegate",
@@ -49,7 +53,7 @@
 absl_source_set("optional") {
   sources = [ "internal/optional.h" ]
   public = [ "optional.h" ]
-  deps = [
+  public_deps = [
     ":bad_optional_access",
     "//third_party/abseil-cpp/absl/base:base_internal",
     "//third_party/abseil-cpp/absl/base:config",
@@ -63,8 +67,10 @@
 absl_source_set("bad_optional_access") {
   sources = [ "bad_optional_access.cc" ]
   public = [ "bad_optional_access.h" ]
-  deps = [
+  public_deps = [
     "//third_party/abseil-cpp/absl/base:config",
+  ]
+  deps = [
     "//third_party/abseil-cpp/absl/base:raw_logging_internal",
   ]
 }
@@ -72,8 +78,10 @@
 absl_source_set("bad_variant_access") {
   sources = [ "bad_variant_access.cc" ]
   public = [ "bad_variant_access.h" ]
-  deps = [
+  public_deps = [
     "//third_party/abseil-cpp/absl/base:config",
+  ]
+  deps = [
     "//third_party/abseil-cpp/absl/base:raw_logging_internal",
   ]
 }
@@ -81,7 +89,7 @@
 absl_source_set("variant") {
   sources = [ "internal/variant.h" ]
   public = [ "variant.h" ]
-  deps = [
+  public_deps = [
     ":bad_variant_access",
     "//third_party/abseil-cpp/absl/base:base_internal",
     "//third_party/abseil-cpp/absl/base:config",
@@ -93,7 +101,7 @@
 
 absl_source_set("compare") {
   public = [ "compare.h" ]
-  deps = [
+  public_deps = [
     "//third_party/abseil-cpp/absl/base:core_headers",
     "//third_party/abseil-cpp/absl/meta:type_traits",
   ]
diff --git a/absl/types/compare.h b/absl/types/compare.h
index 62ca70f..19b076e 100644
--- a/absl/types/compare.h
+++ b/absl/types/compare.h
@@ -86,7 +86,8 @@
 // incomplete types so they need to be defined after the types are complete.
 #ifdef __cpp_inline_variables
 
-#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name)
+// A no-op expansion that can be followed by a semicolon at class level.
+#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "")
 
 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
   static const type name
@@ -99,7 +100,8 @@
 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \
   ABSL_CONST_INIT static const T name
 
-#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name)
+// A no-op expansion that can be followed by a semicolon at class level.
+#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "")
 
 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \
   template <typename T>                            \
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index d404e80..772008c 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -45,7 +45,7 @@
 template <class... Types>
 class variant;
 
-ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
+ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1));
 
 template <class T>
 struct variant_size;
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 776d19a..ac93464 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -604,7 +604,10 @@
 
   // emplace() Functions
 
-  // Constructs a value of the given alternative type T within the variant.
+  // Constructs a value of the given alternative type T within the variant. The
+  // existing value of the variant is destroyed first (provided that
+  // `absl::valueless_by_exception()` is false). Requires that T is unambiguous
+  // in the variant.
   //
   // Example:
   //
@@ -624,7 +627,9 @@
   }
 
   // Constructs a value of the given alternative type T within the variant using
-  // an initializer list.
+  // an initializer list. The existing value of the variant is destroyed first
+  // (provided that `absl::valueless_by_exception()` is false). Requires that T
+  // is unambiguous in the variant.
   //
   // Example:
   //
@@ -643,7 +648,7 @@
   }
 
   // Destroys the current value of the variant (provided that
-  // `absl::valueless_by_exception()` is false, and constructs a new value at
+  // `absl::valueless_by_exception()` is false) and constructs a new value at
   // the given index.
   //
   // Example:
@@ -662,7 +667,7 @@
   }
 
   // Destroys the current value of the variant (provided that
-  // `absl::valueless_by_exception()` is false, and constructs a new value at
+  // `absl::valueless_by_exception()` is false) and constructs a new value at
   // the given index using an initializer list and the provided arguments.
   //
   // Example:
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index cf8f7f3..cf23733 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -2311,7 +2311,8 @@
   ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
   EXPECT_EQ(42, absl::get<int32_t>(variant2));
 
-  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+  variant2 =
+      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
   ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
   EXPECT_EQ(42, absl::get<uint32_t>(variant2));
 #endif  // !ABSL_USES_STD_VARIANT
@@ -2453,7 +2454,8 @@
       ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
   EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
 
-  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+  variant2 =
+      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
   EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
 #endif
 
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index 6881f93..02b2c40 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "utility",
diff --git a/api/audio/echo_canceller3_config.cc b/api/audio/echo_canceller3_config.cc
index aeb809e..5f1923e 100644
--- a/api/audio/echo_canceller3_config.cc
+++ b/api/audio/echo_canceller3_config.cc
@@ -153,6 +153,7 @@
 
   res = res & Limit(&c->filter.config_change_duration_blocks, 0, 100000);
   res = res & Limit(&c->filter.initial_state_seconds, 0.f, 100.f);
+  res = res & Limit(&c->filter.coarse_reset_hangover_blocks, 0, 2500);
 
   res = res & Limit(&c->erle.min, 1.f, 100000.f);
   res = res & Limit(&c->erle.max_l, 1.f, 100000.f);
diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h
index 3ed11ff..55281af 100644
--- a/api/audio/echo_canceller3_config.h
+++ b/api/audio/echo_canceller3_config.h
@@ -86,6 +86,7 @@
 
     size_t config_change_duration_blocks = 250;
     float initial_state_seconds = 2.5f;
+    int coarse_reset_hangover_blocks = 25;
     bool conservative_initial_phase = false;
     bool enable_coarse_filter_output_usage = true;
     bool use_linear_filter = true;
diff --git a/api/audio/echo_canceller3_config_json.cc b/api/audio/echo_canceller3_config_json.cc
index 8b26a2c..4768e36 100644
--- a/api/audio/echo_canceller3_config_json.cc
+++ b/api/audio/echo_canceller3_config_json.cc
@@ -230,6 +230,8 @@
               &cfg.filter.config_change_duration_blocks);
     ReadParam(section, "initial_state_seconds",
               &cfg.filter.initial_state_seconds);
+    ReadParam(section, "coarse_reset_hangover_blocks",
+              &cfg.filter.coarse_reset_hangover_blocks);
     ReadParam(section, "conservative_initial_phase",
               &cfg.filter.conservative_initial_phase);
     ReadParam(section, "enable_coarse_filter_output_usage",
@@ -509,6 +511,8 @@
       << config.filter.config_change_duration_blocks << ",";
   ost << "\"initial_state_seconds\": " << config.filter.initial_state_seconds
       << ",";
+  ost << "\"coarse_reset_hangover_blocks\": "
+      << config.filter.coarse_reset_hangover_blocks << ",";
   ost << "\"conservative_initial_phase\": "
       << (config.filter.conservative_initial_phase ? "true" : "false") << ",";
   ost << "\"enable_coarse_filter_output_usage\": "
diff --git a/api/jsep.h b/api/jsep.h
index cf8aeb0..dcf8213 100644
--- a/api/jsep.h
+++ b/api/jsep.h
@@ -136,6 +136,13 @@
 
   virtual ~SessionDescriptionInterface() {}
 
+  // Create a new SessionDescriptionInterface object
+  // with the same values as the old object.
+  // TODO(bugs.webrtc.org:12215): Remove default implementation
+  virtual std::unique_ptr<SessionDescriptionInterface> Clone() const {
+    return nullptr;
+  }
+
   // Only for use internally.
   virtual cricket::SessionDescription* description() = 0;
   virtual const cricket::SessionDescription* description() const = 0;
diff --git a/api/jsep_ice_candidate.h b/api/jsep_ice_candidate.h
index 4ee84cf..1a4247c 100644
--- a/api/jsep_ice_candidate.h
+++ b/api/jsep_ice_candidate.h
@@ -34,6 +34,8 @@
   JsepIceCandidate(const std::string& sdp_mid,
                    int sdp_mline_index,
                    const cricket::Candidate& candidate);
+  JsepIceCandidate(const JsepIceCandidate&) = delete;
+  JsepIceCandidate& operator=(const JsepIceCandidate&) = delete;
   ~JsepIceCandidate() override;
   // |err| may be null.
   bool Initialize(const std::string& sdp, SdpParseError* err);
@@ -53,8 +55,6 @@
   std::string sdp_mid_;
   int sdp_mline_index_;
   cricket::Candidate candidate_;
-
-  RTC_DISALLOW_COPY_AND_ASSIGN(JsepIceCandidate);
 };
 
 // Implementation of IceCandidateCollection which stores JsepIceCandidates.
@@ -64,6 +64,8 @@
   // Move constructor is defined so that a vector of JsepCandidateCollections
   // can be resized.
   JsepCandidateCollection(JsepCandidateCollection&& o);
+  // Returns a copy of the candidate collection.
+  JsepCandidateCollection Clone() const;
   size_t count() const override;
   bool HasCandidate(const IceCandidateInterface* candidate) const override;
   // Adds and takes ownership of the JsepIceCandidate.
diff --git a/api/jsep_session_description.h b/api/jsep_session_description.h
index 79e15e2..e13d85e 100644
--- a/api/jsep_session_description.h
+++ b/api/jsep_session_description.h
@@ -49,6 +49,8 @@
                   const std::string& session_id,
                   const std::string& session_version);
 
+  virtual std::unique_ptr<SessionDescriptionInterface> Clone() const;
+
   virtual cricket::SessionDescription* description() {
     return description_.get();
   }
diff --git a/api/media_stream_interface.h b/api/media_stream_interface.h
index bd4a2c0..8892ee5 100644
--- a/api/media_stream_interface.h
+++ b/api/media_stream_interface.h
@@ -216,6 +216,11 @@
                   number_of_frames);
   }
 
+  // Returns the number of channels encoded by the sink. This can be less than
+  // the number_of_channels if down-mixing occur. A value of -1 means an unknown
+  // number.
+  virtual int NumPreferredChannels() const { return -1; }
+
  protected:
   virtual ~AudioTrackSinkInterface() {}
 };
diff --git a/api/peer_connection_factory_proxy.h b/api/peer_connection_factory_proxy.h
index e33fb45..be098e3 100644
--- a/api/peer_connection_factory_proxy.h
+++ b/api/peer_connection_factory_proxy.h
@@ -36,6 +36,10 @@
               CreatePeerConnection,
               const PeerConnectionInterface::RTCConfiguration&,
               PeerConnectionDependencies)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>>,
+              CreatePeerConnectionOrError,
+              const PeerConnectionInterface::RTCConfiguration&,
+              PeerConnectionDependencies)
 PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
                    GetRtpSenderCapabilities,
                    cricket::MediaType)
diff --git a/api/peer_connection_interface.cc b/api/peer_connection_interface.cc
index f82e84b..e1d94dd 100644
--- a/api/peer_connection_interface.cc
+++ b/api/peer_connection_interface.cc
@@ -87,6 +87,13 @@
   return nullptr;
 }
 
+RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>>
+PeerConnectionFactoryInterface::CreatePeerConnectionOrError(
+    const PeerConnectionInterface::RTCConfiguration& configuration,
+    PeerConnectionDependencies dependencies) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR);
+}
+
 RtpCapabilities PeerConnectionFactoryInterface::GetRtpSenderCapabilities(
     cricket::MediaType kind) const {
   return {};
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
index 0e6cd5c..92d965b 100644
--- a/api/peer_connection_interface.h
+++ b/api/peer_connection_interface.h
@@ -1428,6 +1428,12 @@
   // configuration and a PeerConnectionDependencies structure.
   // TODO(benwright): Make pure virtual once downstream mock PC factory classes
   // are updated.
+  virtual RTCErrorOr<rtc::scoped_refptr<PeerConnectionInterface>>
+  CreatePeerConnectionOrError(
+      const PeerConnectionInterface::RTCConfiguration& configuration,
+      PeerConnectionDependencies dependencies);
+  // Deprecated creator - does not return an error code on error.
+  // TODO(bugs.webrtc.org:12238): Deprecate and remove.
   virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
       const PeerConnectionInterface::RTCConfiguration& configuration,
       PeerConnectionDependencies dependencies);
diff --git a/api/rtc_error.h b/api/rtc_error.h
index d24737c..7cfd89a 100644
--- a/api/rtc_error.h
+++ b/api/rtc_error.h
@@ -11,9 +11,9 @@
 #ifndef API_RTC_ERROR_H_
 #define API_RTC_ERROR_H_
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 #include <string>
 #include <utility>  // For std::move.
 
@@ -161,7 +161,7 @@
 RTC_EXPORT const char* ToString(RTCErrorType error);
 RTC_EXPORT const char* ToString(RTCErrorDetailType error);
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
     RTCErrorType error) {
@@ -173,7 +173,7 @@
     RTCErrorDetailType error) {
   return stream << ToString(error);
 }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
 // Helper macro that can be used by implementations to create an error with a
 // message and log it. |message| should be a string literal or movable
diff --git a/api/rtp_parameters.h b/api/rtp_parameters.h
index 369d277..df0e7a9 100644
--- a/api/rtp_parameters.h
+++ b/api/rtp_parameters.h
@@ -465,6 +465,9 @@
   // For video, scale the resolution down by this factor.
   absl::optional<double> scale_resolution_down_by;
 
+  // https://w3c.github.io/webrtc-svc/#rtcrtpencodingparameters
+  absl::optional<std::string> scalability_mode;
+
   // For an RtpSender, set to true to cause this encoding to be encoded and
   // sent, and false for it not to be encoded and sent. This allows control
   // across multiple encodings of a sender for turning simulcast layers on and
diff --git a/api/rtp_transceiver_interface.cc b/api/rtp_transceiver_interface.cc
index 1dc0fcc..fd5085c 100644
--- a/api/rtp_transceiver_interface.cc
+++ b/api/rtp_transceiver_interface.cc
@@ -64,6 +64,11 @@
   return webrtc::RTCError(webrtc::RTCErrorType::UNSUPPORTED_OPERATION);
 }
 
+std::vector<RtpHeaderExtensionCapability>
+RtpTransceiverInterface::HeaderExtensionsNegotiated() const {
+  return {};
+}
+
 // TODO(bugs.webrtc.org/11839) Remove default implementations when clients
 // are updated.
 void RtpTransceiverInterface::SetDirection(
diff --git a/api/rtp_transceiver_interface.h b/api/rtp_transceiver_interface.h
index fd3555f..9b46846 100644
--- a/api/rtp_transceiver_interface.h
+++ b/api/rtp_transceiver_interface.h
@@ -156,6 +156,12 @@
   virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsToOffer()
       const;
 
+  // Readonly attribute which is either empty if negotation has not yet
+  // happened, or a vector of the negotiated header extensions.
+  // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface
+  virtual std::vector<RtpHeaderExtensionCapability> HeaderExtensionsNegotiated()
+      const;
+
   // The SetOfferedRtpHeaderExtensions method modifies the next SDP negotiation
   // so that it negotiates use of header extensions which are not kStopped.
   // https://w3c.github.io/webrtc-extensions/#rtcrtptransceiver-interface
diff --git a/api/transport/stun.cc b/api/transport/stun.cc
index 7fee6ea..e1bf03b 100644
--- a/api/transport/stun.cc
+++ b/api/transport/stun.cc
@@ -11,8 +11,9 @@
 #include "api/transport/stun.h"
 
 #include <string.h>
-
 #include <algorithm>
+#include <cstdint>
+#include <iterator>
 #include <memory>
 #include <utility>
 
@@ -25,8 +26,15 @@
 using rtc::ByteBufferReader;
 using rtc::ByteBufferWriter;
 
+namespace cricket {
+
 namespace {
 
+const int k127Utf8CharactersLengthInBytes = 508;
+const int kDefaultMaxAttributeLength = 508;
+const int kMessageIntegrityAttributeLength = 20;
+const int kTheoreticalMaximumAttributeLength = 65535;
+
 uint32_t ReduceTransactionId(const std::string& transaction_id) {
   RTC_DCHECK(transaction_id.length() == cricket::kStunTransactionIdLength ||
              transaction_id.length() ==
@@ -40,9 +48,46 @@
   return result;
 }
 
-}  // namespace
+// Check the maximum length of a BYTE_STRING attribute against specifications.
+bool LengthValid(int type, int length) {
+  // "Less than 509 bytes" is intended to indicate a maximum of 127
+  // UTF-8 characters, which may take up to 4 bytes per character.
+  switch (type) {
+    case STUN_ATTR_USERNAME:
+      return length <=
+             k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.3
+    case STUN_ATTR_MESSAGE_INTEGRITY:
+      return length ==
+             kMessageIntegrityAttributeLength;  // RFC 8489 section 14.5
+    case STUN_ATTR_REALM:
+      return length <=
+             k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.9
+    case STUN_ATTR_NONCE:
+      return length <=
+             k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.10
+    case STUN_ATTR_SOFTWARE:
+      return length <=
+             k127Utf8CharactersLengthInBytes;  // RFC 8489 section 14.14
+    case STUN_ATTR_ORIGIN:
+      // 0x802F is unassigned by IANA.
+      // RESPONSE-ORIGIN is defined in RFC 5780 section 7.3, but does not
+      // specify a maximum length. It's an URL, so return an arbitrary
+      // restriction.
+      return length <= kDefaultMaxAttributeLength;
+    case STUN_ATTR_DATA:
+      // No length restriction in RFC; it's the content of an UDP datagram,
+      // which in theory can be up to 65.535 bytes.
+      // TODO(bugs.webrtc.org/12179): Write a test to find the real limit.
+      return length <= kTheoreticalMaximumAttributeLength;
+    default:
+      // Return an arbitrary restriction for all other types.
+      return length <= kTheoreticalMaximumAttributeLength;
+  }
+  RTC_NOTREACHED();
+  return true;
+}
 
-namespace cricket {
+}  // namespace
 
 const char STUN_ERROR_REASON_TRY_ALTERNATE_SERVER[] = "Try Alternate Server";
 const char STUN_ERROR_REASON_BAD_REQUEST[] = "Bad Request";
@@ -993,6 +1038,10 @@
 }
 
 bool StunByteStringAttribute::Write(ByteBufferWriter* buf) const {
+  // Check that length is legal according to specs
+  if (!LengthValid(type(), length())) {
+    return false;
+  }
   buf->WriteBytes(bytes_, length());
   WritePadding(buf);
   return true;
diff --git a/api/transport/stun.h b/api/transport/stun.h
index db37b8e..8893b2a 100644
--- a/api/transport/stun.h
+++ b/api/transport/stun.h
@@ -16,11 +16,13 @@
 
 #include <stddef.h>
 #include <stdint.h>
-
+#include <functional>
 #include <memory>
 #include <string>
 #include <vector>
 
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
 #include "rtc_base/byte_buffer.h"
 #include "rtc_base/ip_address.h"
 #include "rtc_base/socket_address.h"
@@ -133,7 +135,6 @@
 class StunAttribute;
 class StunByteStringAttribute;
 class StunErrorCodeAttribute;
-
 class StunUInt16ListAttribute;
 class StunUInt32Attribute;
 class StunUInt64Attribute;
diff --git a/api/transport/stun_unittest.cc b/api/transport/stun_unittest.cc
index 0884b2c..bf2717e 100644
--- a/api/transport/stun_unittest.cc
+++ b/api/transport/stun_unittest.cc
@@ -1903,4 +1903,16 @@
       sizeof(kRfc5769SampleRequest)));
 }
 
+TEST_F(StunTest, SizeRestrictionOnAttributes) {
+  StunMessage msg;
+  msg.SetType(STUN_BINDING_REQUEST);
+  msg.SetTransactionID("ABCDEFGH");
+  auto long_username = StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
+  std::string long_string(509, 'x');
+  long_username->CopyBytes(long_string.c_str(), long_string.size());
+  msg.AddAttribute(std::move(long_username));
+  rtc::ByteBufferWriter out;
+  ASSERT_FALSE(msg.Write(&out));
+}
+
 }  // namespace cricket
diff --git a/api/units/data_rate.h b/api/units/data_rate.h
index 5c8a61f..9857212 100644
--- a/api/units/data_rate.h
+++ b/api/units/data_rate.h
@@ -11,9 +11,9 @@
 #ifndef API_UNITS_DATA_RATE_H_
 #define API_UNITS_DATA_RATE_H_
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
-#endif              // UNIT_TEST
+#endif              // WEBRTC_UNIT_TEST
 
 #include <limits>
 #include <string>
@@ -142,13 +142,13 @@
   return ToString(value);
 }
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
     DataRate value) {
   return stream << ToString(value);
 }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
 }  // namespace webrtc
 
diff --git a/api/units/data_size.h b/api/units/data_size.h
index 27a2a4e..6817e24 100644
--- a/api/units/data_size.h
+++ b/api/units/data_size.h
@@ -11,9 +11,9 @@
 #ifndef API_UNITS_DATA_SIZE_H_
 #define API_UNITS_DATA_SIZE_H_
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
-#endif              // UNIT_TEST
+#endif              // WEBRTC_UNIT_TEST
 
 #include <string>
 #include <type_traits>
@@ -53,13 +53,13 @@
   return ToString(value);
 }
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
     DataSize value) {
   return stream << ToString(value);
 }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
 }  // namespace webrtc
 
diff --git a/api/units/frequency.h b/api/units/frequency.h
index 88912c6..8e9cc2b 100644
--- a/api/units/frequency.h
+++ b/api/units/frequency.h
@@ -10,9 +10,9 @@
 #ifndef API_UNITS_FREQUENCY_H_
 #define API_UNITS_FREQUENCY_H_
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
-#endif              // UNIT_TEST
+#endif              // WEBRTC_UNIT_TEST
 
 #include <cstdlib>
 #include <limits>
@@ -89,13 +89,13 @@
   return ToString(value);
 }
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
     Frequency value) {
   return stream << ToString(value);
 }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
 }  // namespace webrtc
 #endif  // API_UNITS_FREQUENCY_H_
diff --git a/api/units/time_delta.h b/api/units/time_delta.h
index 173affc..6f19103 100644
--- a/api/units/time_delta.h
+++ b/api/units/time_delta.h
@@ -11,9 +11,9 @@
 #ifndef API_UNITS_TIME_DELTA_H_
 #define API_UNITS_TIME_DELTA_H_
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
-#endif              // UNIT_TEST
+#endif              // WEBRTC_UNIT_TEST
 
 #include <cstdlib>
 #include <string>
@@ -92,13 +92,13 @@
   return ToString(value);
 }
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
     TimeDelta value) {
   return stream << ToString(value);
 }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
 }  // namespace webrtc
 
diff --git a/api/units/timestamp.h b/api/units/timestamp.h
index f83477e..1e9f9d1 100644
--- a/api/units/timestamp.h
+++ b/api/units/timestamp.h
@@ -11,9 +11,9 @@
 #ifndef API_UNITS_TIMESTAMP_H_
 #define API_UNITS_TIMESTAMP_H_
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
-#endif              // UNIT_TEST
+#endif              // WEBRTC_UNIT_TEST
 
 #include <string>
 #include <type_traits>
@@ -125,13 +125,13 @@
   return ToString(value);
 }
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
     std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
     Timestamp value) {
   return stream << ToString(value);
 }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
 }  // namespace webrtc
 
diff --git a/api/video/encoded_frame.h b/api/video/encoded_frame.h
index f0a67a1..6a2b1f8 100644
--- a/api/video/encoded_frame.h
+++ b/api/video/encoded_frame.h
@@ -79,7 +79,6 @@
   // many |references|.
   size_t num_references = 0;
   int64_t references[kMaxFrameReferences];
-  bool inter_layer_predicted = false;
   // Is this subframe the last one in the superframe (In RTP stream that would
   // mean that the last packet has a marker bit set).
   bool is_last_spatial_layer = true;
diff --git a/api/video/video_stream_encoder_create.cc b/api/video/video_stream_encoder_create.cc
deleted file mode 100644
index 3a2ebe7..0000000
--- a/api/video/video_stream_encoder_create.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "api/video/video_stream_encoder_create.h"
-
-#include <memory>
-
-#include "video/adaptation/overuse_frame_detector.h"
-#include "video/video_stream_encoder.h"
-
-namespace webrtc {
-
-std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
-    Clock* clock,
-    TaskQueueFactory* task_queue_factory,
-    uint32_t number_of_cores,
-    VideoStreamEncoderObserver* encoder_stats_observer,
-    const VideoStreamEncoderSettings& settings) {
-  return std::make_unique<VideoStreamEncoder>(
-      clock, number_of_cores, encoder_stats_observer, settings,
-      std::make_unique<OveruseFrameDetector>(encoder_stats_observer),
-      task_queue_factory);
-}
-
-}  // namespace webrtc
diff --git a/api/video/video_stream_encoder_create.h b/api/video/video_stream_encoder_create.h
deleted file mode 100644
index 3946b95..0000000
--- a/api/video/video_stream_encoder_create.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
-#define API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
-
-#include <stdint.h>
-
-#include <memory>
-
-#include "api/task_queue/task_queue_factory.h"
-#include "api/video/video_frame.h"
-#include "api/video/video_sink_interface.h"
-#include "api/video/video_stream_encoder_interface.h"
-#include "api/video/video_stream_encoder_observer.h"
-#include "api/video/video_stream_encoder_settings.h"
-
-namespace webrtc {
-// TODO(srte): Find a way to avoid this forward declaration.
-class Clock;
-
-std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
-    Clock* clock,
-    TaskQueueFactory* task_queue_factory,
-    uint32_t number_of_cores,
-    VideoStreamEncoderObserver* encoder_stats_observer,
-    const VideoStreamEncoderSettings& settings);
-}  // namespace webrtc
-
-#endif  // API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
diff --git a/api/video/video_stream_encoder_settings.h b/api/video/video_stream_encoder_settings.h
index cbeed3d..743524b 100644
--- a/api/video/video_stream_encoder_settings.h
+++ b/api/video/video_stream_encoder_settings.h
@@ -39,12 +39,6 @@
 };
 
 struct VideoStreamEncoderSettings {
-  enum class BitrateAllocationCallbackType {
-    kVideoBitrateAllocation,
-    kVideoBitrateAllocationWhenScreenSharing,
-    kVideoLayersAllocation
-  };
-
   explicit VideoStreamEncoderSettings(
       const VideoEncoder::Capabilities& capabilities)
       : capabilities(capabilities) {}
@@ -65,11 +59,6 @@
   // Negotiated capabilities which the VideoEncoder may expect the other
   // side to use.
   VideoEncoder::Capabilities capabilities;
-
-  // TODO(bugs.webrtc.org/12000): Reporting of VideoBitrateAllocation is beeing
-  // deprecated. Instead VideoLayersAllocation should be reported.
-  BitrateAllocationCallbackType allocation_cb_type =
-      BitrateAllocationCallbackType::kVideoBitrateAllocationWhenScreenSharing;
 };
 
 }  // namespace webrtc
diff --git a/audio/BUILD.gn b/audio/BUILD.gn
index bc61c31..6901e33 100644
--- a/audio/BUILD.gn
+++ b/audio/BUILD.gn
@@ -80,7 +80,6 @@
     "../modules/audio_processing:audio_frame_proxies",
     "../modules/audio_processing:rms_level",
     "../modules/pacing",
-    "../modules/remote_bitrate_estimator",
     "../modules/rtp_rtcp",
     "../modules/rtp_rtcp:rtp_rtcp_format",
     "../modules/utility",
@@ -94,6 +93,7 @@
     "../rtc_base/experiments:field_trial_parser",
     "../rtc_base/synchronization:mutex",
     "../rtc_base/synchronization:sequence_checker",
+    "../rtc_base/system:no_unique_address",
     "../rtc_base/task_utils:to_queued_task",
     "../system_wrappers",
     "../system_wrappers:field_trial",
diff --git a/audio/DEPS b/audio/DEPS
index 16f8194..9b89dc3 100644
--- a/audio/DEPS
+++ b/audio/DEPS
@@ -11,7 +11,6 @@
   "+modules/bitrate_controller",
   "+modules/congestion_controller",
   "+modules/pacing",
-  "+modules/remote_bitrate_estimator",
   "+modules/rtp_rtcp",
   "+modules/utility",
   "+system_wrappers",
diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc
index f0f150a..fcd691e 100644
--- a/audio/audio_receive_stream_unittest.cc
+++ b/audio/audio_receive_stream_unittest.cc
@@ -36,6 +36,7 @@
 
 using ::testing::_;
 using ::testing::FloatEq;
+using ::testing::NiceMock;
 using ::testing::Return;
 
 AudioDecodingCallStats MakeAudioDecodeStatsForTest() {
@@ -86,7 +87,7 @@
     config.audio_processing =
         use_null_audio_processing
             ? nullptr
-            : new rtc::RefCountedObject<MockAudioProcessing>();
+            : new rtc::RefCountedObject<NiceMock<MockAudioProcessing>>();
     config.audio_device_module =
         new rtc::RefCountedObject<testing::NiceMock<MockAudioDeviceModule>>();
     audio_state_ = AudioState::Create(config);
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index 1c0a32f..4e21b1f 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -143,7 +143,6 @@
     std::unique_ptr<voe::ChannelSendInterface> channel_send)
     : clock_(clock),
       worker_queue_(rtp_transport->GetWorkerQueue()),
-      audio_send_side_bwe_(field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")),
       allocate_audio_without_feedback_(
           field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC")),
       enable_audio_alr_probing_(
@@ -289,7 +288,7 @@
 
     RtcpBandwidthObserver* bandwidth_observer = nullptr;
 
-    if (audio_send_side_bwe_ && !allocate_audio_without_feedback_ &&
+    if (!allocate_audio_without_feedback_ &&
         new_ids.transport_sequence_number != 0) {
       rtp_rtcp_module_->RegisterRtpHeaderExtension(
           TransportSequenceNumber::kUri, new_ids.transport_sequence_number);
@@ -809,8 +808,7 @@
   if (config_.min_bitrate_bps == new_config.min_bitrate_bps &&
       config_.max_bitrate_bps == new_config.max_bitrate_bps &&
       config_.bitrate_priority == new_config.bitrate_priority &&
-      (TransportSeqNumId(config_) == TransportSeqNumId(new_config) ||
-       !audio_send_side_bwe_) &&
+      TransportSeqNumId(config_) == TransportSeqNumId(new_config) &&
       config_.audio_network_adaptor_config ==
           new_config.audio_network_adaptor_config) {
     return;
diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h
index 12fcb9f..1e6982e 100644
--- a/audio/audio_send_stream.h
+++ b/audio/audio_send_stream.h
@@ -155,7 +155,6 @@
   rtc::RaceChecker audio_capture_race_checker_;
   rtc::TaskQueue* worker_queue_;
 
-  const bool audio_send_side_bwe_;
   const bool allocate_audio_without_feedback_;
   const bool force_no_audio_feedback_ = allocate_audio_without_feedback_;
   const bool enable_audio_alr_probing_;
diff --git a/audio/audio_send_stream_tests.cc b/audio/audio_send_stream_tests.cc
index d2ea99c..e389503 100644
--- a/audio/audio_send_stream_tests.cc
+++ b/audio/audio_send_stream_tests.cc
@@ -188,17 +188,10 @@
 };
 
 TEST_F(AudioSendStreamCallTest, SendsTransportWideSequenceNumbersInFieldTrial) {
-  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   TransportWideSequenceNumberObserver test(/*expect_sequence_number=*/true);
   RunBaseTest(&test);
 }
 
-TEST_F(AudioSendStreamCallTest,
-       DoesNotSendTransportWideSequenceNumbersPerDefault) {
-  TransportWideSequenceNumberObserver test(/*expect_sequence_number=*/false);
-  RunBaseTest(&test);
-}
-
 TEST_F(AudioSendStreamCallTest, SendDtmf) {
   static const uint8_t kDtmfPayloadType = 120;
   static const int kDtmfPayloadFrequency = 8000;
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index bfec59b..f76a8fa 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -48,6 +48,7 @@
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::Ne;
+using ::testing::NiceMock;
 using ::testing::Return;
 using ::testing::StrEq;
 
@@ -153,7 +154,7 @@
         audio_processing_(
             use_null_audio_processing
                 ? nullptr
-                : new rtc::RefCountedObject<MockAudioProcessing>()),
+                : new rtc::RefCountedObject<NiceMock<MockAudioProcessing>>()),
         bitrate_allocator_(&limit_observer_),
         worker_queue_(task_queue_factory_->CreateTaskQueue(
             "ConfigHelper_worker_queue",
@@ -421,7 +422,6 @@
 }
 
 TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
-  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   for (bool use_null_audio_processing : {false, true}) {
     ConfigHelper helper(true, true, use_null_audio_processing);
     auto send_stream = helper.CreateAudioSendStream();
@@ -523,14 +523,12 @@
 
 TEST(AudioSendStreamTest, SendCodecAppliesAudioNetworkAdaptor) {
   for (bool use_null_audio_processing : {false, true}) {
-    ConfigHelper helper(false, true, use_null_audio_processing);
+    ConfigHelper helper(true, true, use_null_audio_processing);
     helper.config().send_codec_spec =
         AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
     const std::string kAnaConfigString = "abcde";
     const std::string kAnaReconfigString = "12345";
 
-    helper.config().rtp.extensions.push_back(RtpExtension(
-        RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
     helper.config().audio_network_adaptor_config = kAnaConfigString;
 
     EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
@@ -559,12 +557,10 @@
 
 TEST(AudioSendStreamTest, AudioNetworkAdaptorReceivesOverhead) {
   for (bool use_null_audio_processing : {false, true}) {
-    ConfigHelper helper(false, true, use_null_audio_processing);
+    ConfigHelper helper(true, true, use_null_audio_processing);
     helper.config().send_codec_spec =
         AudioSendStream::Config::SendCodecSpec(0, kOpusFormat);
     const std::string kAnaConfigString = "abcde";
-    helper.config().rtp.extensions.push_back(RtpExtension(
-        RtpExtension::kTransportSequenceNumberUri, kTransportSequenceNumberId));
 
     EXPECT_CALL(helper.mock_encoder_factory(), MakeAudioEncoderMock(_, _, _, _))
         .WillOnce(Invoke(
@@ -647,7 +643,6 @@
 }
 
 TEST(AudioSendStreamTest, SSBweTargetInRangeRespected) {
-  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   for (bool use_null_audio_processing : {false, true}) {
     ConfigHelper helper(true, true, use_null_audio_processing);
     auto send_stream = helper.CreateAudioSendStream();
@@ -666,7 +661,6 @@
 
 TEST(AudioSendStreamTest, SSBweFieldTrialMinRespected) {
   ScopedFieldTrials field_trials(
-      "WebRTC-Audio-SendSideBwe/Enabled/"
       "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
   for (bool use_null_audio_processing : {false, true}) {
     ConfigHelper helper(true, true, use_null_audio_processing);
@@ -684,7 +678,6 @@
 
 TEST(AudioSendStreamTest, SSBweFieldTrialMaxRespected) {
   ScopedFieldTrials field_trials(
-      "WebRTC-Audio-SendSideBwe/Enabled/"
       "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
   for (bool use_null_audio_processing : {false, true}) {
     ConfigHelper helper(true, true, use_null_audio_processing);
@@ -702,8 +695,6 @@
 
 TEST(AudioSendStreamTest, SSBweWithOverhead) {
   ScopedFieldTrials field_trials(
-      "WebRTC-Audio-SendSideBwe/Enabled/"
-      "WebRTC-SendSideBwe-WithOverhead/Enabled/"
       "WebRTC-Audio-LegacyOverhead/Disabled/");
   for (bool use_null_audio_processing : {false, true}) {
     ConfigHelper helper(true, true, use_null_audio_processing);
@@ -725,8 +716,6 @@
 
 TEST(AudioSendStreamTest, SSBweWithOverheadMinRespected) {
   ScopedFieldTrials field_trials(
-      "WebRTC-Audio-SendSideBwe/Enabled/"
-      "WebRTC-SendSideBwe-WithOverhead/Enabled/"
       "WebRTC-Audio-LegacyOverhead/Disabled/"
       "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
   for (bool use_null_audio_processing : {false, true}) {
@@ -747,8 +736,6 @@
 
 TEST(AudioSendStreamTest, SSBweWithOverheadMaxRespected) {
   ScopedFieldTrials field_trials(
-      "WebRTC-Audio-SendSideBwe/Enabled/"
-      "WebRTC-SendSideBwe-WithOverhead/Enabled/"
       "WebRTC-Audio-LegacyOverhead/Disabled/"
       "WebRTC-Audio-Allocation/min:6kbps,max:64kbps/");
   for (bool use_null_audio_processing : {false, true}) {
@@ -808,7 +795,6 @@
 }
 
 TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
-  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   for (bool use_null_audio_processing : {false, true}) {
     ConfigHelper helper(false, true, use_null_audio_processing);
     auto send_stream = helper.CreateAudioSendStream();
diff --git a/audio/channel_receive_frame_transformer_delegate.h b/audio/channel_receive_frame_transformer_delegate.h
index 73112d1..3227c55 100644
--- a/audio/channel_receive_frame_transformer_delegate.h
+++ b/audio/channel_receive_frame_transformer_delegate.h
@@ -15,6 +15,7 @@
 
 #include "api/frame_transformer_interface.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/thread.h"
 
@@ -61,7 +62,7 @@
   ~ChannelReceiveFrameTransformerDelegate() override = default;
 
  private:
-  SequenceChecker sequence_checker_;
+  RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
   ReceiveFrameCallback receive_frame_callback_
       RTC_GUARDED_BY(sequence_checker_);
   rtc::scoped_refptr<FrameTransformerInterface> frame_transformer_
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
index 80e7ab2..d331f01 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -241,6 +241,8 @@
   // Defined last to ensure that there are no running tasks when the other
   // members are destroyed.
   rtc::TaskQueue encoder_queue_;
+
+  const bool fixing_timestamp_stall_;
 };
 
 const int kTelephoneEventAttenuationdB = 10;
@@ -471,7 +473,9 @@
       crypto_options_(crypto_options),
       encoder_queue_(task_queue_factory->CreateTaskQueue(
           "AudioEncoder",
-          TaskQueueFactory::Priority::NORMAL)) {
+          TaskQueueFactory::Priority::NORMAL)),
+      fixing_timestamp_stall_(
+          !field_trial::IsDisabled("WebRTC-Audio-FixTimestampStall")) {
   RTC_DCHECK(module_process_thread);
   module_process_thread_checker_.Detach();
 
@@ -808,6 +812,10 @@
       [this, audio_frame = std::move(audio_frame)]() mutable {
         RTC_DCHECK_RUN_ON(&encoder_queue_);
         if (!encoder_queue_is_active_) {
+          if (fixing_timestamp_stall_) {
+            _timeStamp +=
+                static_cast<uint32_t>(audio_frame->samples_per_channel_);
+          }
           return;
         }
         // Measure time between when the audio frame is added to the task queue
diff --git a/audio/remix_resample.cc b/audio/remix_resample.cc
index 3694d34..178af62 100644
--- a/audio/remix_resample.cc
+++ b/audio/remix_resample.cc
@@ -56,9 +56,10 @@
 
   if (resampler->InitializeIfNeeded(sample_rate_hz, dst_frame->sample_rate_hz_,
                                     audio_ptr_num_channels) == -1) {
-    FATAL() << "InitializeIfNeeded failed: sample_rate_hz = " << sample_rate_hz
-            << ", dst_frame->sample_rate_hz_ = " << dst_frame->sample_rate_hz_
-            << ", audio_ptr_num_channels = " << audio_ptr_num_channels;
+    RTC_FATAL() << "InitializeIfNeeded failed: sample_rate_hz = "
+                << sample_rate_hz << ", dst_frame->sample_rate_hz_ = "
+                << dst_frame->sample_rate_hz_
+                << ", audio_ptr_num_channels = " << audio_ptr_num_channels;
   }
 
   // TODO(yujo): for muted input frames, don't resample. Either 1) allow
@@ -70,9 +71,10 @@
       resampler->Resample(audio_ptr, src_length, dst_frame->mutable_data(),
                           AudioFrame::kMaxDataSizeSamples);
   if (out_length == -1) {
-    FATAL() << "Resample failed: audio_ptr = " << audio_ptr
-            << ", src_length = " << src_length
-            << ", dst_frame->mutable_data() = " << dst_frame->mutable_data();
+    RTC_FATAL() << "Resample failed: audio_ptr = " << audio_ptr
+                << ", src_length = " << src_length
+                << ", dst_frame->mutable_data() = "
+                << dst_frame->mutable_data();
   }
   dst_frame->samples_per_channel_ = out_length / audio_ptr_num_channels;
 
diff --git a/audio/voip/BUILD.gn b/audio/voip/BUILD.gn
index 52f9d07..ed0508f 100644
--- a/audio/voip/BUILD.gn
+++ b/audio/voip/BUILD.gn
@@ -67,6 +67,7 @@
     "../../api:transport_api",
     "../../api/audio:audio_mixer_api",
     "../../api/audio_codecs:audio_codecs_api",
+    "../../api/voip:voip_api",
     "../../modules/audio_coding",
     "../../modules/rtp_rtcp",
     "../../modules/rtp_rtcp:rtp_rtcp_format",
@@ -78,6 +79,7 @@
     "../../rtc_base/synchronization:mutex",
     "../utility:audio_frame_operations",
   ]
+  absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
 
 rtc_library("audio_egress") {
@@ -98,6 +100,7 @@
     "../../rtc_base:thread_checker",
     "../../rtc_base:timeutils",
     "../../rtc_base/synchronization:mutex",
+    "../../rtc_base/system:no_unique_address",
     "../utility:audio_frame_operations",
   ]
 }
diff --git a/audio/voip/audio_channel.cc b/audio/voip/audio_channel.cc
index 926130d..d11e6d7 100644
--- a/audio/voip/audio_channel.cc
+++ b/audio/voip/audio_channel.cc
@@ -79,6 +79,12 @@
   }
 
   audio_mixer_->RemoveSource(ingress_.get());
+
+  // AudioEgress could hold current global TaskQueueBase that we need to clear
+  // before ProcessThread::DeRegisterModule.
+  egress_.reset();
+  ingress_.reset();
+
   process_thread_->DeRegisterModule(rtp_rtcp_.get());
 }
 
@@ -155,8 +161,21 @@
   ingress_stats.neteq_stats.interruption_count = stats.interruptionCount;
   ingress_stats.neteq_stats.total_interruption_duration_ms =
       stats.totalInterruptionDurationMs;
-  ingress_stats.total_duration = ingress_->GetTotalDuration();
+  ingress_stats.total_duration = ingress_->GetOutputTotalDuration();
   return ingress_stats;
 }
 
+ChannelStatistics AudioChannel::GetChannelStatistics() {
+  ChannelStatistics channel_stat = ingress_->GetChannelStatistics();
+
+  StreamDataCounters rtp_stats, rtx_stats;
+  rtp_rtcp_->GetSendStreamDataCounters(&rtp_stats, &rtx_stats);
+  channel_stat.bytes_sent =
+      rtp_stats.transmitted.payload_bytes + rtx_stats.transmitted.payload_bytes;
+  channel_stat.packets_sent =
+      rtp_stats.transmitted.packets + rtx_stats.transmitted.packets;
+
+  return channel_stat;
+}
+
 }  // namespace webrtc
diff --git a/audio/voip/audio_channel.h b/audio/voip/audio_channel.h
index a8946a7..7b9fa6f 100644
--- a/audio/voip/audio_channel.h
+++ b/audio/voip/audio_channel.h
@@ -70,6 +70,7 @@
   bool SendTelephoneEvent(int dtmf_event, int duration_ms) {
     return egress_->SendTelephoneEvent(dtmf_event, duration_ms);
   }
+  void SetMute(bool enable) { egress_->SetMute(enable); }
 
   // APIs relayed to AudioIngress.
   bool IsPlaying() const { return ingress_->IsPlaying(); }
@@ -83,6 +84,34 @@
     ingress_->SetReceiveCodecs(codecs);
   }
   IngressStatistics GetIngressStatistics();
+  ChannelStatistics GetChannelStatistics();
+
+  // See comments on the methods used from AudioEgress and AudioIngress.
+  // Conversion to double is following what is done in
+  // DoubleAudioLevelFromIntAudioLevel method in rtc_stats_collector.cc to be
+  // consistent.
+  double GetInputAudioLevel() const {
+    return egress_->GetInputAudioLevel() / 32767.0;
+  }
+  double GetInputTotalEnergy() const { return egress_->GetInputTotalEnergy(); }
+  double GetInputTotalDuration() const {
+    return egress_->GetInputTotalDuration();
+  }
+  double GetOutputAudioLevel() const {
+    return ingress_->GetOutputAudioLevel() / 32767.0;
+  }
+  double GetOutputTotalEnergy() const {
+    return ingress_->GetOutputTotalEnergy();
+  }
+  double GetOutputTotalDuration() const {
+    return ingress_->GetOutputTotalDuration();
+  }
+
+  // Internal API for testing purpose.
+  void SendRTCPReportForTesting(RTCPPacketType type) {
+    int32_t result = rtp_rtcp_->SendRTCP(type);
+    RTC_DCHECK(result == 0);
+  }
 
  private:
   // ChannelId that this audio channel belongs for logging purpose.
diff --git a/audio/voip/audio_egress.cc b/audio/voip/audio_egress.cc
index 90e069e..1162824 100644
--- a/audio/voip/audio_egress.cc
+++ b/audio/voip/audio_egress.cc
@@ -80,6 +80,12 @@
           return;
         }
 
+        double duration_seconds =
+            static_cast<double>(audio_frame->samples_per_channel_) /
+            audio_frame->sample_rate_hz_;
+
+        input_audio_level_.ComputeLevel(*audio_frame, duration_seconds);
+
         AudioFrameOperations::Mute(audio_frame.get(),
                                    encoder_context_.previously_muted_,
                                    encoder_context_.mute_);
diff --git a/audio/voip/audio_egress.h b/audio/voip/audio_egress.h
index 6b2d374..fcd9ed0 100644
--- a/audio/voip/audio_egress.h
+++ b/audio/voip/audio_egress.h
@@ -16,6 +16,7 @@
 
 #include "api/audio_codecs/audio_format.h"
 #include "api/task_queue/task_queue_factory.h"
+#include "audio/audio_level.h"
 #include "audio/utility/audio_frame_operations.h"
 #include "call/audio_sender.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
@@ -89,6 +90,16 @@
   // otherwise false when the dtmf queue reached maximum of 20 events.
   bool SendTelephoneEvent(int dtmf_event, int duration_ms);
 
+  // See comments on LevelFullRange, TotalEnergy, TotalDuration from
+  // audio/audio_level.h.
+  int GetInputAudioLevel() const { return input_audio_level_.LevelFullRange(); }
+  double GetInputTotalEnergy() const {
+    return input_audio_level_.TotalEnergy();
+  }
+  double GetInputTotalDuration() const {
+    return input_audio_level_.TotalDuration();
+  }
+
   // Implementation of AudioSender interface.
   void SendAudioData(std::unique_ptr<AudioFrame> audio_frame) override;
 
@@ -119,6 +130,9 @@
   // Synchronization is handled internally by AudioCodingModule.
   const std::unique_ptr<AudioCodingModule> audio_coding_;
 
+  // Synchronization is handled internally by voe::AudioLevel.
+  voe::AudioLevel input_audio_level_;
+
   // Struct that holds all variables used by encoder task queue.
   struct EncoderContext {
     // Offset used to mark rtp timestamp in sample rate unit in
diff --git a/audio/voip/audio_ingress.cc b/audio/voip/audio_ingress.cc
index 07def99..8aa552b 100644
--- a/audio/voip/audio_ingress.cc
+++ b/audio/voip/audio_ingress.cc
@@ -17,6 +17,10 @@
 #include "api/audio_codecs/audio_format.h"
 #include "audio/utility/audio_frame_operations.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_minmax.h"
 
@@ -153,6 +157,12 @@
     rtp_packet_received.set_payload_type_frequency(it->second);
   }
 
+  // Track current remote SSRC.
+  if (rtp_packet_received.Ssrc() != remote_ssrc_) {
+    rtp_rtcp_->SetRemoteSSRC(rtp_packet_received.Ssrc());
+    remote_ssrc_.store(rtp_packet_received.Ssrc());
+  }
+
   rtp_receive_statistics_->OnRtpPacket(rtp_packet_received);
 
   RTPHeader header;
@@ -181,11 +191,28 @@
 
 void AudioIngress::ReceivedRTCPPacket(
     rtc::ArrayView<const uint8_t> rtcp_packet) {
-  // Deliver RTCP packet to RTP/RTCP module for parsing.
+  rtcp::CommonHeader rtcp_header;
+  if (rtcp_header.Parse(rtcp_packet.data(), rtcp_packet.size()) &&
+      (rtcp_header.type() == rtcp::SenderReport::kPacketType ||
+       rtcp_header.type() == rtcp::ReceiverReport::kPacketType)) {
+    RTC_DCHECK_GE(rtcp_packet.size(), 8);
+
+    uint32_t sender_ssrc =
+        ByteReader<uint32_t>::ReadBigEndian(rtcp_packet.data() + 4);
+
+    // If we don't have remote ssrc at this point, it's likely that remote
+    // endpoint is receive-only or it could have restarted the media.
+    if (sender_ssrc != remote_ssrc_) {
+      rtp_rtcp_->SetRemoteSSRC(sender_ssrc);
+      remote_ssrc_.store(sender_ssrc);
+    }
+  }
+
+  // Deliver RTCP packet to RTP/RTCP module for parsing and processing.
   rtp_rtcp_->IncomingRtcpPacket(rtcp_packet.data(), rtcp_packet.size());
 
-  int64_t rtt = GetRoundTripTime();
-  if (rtt == -1) {
+  int64_t rtt = 0;
+  if (rtp_rtcp_->RTT(remote_ssrc_, &rtt, nullptr, nullptr, nullptr) != 0) {
     // Waiting for valid RTT.
     return;
   }
@@ -203,30 +230,65 @@
   }
 }
 
-int64_t AudioIngress::GetRoundTripTime() {
+ChannelStatistics AudioIngress::GetChannelStatistics() {
+  ChannelStatistics channel_stats;
+
+  // Get clockrate for current decoder ahead of jitter calculation.
+  uint32_t clockrate_hz = 0;
+  absl::optional<std::pair<int, SdpAudioFormat>> decoder =
+      acm_receiver_.LastDecoder();
+  if (decoder) {
+    clockrate_hz = decoder->second.clockrate_hz;
+  }
+
+  StreamStatistician* statistician =
+      rtp_receive_statistics_->GetStatistician(remote_ssrc_);
+  if (statistician) {
+    RtpReceiveStats stats = statistician->GetStats();
+    channel_stats.packets_lost = stats.packets_lost;
+    channel_stats.packets_received = stats.packet_counter.packets;
+    channel_stats.bytes_received = stats.packet_counter.payload_bytes;
+    channel_stats.remote_ssrc = remote_ssrc_;
+    if (clockrate_hz > 0) {
+      channel_stats.jitter = static_cast<double>(stats.jitter) / clockrate_hz;
+    }
+  }
+
+  // Get RTCP report using remote SSRC.
   const std::vector<ReportBlockData>& report_data =
       rtp_rtcp_->GetLatestReportBlockData();
+  for (const ReportBlockData& block_data : report_data) {
+    const RTCPReportBlock& rtcp_report = block_data.report_block();
+    if (rtp_rtcp_->SSRC() != rtcp_report.source_ssrc ||
+        remote_ssrc_ != rtcp_report.sender_ssrc) {
+      continue;
+    }
+    RemoteRtcpStatistics remote_stat;
+    remote_stat.packets_lost = rtcp_report.packets_lost;
+    remote_stat.fraction_lost =
+        static_cast<double>(rtcp_report.fraction_lost) / (1 << 8);
+    if (clockrate_hz > 0) {
+      remote_stat.jitter =
+          static_cast<double>(rtcp_report.jitter) / clockrate_hz;
+    }
+    if (block_data.has_rtt()) {
+      remote_stat.round_trip_time =
+          static_cast<double>(block_data.last_rtt_ms()) /
+          rtc::kNumMillisecsPerSec;
+    }
+    remote_stat.last_report_received_timestamp_ms =
+        block_data.report_block_timestamp_utc_us() /
+        rtc::kNumMicrosecsPerMillisec;
+    channel_stats.remote_rtcp = remote_stat;
 
-  // If we do not have report block which means remote RTCP hasn't be received
-  // yet, return -1 as to indicate uninitialized value.
-  if (report_data.empty()) {
-    return -1;
+    // Receive only channel won't send any RTP packets.
+    if (!channel_stats.remote_ssrc.has_value()) {
+      channel_stats.remote_ssrc = remote_ssrc_;
+    }
+    break;
   }
 
-  // We don't know in advance the remote SSRC used by the other end's receiver
-  // reports, so use the SSRC of the first report block as remote SSRC for now.
-  // TODO(natim@webrtc.org): handle the case where remote end is changing ssrc
-  // and update accordingly here.
-  const ReportBlockData& block_data = report_data[0];
-
-  const uint32_t sender_ssrc = block_data.report_block().sender_ssrc;
-
-  if (sender_ssrc != remote_ssrc_.load()) {
-    remote_ssrc_.store(sender_ssrc);
-    rtp_rtcp_->SetRemoteSSRC(sender_ssrc);
-  }
-
-  return (block_data.has_rtt() ? block_data.last_rtt_ms() : -1);
+  return channel_stats;
 }
 
 }  // namespace webrtc
diff --git a/audio/voip/audio_ingress.h b/audio/voip/audio_ingress.h
index acb84c0..9a36a46 100644
--- a/audio/voip/audio_ingress.h
+++ b/audio/voip/audio_ingress.h
@@ -17,10 +17,12 @@
 #include <memory>
 #include <utility>
 
+#include "absl/types/optional.h"
 #include "api/array_view.h"
 #include "api/audio/audio_mixer.h"
 #include "api/rtp_headers.h"
 #include "api/scoped_refptr.h"
+#include "api/voip/voip_statistics.h"
 #include "audio/audio_level.h"
 #include "modules/audio_coding/acm2/acm_receiver.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
@@ -68,23 +70,16 @@
   void ReceivedRTPPacket(rtc::ArrayView<const uint8_t> rtp_packet);
   void ReceivedRTCPPacket(rtc::ArrayView<const uint8_t> rtcp_packet);
 
-  // Retrieve highest speech output level in last 100 ms.  Note that
-  // this isn't RMS but absolute raw audio level on int16_t sample unit.
-  // Therefore, the return value will vary between 0 ~ 0xFFFF. This type of
-  // value may be useful to be used for measuring active speaker gauge.
-  int GetSpeechOutputLevelFullRange() const {
+  // See comments on LevelFullRange, TotalEnergy, TotalDuration from
+  // audio/audio_level.h.
+  int GetOutputAudioLevel() const {
     return output_audio_level_.LevelFullRange();
   }
-  // Retrieves the total duration for all samples played so far as explained in
-  // audio/AudioLevel.h.
-  double GetTotalDuration() const {
+  double GetOutputTotalEnergy() { return output_audio_level_.TotalEnergy(); }
+  double GetOutputTotalDuration() {
     return output_audio_level_.TotalDuration();
   }
 
-  // Returns network round trip time (RTT) measued by RTCP exchange with
-  // remote media endpoint. RTT value -1 indicates that it's not initialized.
-  int64_t GetRoundTripTime();
-
   NetworkStatistics GetNetworkStatistics() const {
     NetworkStatistics stats;
     acm_receiver_.GetNetworkStatistics(&stats,
@@ -92,6 +87,8 @@
     return stats;
   }
 
+  ChannelStatistics GetChannelStatistics();
+
   // Implementation of AudioMixer::Source interface.
   AudioMixer::Source::AudioFrameInfo GetAudioFrameWithInfo(
       int sampling_rate,
diff --git a/audio/voip/voip_core.cc b/audio/voip/voip_core.cc
index 92b80b5..33dadbc 100644
--- a/audio/voip/voip_core.cc
+++ b/audio/voip/voip_core.cc
@@ -127,10 +127,9 @@
   return true;
 }
 
-absl::optional<ChannelId> VoipCore::CreateChannel(
-    Transport* transport,
-    absl::optional<uint32_t> local_ssrc) {
-  absl::optional<ChannelId> channel_id;
+ChannelId VoipCore::CreateChannel(Transport* transport,
+                                  absl::optional<uint32_t> local_ssrc) {
+  ChannelId channel_id;
 
   // Set local ssrc to random if not set by caller.
   if (!local_ssrc) {
@@ -153,7 +152,7 @@
     start_process_thread = channels_.empty();
 
     channel_id = static_cast<ChannelId>(next_channel_id_);
-    channels_[*channel_id] = channel;
+    channels_[channel_id] = channel;
     next_channel_id_++;
     if (next_channel_id_ >= kMaxChannelId) {
       next_channel_id_ = 0;
@@ -161,7 +160,7 @@
   }
 
   // Set ChannelId in audio channel for logging/debugging purpose.
-  channel->SetId(*channel_id);
+  channel->SetId(channel_id);
 
   if (start_process_thread) {
     process_thread_->Start();
@@ -170,7 +169,7 @@
   return channel_id;
 }
 
-void VoipCore::ReleaseChannel(ChannelId channel_id) {
+VoipResult VoipCore::ReleaseChannel(ChannelId channel_id) {
   // Destroy channel outside of the lock.
   rtc::scoped_refptr<AudioChannel> channel;
 
@@ -188,8 +187,10 @@
     no_channels_after_release = channels_.empty();
   }
 
+  VoipResult status_code = VoipResult::kOk;
   if (!channel) {
     RTC_LOG(LS_WARNING) << "Channel " << channel_id << " not found";
+    status_code = VoipResult::kInvalidArgument;
   }
 
   if (no_channels_after_release) {
@@ -201,9 +202,12 @@
     if (audio_device_module_->Playing()) {
       if (audio_device_module_->StopPlayout() != 0) {
         RTC_LOG(LS_WARNING) << "StopPlayout failed";
+        status_code = VoipResult::kInternal;
       }
     }
   }
+
+  return status_code;
 }
 
 rtc::scoped_refptr<AudioChannel> VoipCore::GetChannel(ChannelId channel_id) {
@@ -281,143 +285,232 @@
   return true;
 }
 
-bool VoipCore::StartSend(ChannelId channel_id) {
-  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
-
-  if (!channel || !channel->StartSend()) {
-    return false;
-  }
-
-  return UpdateAudioTransportWithSenders();
-}
-
-bool VoipCore::StopSend(ChannelId channel_id) {
+VoipResult VoipCore::StartSend(ChannelId channel_id) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
   if (!channel) {
-    return false;
+    return VoipResult::kInvalidArgument;
+  }
+
+  if (!channel->StartSend()) {
+    return VoipResult::kFailedPrecondition;
+  }
+
+  return UpdateAudioTransportWithSenders() ? VoipResult::kOk
+                                           : VoipResult::kInternal;
+}
+
+VoipResult VoipCore::StopSend(ChannelId channel_id) {
+  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
+
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
 
   channel->StopSend();
 
-  return UpdateAudioTransportWithSenders();
+  return UpdateAudioTransportWithSenders() ? VoipResult::kOk
+                                           : VoipResult::kInternal;
 }
 
-bool VoipCore::StartPlayout(ChannelId channel_id) {
+VoipResult VoipCore::StartPlayout(ChannelId channel_id) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
   if (!channel) {
-    return false;
+    return VoipResult::kInvalidArgument;
   }
 
   if (channel->IsPlaying()) {
-    return true;
+    return VoipResult::kOk;
   }
 
   if (!channel->StartPlay()) {
-    return false;
+    return VoipResult::kFailedPrecondition;
   }
 
   // Initialize audio device module and default device if needed.
   if (!InitializeIfNeeded()) {
-    return false;
+    return VoipResult::kInternal;
   }
 
   if (!audio_device_module_->Playing()) {
     if (audio_device_module_->InitPlayout() != 0) {
       RTC_LOG(LS_ERROR) << "InitPlayout failed";
-      return false;
+      return VoipResult::kInternal;
     }
     if (audio_device_module_->StartPlayout() != 0) {
       RTC_LOG(LS_ERROR) << "StartPlayout failed";
-      return false;
+      return VoipResult::kInternal;
     }
   }
-  return true;
+
+  return VoipResult::kOk;
 }
 
-bool VoipCore::StopPlayout(ChannelId channel_id) {
+VoipResult VoipCore::StopPlayout(ChannelId channel_id) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
   if (!channel) {
-    return false;
+    return VoipResult::kInvalidArgument;
   }
 
   channel->StopPlay();
 
-  return true;
+  return VoipResult::kOk;
 }
 
-void VoipCore::ReceivedRTPPacket(ChannelId channel_id,
-                                 rtc::ArrayView<const uint8_t> rtp_packet) {
+VoipResult VoipCore::ReceivedRTPPacket(
+    ChannelId channel_id,
+    rtc::ArrayView<const uint8_t> rtp_packet) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    channel->ReceivedRTPPacket(rtp_packet);
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
+
+  channel->ReceivedRTPPacket(rtp_packet);
+
+  return VoipResult::kOk;
 }
 
-void VoipCore::ReceivedRTCPPacket(ChannelId channel_id,
-                                  rtc::ArrayView<const uint8_t> rtcp_packet) {
+VoipResult VoipCore::ReceivedRTCPPacket(
+    ChannelId channel_id,
+    rtc::ArrayView<const uint8_t> rtcp_packet) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    channel->ReceivedRTCPPacket(rtcp_packet);
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
+
+  channel->ReceivedRTCPPacket(rtcp_packet);
+
+  return VoipResult::kOk;
 }
 
-void VoipCore::SetSendCodec(ChannelId channel_id,
-                            int payload_type,
-                            const SdpAudioFormat& encoder_format) {
+VoipResult VoipCore::SetSendCodec(ChannelId channel_id,
+                                  int payload_type,
+                                  const SdpAudioFormat& encoder_format) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    auto encoder = encoder_factory_->MakeAudioEncoder(
-        payload_type, encoder_format, absl::nullopt);
-    channel->SetEncoder(payload_type, encoder_format, std::move(encoder));
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
+
+  auto encoder = encoder_factory_->MakeAudioEncoder(
+      payload_type, encoder_format, absl::nullopt);
+  channel->SetEncoder(payload_type, encoder_format, std::move(encoder));
+
+  return VoipResult::kOk;
 }
 
-void VoipCore::SetReceiveCodecs(
+VoipResult VoipCore::SetReceiveCodecs(
     ChannelId channel_id,
     const std::map<int, SdpAudioFormat>& decoder_specs) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    channel->SetReceiveCodecs(decoder_specs);
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
+
+  channel->SetReceiveCodecs(decoder_specs);
+
+  return VoipResult::kOk;
 }
 
-void VoipCore::RegisterTelephoneEventType(ChannelId channel_id,
-                                          int rtp_payload_type,
-                                          int sample_rate_hz) {
+VoipResult VoipCore::RegisterTelephoneEventType(ChannelId channel_id,
+                                                int rtp_payload_type,
+                                                int sample_rate_hz) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    channel->RegisterTelephoneEventType(rtp_payload_type, sample_rate_hz);
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
+
+  channel->RegisterTelephoneEventType(rtp_payload_type, sample_rate_hz);
+
+  return VoipResult::kOk;
 }
 
-bool VoipCore::SendDtmfEvent(ChannelId channel_id,
-                             DtmfEvent dtmf_event,
-                             int duration_ms) {
+VoipResult VoipCore::SendDtmfEvent(ChannelId channel_id,
+                                   DtmfEvent dtmf_event,
+                                   int duration_ms) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    return channel->SendTelephoneEvent(static_cast<int>(dtmf_event),
-                                       duration_ms);
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
-  return false;
+
+  return (channel->SendTelephoneEvent(static_cast<int>(dtmf_event), duration_ms)
+              ? VoipResult::kOk
+              : VoipResult::kFailedPrecondition);
 }
 
-absl::optional<IngressStatistics> VoipCore::GetIngressStatistics(
-    ChannelId channel_id) {
+VoipResult VoipCore::GetIngressStatistics(ChannelId channel_id,
+                                          IngressStatistics& ingress_stats) {
   rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
 
-  if (channel) {
-    return channel->GetIngressStatistics();
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
   }
-  return absl::nullopt;
+
+  ingress_stats = channel->GetIngressStatistics();
+
+  return VoipResult::kOk;
+}
+
+VoipResult VoipCore::GetChannelStatistics(ChannelId channel_id,
+                                          ChannelStatistics& channel_stats) {
+  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
+
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
+  }
+
+  channel_stats = channel->GetChannelStatistics();
+
+  return VoipResult::kOk;
+}
+
+VoipResult VoipCore::SetInputMuted(ChannelId channel_id, bool enable) {
+  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
+
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
+  }
+
+  channel->SetMute(enable);
+
+  return VoipResult::kOk;
+}
+
+VoipResult VoipCore::GetInputVolumeInfo(ChannelId channel_id,
+                                        VolumeInfo& input_volume) {
+  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
+
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
+  }
+
+  input_volume.audio_level = channel->GetInputAudioLevel();
+  input_volume.total_energy = channel->GetInputTotalEnergy();
+  input_volume.total_duration = channel->GetInputTotalDuration();
+
+  return VoipResult::kOk;
+}
+
+VoipResult VoipCore::GetOutputVolumeInfo(ChannelId channel_id,
+                                         VolumeInfo& output_volume) {
+  rtc::scoped_refptr<AudioChannel> channel = GetChannel(channel_id);
+
+  if (!channel) {
+    return VoipResult::kInvalidArgument;
+  }
+
+  output_volume.audio_level = channel->GetOutputAudioLevel();
+  output_volume.total_energy = channel->GetOutputTotalEnergy();
+  output_volume.total_duration = channel->GetOutputTotalDuration();
+
+  return VoipResult::kOk;
 }
 
 }  // namespace webrtc
diff --git a/audio/voip/voip_core.h b/audio/voip/voip_core.h
index 4279f77..b7c1f29 100644
--- a/audio/voip/voip_core.h
+++ b/audio/voip/voip_core.h
@@ -27,6 +27,7 @@
 #include "api/voip/voip_engine.h"
 #include "api/voip/voip_network.h"
 #include "api/voip/voip_statistics.h"
+#include "api/voip/voip_volume_control.h"
 #include "audio/audio_transport_impl.h"
 #include "audio/voip/audio_channel.h"
 #include "modules/audio_device/include/audio_device.h"
@@ -49,7 +50,8 @@
                  public VoipNetwork,
                  public VoipCodec,
                  public VoipDtmf,
-                 public VoipStatistics {
+                 public VoipStatistics,
+                 public VoipVolumeControl {
  public:
   // Construct VoipCore with provided arguments.
   // ProcessThread implementation can be injected by |process_thread|
@@ -69,42 +71,53 @@
   VoipCodec& Codec() override { return *this; }
   VoipDtmf& Dtmf() override { return *this; }
   VoipStatistics& Statistics() override { return *this; }
+  VoipVolumeControl& VolumeControl() override { return *this; }
 
   // Implements VoipBase interfaces.
-  absl::optional<ChannelId> CreateChannel(
-      Transport* transport,
-      absl::optional<uint32_t> local_ssrc) override;
-  void ReleaseChannel(ChannelId channel_id) override;
-  bool StartSend(ChannelId channel_id) override;
-  bool StopSend(ChannelId channel_id) override;
-  bool StartPlayout(ChannelId channel_id) override;
-  bool StopPlayout(ChannelId channel_id) override;
+  ChannelId CreateChannel(Transport* transport,
+                          absl::optional<uint32_t> local_ssrc) override;
+  VoipResult ReleaseChannel(ChannelId channel_id) override;
+  VoipResult StartSend(ChannelId channel_id) override;
+  VoipResult StopSend(ChannelId channel_id) override;
+  VoipResult StartPlayout(ChannelId channel_id) override;
+  VoipResult StopPlayout(ChannelId channel_id) override;
 
   // Implements VoipNetwork interfaces.
-  void ReceivedRTPPacket(ChannelId channel_id,
-                         rtc::ArrayView<const uint8_t> rtp_packet) override;
-  void ReceivedRTCPPacket(ChannelId channel_id,
-                          rtc::ArrayView<const uint8_t> rtcp_packet) override;
+  VoipResult ReceivedRTPPacket(
+      ChannelId channel_id,
+      rtc::ArrayView<const uint8_t> rtp_packet) override;
+  VoipResult ReceivedRTCPPacket(
+      ChannelId channel_id,
+      rtc::ArrayView<const uint8_t> rtcp_packet) override;
 
   // Implements VoipCodec interfaces.
-  void SetSendCodec(ChannelId channel_id,
-                    int payload_type,
-                    const SdpAudioFormat& encoder_format) override;
-  void SetReceiveCodecs(
+  VoipResult SetSendCodec(ChannelId channel_id,
+                          int payload_type,
+                          const SdpAudioFormat& encoder_format) override;
+  VoipResult SetReceiveCodecs(
       ChannelId channel_id,
       const std::map<int, SdpAudioFormat>& decoder_specs) override;
 
   // Implements VoipDtmf interfaces.
-  void RegisterTelephoneEventType(ChannelId channel_id,
-                                  int rtp_payload_type,
-                                  int sample_rate_hz) override;
-  bool SendDtmfEvent(ChannelId channel_id,
-                     DtmfEvent dtmf_event,
-                     int duration_ms) override;
+  VoipResult RegisterTelephoneEventType(ChannelId channel_id,
+                                        int rtp_payload_type,
+                                        int sample_rate_hz) override;
+  VoipResult SendDtmfEvent(ChannelId channel_id,
+                           DtmfEvent dtmf_event,
+                           int duration_ms) override;
 
   // Implements VoipStatistics interfaces.
-  absl::optional<IngressStatistics> GetIngressStatistics(
-      ChannelId channel_id) override;
+  VoipResult GetIngressStatistics(ChannelId channel_id,
+                                  IngressStatistics& ingress_stats) override;
+  VoipResult GetChannelStatistics(ChannelId channe_id,
+                                  ChannelStatistics& channel_stats) override;
+
+  // Implements VoipVolumeControl interfaces.
+  VoipResult SetInputMuted(ChannelId channel_id, bool enable) override;
+  VoipResult GetInputVolumeInfo(ChannelId channel_id,
+                                VolumeInfo& volume_info) override;
+  VoipResult GetOutputVolumeInfo(ChannelId channel_id,
+                                 VolumeInfo& volume_info) override;
 
  private:
   // Initialize ADM and default audio device if needed.
diff --git a/common_audio/OWNERS b/common_audio/OWNERS
index ba1c8b1..4cb5316 100644
--- a/common_audio/OWNERS
+++ b/common_audio/OWNERS
@@ -1,3 +1,3 @@
 henrik.lundin@webrtc.org
-kwiberg@webrtc.org
+minyue@webrtc.org
 peah@webrtc.org
diff --git a/common_audio/signal_processing/splitting_filter.c b/common_audio/signal_processing/splitting_filter.c
index 399433f..b0d83f1 100644
--- a/common_audio/signal_processing/splitting_filter.c
+++ b/common_audio/signal_processing/splitting_filter.c
@@ -44,9 +44,11 @@
 //                            |data_length|
 //
 
-void WebRtcSpl_AllPassQMF(int32_t* in_data, size_t data_length,
-                          int32_t* out_data, const uint16_t* filter_coefficients,
-                          int32_t* filter_state)
+static void WebRtcSpl_AllPassQMF(int32_t* in_data,
+                                 size_t data_length,
+                                 int32_t* out_data,
+                                 const uint16_t* filter_coefficients,
+                                 int32_t* filter_state)
 {
     // The procedure is to filter the input with three first order all pass filters
     // (cascade operations).
diff --git a/cras-config/aec_config.cc b/cras-config/aec_config.cc
index c98bc91..5ce9581 100644
--- a/cras-config/aec_config.cc
+++ b/cras-config/aec_config.cc
@@ -120,6 +120,8 @@
 		AEC_GET_INT(ini, FILTER, CONFIG_CHANGE_DURATION_BLOCKS);
 	config->filter.initial_state_seconds =
 		AEC_GET_FLOAT(ini, FILTER, INITIAL_STATE_SECONDS);
+	config->filter.coarse_reset_hangover_blocks =
+		AEC_GET_INT(ini, FILTER, COARSE_RESET_HANGOVER_BLOCKS);;
 	config->filter.conservative_initial_phase =
 		AEC_GET_INT(ini, FILTER, CONSERVATIVE_INITIAL_PHASE);
 	config->filter.enable_coarse_filter_output_usage =
@@ -402,6 +404,9 @@
 			config.filter.config_change_duration_blocks);
 	syslog(LOG_ERR, "    initial_state_seconds %f",
 			config.filter.initial_state_seconds);
+
+	syslog(LOG_ERR, "    coarse_reset_hangover_blocks %d",
+			config.filter.coarse_reset_hangover_blocks);
 	syslog(LOG_ERR, "    conservative_initial_phase %d",
 			config.filter.conservative_initial_phase);
 	syslog(LOG_ERR, "    enable_coarse_filter_output_usage %d",
diff --git a/cras-config/aec_config.h b/cras-config/aec_config.h
index fcf4f56..4f1b46a 100644
--- a/cras-config/aec_config.h
+++ b/cras-config/aec_config.h
@@ -124,6 +124,9 @@
 #define AEC_FILTER_CONFIG_CHANGE_DURATION_BLOCKS_VALUE 250
 #define AEC_FILTER_INITIAL_STATE_SECONDS "filter:initial_state_seconds"
 #define AEC_FILTER_INITIAL_STATE_SECONDS_VALUE 2.5f
+#define AEC_FILTER_COARSE_RESET_HANGOVER_BLOCKS \
+	"filter:coarse_reset_hangover_blocks"
+#define AEC_FILTER_COARSE_RESET_HANGOVER_BLOCKS_VALUE 25
 #define AEC_FILTER_CONSERVATIVE_INITIAL_PHASE \
 	"filter:conservative_initial_phase"
 #define AEC_FILTER_CONSERVATIVE_INITIAL_PHASE_VALUE 0
diff --git a/cras-config/apm_config.cc b/cras-config/apm_config.cc
index 7d713d4..c921ee7 100644
--- a/cras-config/apm_config.cc
+++ b/cras-config/apm_config.cc
@@ -174,6 +174,12 @@
 		APM_GET_INT(ini, ADAPTIVE_DIGITAL_LEVEL_ESTIMATOR));
 	syslog(LOG_ERR, "adaptive_digital_use_saturation_protector %d",
 		APM_GET_INT(ini, ADAPTIVE_DIGITAL_USE_SATURATION_PROTECTOR));
+	syslog(LOG_ERR, "adaptive_digital_sse2_allowed %d",
+		APM_GET_INT(ini, ADAPTIVE_DIGITAL_SSE2_ALLOWED));
+	syslog(LOG_ERR, "adaptive_digital_avx2_allowed %d",
+		APM_GET_INT(ini, ADAPTIVE_DIGITAL_AVX2_ALLOWED));
+	syslog(LOG_ERR, "adaptive_digital_neon_allowed %d",
+		APM_GET_INT(ini, ADAPTIVE_DIGITAL_NEON_ALLOWED));
 	syslog(LOG_ERR, "gain_controller2_fixed_digital_gain_db %f",
 		APM_GET_FLOAT(ini, APM_GAIN_CONTROLLER2_FIXED_DIGITAL_GAIN_DB));
 
diff --git a/cras-config/apm_config.h b/cras-config/apm_config.h
index 0f4e5fb..35c76f6 100644
--- a/cras-config/apm_config.h
+++ b/cras-config/apm_config.h
@@ -76,6 +76,15 @@
 #define ADAPTIVE_DIGITAL_MAX_OUTPUT_NOISE_LEVEL_DBFS \
 	"apm:adaptive_digital_max_output_noise_level_dbfs"
 #define ADAPTIVE_DIGITAL_MAX_OUTPUT_NOISE_LEVEL_DBFS_VALUE -50.f
+#define ADAPTIVE_DIGITAL_SSE2_ALLOWED \
+	"apm:adaptive_digital_sse2_allowed"
+#define ADAPTIVE_DIGITAL_SSE2_ALLOWED_VALUE 1
+#define ADAPTIVE_DIGITAL_AVX2_ALLOWED \
+	"apm:adaptive_digital_avx2_allowed"
+#define ADAPTIVE_DIGITAL_AVX2_ALLOWED_VALUE 1
+#define ADAPTIVE_DIGITAL_NEON_ALLOWED \
+	"apm:adaptive_digital_neon_allowed"
+#define ADAPTIVE_DIGITAL_NEON_ALLOWED_VALUE 1
 
 #define APM_GAIN_CONTROL_COMPRESSION_GAIN_DB "apm:gain_control_compression_gain_db"
 #define APM_GAIN_CONTROL_COMPRESSION_GAIN_DB_VALUE 9
diff --git a/modules/audio_coding/OWNERS b/modules/audio_coding/OWNERS
index 3d4b4fd..f7a0e47 100644
--- a/modules/audio_coding/OWNERS
+++ b/modules/audio_coding/OWNERS
@@ -1,4 +1,3 @@
 henrik.lundin@webrtc.org
-kwiberg@webrtc.org
 minyue@webrtc.org
 ivoc@webrtc.org
diff --git a/modules/audio_coding/codecs/cng/audio_encoder_cng.cc b/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
index 600cb0c..7546ac1 100644
--- a/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
+++ b/modules/audio_coding/codecs/cng/audio_encoder_cng.cc
@@ -171,9 +171,8 @@
       last_frame_active_ = true;
       break;
     }
-    case Vad::kError: {
-      FATAL();  // Fails only if fed invalid data.
-      break;
+    default: {
+      RTC_CHECK_NOTREACHED();
     }
   }
 
diff --git a/modules/audio_coding/codecs/ilbc/abs_quant.c b/modules/audio_coding/codecs/ilbc/abs_quant.c
index 308902f..77da78b 100644
--- a/modules/audio_coding/codecs/ilbc/abs_quant.c
+++ b/modules/audio_coding/codecs/ilbc/abs_quant.c
@@ -16,9 +16,11 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/abs_quant.h"
+
 #include "modules/audio_coding/codecs/ilbc/abs_quant_loop.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/abs_quant.h b/modules/audio_coding/codecs/ilbc/abs_quant.h
index 331921c..c72e29c 100644
--- a/modules/audio_coding/codecs/ilbc/abs_quant.h
+++ b/modules/audio_coding/codecs/ilbc/abs_quant.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/abs_quant_loop.c b/modules/audio_coding/codecs/ilbc/abs_quant_loop.c
index 2d8a998..cf92662 100644
--- a/modules/audio_coding/codecs/ilbc/abs_quant_loop.c
+++ b/modules/audio_coding/codecs/ilbc/abs_quant_loop.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/abs_quant_loop.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/sort_sq.h"
 
 void WebRtcIlbcfix_AbsQuantLoop(int16_t *syntOutIN, int16_t *in_weightedIN,
diff --git a/modules/audio_coding/codecs/ilbc/abs_quant_loop.h b/modules/audio_coding/codecs/ilbc/abs_quant_loop.h
index a193a07..841d73b 100644
--- a/modules/audio_coding/codecs/ilbc/abs_quant_loop.h
+++ b/modules/audio_coding/codecs/ilbc/abs_quant_loop.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ABS_QUANT_LOOP_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  predictive noise shaping encoding of scaled start state
diff --git a/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h b/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
index d73ef0d..c2d62ed 100644
--- a/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
@@ -13,6 +13,7 @@
 
 #include <stddef.h>
 #include <stdint.h>
+
 #include <vector>
 
 #include "api/audio_codecs/audio_decoder.h"
diff --git a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
index fe3e329..05a900e 100644
--- a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
@@ -11,6 +11,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_AUDIO_ENCODER_ILBC_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include <utility>
 
 #include "absl/types/optional.h"
diff --git a/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c b/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c
index 77b0f7f..c915a2f 100644
--- a/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c
+++ b/modules/audio_coding/codecs/ilbc/augmented_cb_corr.c
@@ -16,10 +16,11 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
 #include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
 
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
 void WebRtcIlbcfix_AugmentedCbCorr(
     int16_t *target,   /* (i) Target vector */
     int16_t *buffer,   /* (i) Memory buffer */
diff --git a/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h b/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h
index 646e564..2e9612e 100644
--- a/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h
+++ b/modules/audio_coding/codecs/ilbc/augmented_cb_corr.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_AUGMENTED_CB_CORR_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Calculate correlation between target and Augmented codebooks
diff --git a/modules/audio_coding/codecs/ilbc/bw_expand.c b/modules/audio_coding/codecs/ilbc/bw_expand.c
index 566af7d..1a9b882 100644
--- a/modules/audio_coding/codecs/ilbc/bw_expand.c
+++ b/modules/audio_coding/codecs/ilbc/bw_expand.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/bw_expand.h b/modules/audio_coding/codecs/ilbc/bw_expand.h
index d25325c..ff9b0b3 100644
--- a/modules/audio_coding/codecs/ilbc/bw_expand.h
+++ b/modules/audio_coding/codecs/ilbc/bw_expand.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_BW_EXPAND_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  lpc bandwidth expansion
diff --git a/modules/audio_coding/codecs/ilbc/cb_construct.h b/modules/audio_coding/codecs/ilbc/cb_construct.h
index f4df387..0a4a47a 100644
--- a/modules/audio_coding/codecs/ilbc/cb_construct.h
+++ b/modules/audio_coding/codecs/ilbc/cb_construct.h
@@ -20,6 +20,7 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_CONSTRUCT_H_
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 
 #include "modules/audio_coding/codecs/ilbc/defines.h"
diff --git a/modules/audio_coding/codecs/ilbc/cb_mem_energy.c b/modules/audio_coding/codecs/ilbc/cb_mem_energy.c
index 9304a91..21e4197 100644
--- a/modules/audio_coding/codecs/ilbc/cb_mem_energy.c
+++ b/modules/audio_coding/codecs/ilbc/cb_mem_energy.c
@@ -16,9 +16,11 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy.h"
+
 #include "modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Function WebRtcIlbcfix_CbMemEnergy computes the energy of all
diff --git a/modules/audio_coding/codecs/ilbc/cb_mem_energy.h b/modules/audio_coding/codecs/ilbc/cb_mem_energy.h
index 894f5d0..17ec337 100644
--- a/modules/audio_coding/codecs/ilbc/cb_mem_energy.h
+++ b/modules/audio_coding/codecs/ilbc/cb_mem_energy.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 void WebRtcIlbcfix_CbMemEnergy(
     size_t range,
     int16_t* CB,           /* (i) The CB memory (1:st section) */
diff --git a/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c b/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c
index df9ff45..0619bbe 100644
--- a/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c
+++ b/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 void WebRtcIlbcfix_CbMemEnergyAugmentation(
     int16_t *interpSamples, /* (i) The interpolated samples */
diff --git a/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h b/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h
index b7b972f..d7b7a0d 100644
--- a/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h
+++ b/modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_AUGMENTATION_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 void WebRtcIlbcfix_CbMemEnergyAugmentation(
     int16_t* interpSamples, /* (i) The interpolated samples */
     int16_t* CBmem,         /* (i) The CB memory */
diff --git a/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c b/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c
index 35d3ce4..58c0c5f 100644
--- a/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c
+++ b/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /* Compute the energy of the rest of the cb memory
diff --git a/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h b/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h
index 5511ef1..1d1e8d6 100644
--- a/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h
+++ b/modules/audio_coding/codecs/ilbc/cb_mem_energy_calc.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_MEM_ENERGY_CALC_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 void WebRtcIlbcfix_CbMemEnergyCalc(
     int32_t energy,        /* (i) input start energy */
     size_t range,          /* (i) number of iterations */
diff --git a/modules/audio_coding/codecs/ilbc/cb_search.c b/modules/audio_coding/codecs/ilbc/cb_search.c
index 88b2f01..24b5292 100644
--- a/modules/audio_coding/codecs/ilbc/cb_search.c
+++ b/modules/audio_coding/codecs/ilbc/cb_search.c
@@ -16,18 +16,20 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
-#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/cb_search.h"
+
+#include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
 #include "modules/audio_coding/codecs/ilbc/cb_mem_energy.h"
-#include "modules/audio_coding/codecs/ilbc/interpolate_samples.h"
 #include "modules/audio_coding/codecs/ilbc/cb_mem_energy_augmentation.h"
 #include "modules/audio_coding/codecs/ilbc/cb_search_core.h"
-#include "modules/audio_coding/codecs/ilbc/energy_inverse.h"
-#include "modules/audio_coding/codecs/ilbc/augmented_cb_corr.h"
 #include "modules/audio_coding/codecs/ilbc/cb_update_best_index.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
 #include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/energy_inverse.h"
+#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
+#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
+#include "modules/audio_coding/codecs/ilbc/interpolate_samples.h"
 
 /*----------------------------------------------------------------*
  *  Search routine for codebook encoding and gain quantization.
diff --git a/modules/audio_coding/codecs/ilbc/cb_search.h b/modules/audio_coding/codecs/ilbc/cb_search.h
index 393a2de..84a52c7 100644
--- a/modules/audio_coding/codecs/ilbc/cb_search.h
+++ b/modules/audio_coding/codecs/ilbc/cb_search.h
@@ -19,6 +19,11 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
 void WebRtcIlbcfix_CbSearch(
     IlbcEncoder* iLBCenc_inst,
     /* (i) the encoder state structure */
diff --git a/modules/audio_coding/codecs/ilbc/cb_search_core.c b/modules/audio_coding/codecs/ilbc/cb_search_core.c
index 09d26d3..a75e5b0 100644
--- a/modules/audio_coding/codecs/ilbc/cb_search_core.c
+++ b/modules/audio_coding/codecs/ilbc/cb_search_core.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/cb_search_core.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 void WebRtcIlbcfix_CbSearchCore(
     int32_t *cDot,    /* (i) Cross Correlation */
diff --git a/modules/audio_coding/codecs/ilbc/cb_search_core.h b/modules/audio_coding/codecs/ilbc/cb_search_core.h
index af5a1db..5da70e0 100644
--- a/modules/audio_coding/codecs/ilbc/cb_search_core.h
+++ b/modules/audio_coding/codecs/ilbc/cb_search_core.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_SEARCH_CORE_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 void WebRtcIlbcfix_CbSearchCore(
     int32_t* cDot,               /* (i) Cross Correlation */
diff --git a/modules/audio_coding/codecs/ilbc/cb_update_best_index.c b/modules/audio_coding/codecs/ilbc/cb_update_best_index.c
index ed20c46..d6fa4d9 100644
--- a/modules/audio_coding/codecs/ilbc/cb_update_best_index.c
+++ b/modules/audio_coding/codecs/ilbc/cb_update_best_index.c
@@ -16,9 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/cb_update_best_index.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 void WebRtcIlbcfix_CbUpdateBestIndex(
     int32_t CritNew,    /* (i) New Potentially best Criteria */
diff --git a/modules/audio_coding/codecs/ilbc/cb_update_best_index.h b/modules/audio_coding/codecs/ilbc/cb_update_best_index.h
index 3f57d48..1a95d53 100644
--- a/modules/audio_coding/codecs/ilbc/cb_update_best_index.h
+++ b/modules/audio_coding/codecs/ilbc/cb_update_best_index.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CB_UPDATE_BEST_INDEX_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 void WebRtcIlbcfix_CbUpdateBestIndex(
     int32_t CritNew,        /* (i) New Potentially best Criteria */
diff --git a/modules/audio_coding/codecs/ilbc/chebyshev.c b/modules/audio_coding/codecs/ilbc/chebyshev.c
index 38a3069..b4eee66 100644
--- a/modules/audio_coding/codecs/ilbc/chebyshev.c
+++ b/modules/audio_coding/codecs/ilbc/chebyshev.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/chebyshev.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*------------------------------------------------------------------*
  *  Calculate the Chevyshev polynomial series
diff --git a/modules/audio_coding/codecs/ilbc/chebyshev.h b/modules/audio_coding/codecs/ilbc/chebyshev.h
index 64b2f49..7e7742c 100644
--- a/modules/audio_coding/codecs/ilbc/chebyshev.h
+++ b/modules/audio_coding/codecs/ilbc/chebyshev.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CHEBYSHEV_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*------------------------------------------------------------------*
  *  Calculate the Chevyshev polynomial series
diff --git a/modules/audio_coding/codecs/ilbc/comp_corr.c b/modules/audio_coding/codecs/ilbc/comp_corr.c
index b43f2fc..452bc78 100644
--- a/modules/audio_coding/codecs/ilbc/comp_corr.c
+++ b/modules/audio_coding/codecs/ilbc/comp_corr.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/comp_corr.h b/modules/audio_coding/codecs/ilbc/comp_corr.h
index 1e6b296..010c6a1 100644
--- a/modules/audio_coding/codecs/ilbc/comp_corr.h
+++ b/modules/audio_coding/codecs/ilbc/comp_corr.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_COMP_CORR_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Compute cross correlation and pitch gain for pitch prediction
diff --git a/modules/audio_coding/codecs/ilbc/constants.c b/modules/audio_coding/codecs/ilbc/constants.c
index 8efa6ae..22f2acb 100644
--- a/modules/audio_coding/codecs/ilbc/constants.c
+++ b/modules/audio_coding/codecs/ilbc/constants.c
@@ -16,9 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
 
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
 /* HP Filters {b[0] b[1] b[2] -a[1] -a[2]} */
 
 const int16_t WebRtcIlbcfix_kHpInCoefs[5] = {3798, -7596, 3798, 7807, -3733};
diff --git a/modules/audio_coding/codecs/ilbc/constants.h b/modules/audio_coding/codecs/ilbc/constants.h
index 07369a3..a8645c0 100644
--- a/modules/audio_coding/codecs/ilbc/constants.h
+++ b/modules/audio_coding/codecs/ilbc/constants.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CONSTANTS_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /* high pass filters */
diff --git a/modules/audio_coding/codecs/ilbc/create_augmented_vec.c b/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
index 6a4d058..8033c95 100644
--- a/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
+++ b/modules/audio_coding/codecs/ilbc/create_augmented_vec.c
@@ -16,10 +16,12 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "rtc_base/sanitizer.h"
+#include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
+
 #include "common_audio/signal_processing/include/signal_processing_library.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "rtc_base/sanitizer.h"
 
 /*----------------------------------------------------------------*
  *  Recreate a specific codebook vector from the augmented part.
diff --git a/modules/audio_coding/codecs/ilbc/create_augmented_vec.h b/modules/audio_coding/codecs/ilbc/create_augmented_vec.h
index 28c9400..d7e5be1 100644
--- a/modules/audio_coding/codecs/ilbc/create_augmented_vec.h
+++ b/modules/audio_coding/codecs/ilbc/create_augmented_vec.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_CREATE_AUGMENTED_VEC_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Recreate a specific codebook vector from the augmented part.
diff --git a/modules/audio_coding/codecs/ilbc/decode.c b/modules/audio_coding/codecs/ilbc/decode.c
index 3848bc7..d7621d5 100644
--- a/modules/audio_coding/codecs/ilbc/decode.c
+++ b/modules/audio_coding/codecs/ilbc/decode.c
@@ -16,22 +16,23 @@
 
 ******************************************************************/
 
-// Defines WEBRTC_ARCH_BIG_ENDIAN, used below.
+#include "modules/audio_coding/codecs/ilbc/decode.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/decode_residual.h"
+#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/do_plc.h"
+#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
+#include "modules/audio_coding/codecs/ilbc/hp_output.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
+#include "modules/audio_coding/codecs/ilbc/init_decode.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
+#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
 #include "rtc_base/system/arch.h"
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
-#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
-#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
-#include "modules/audio_coding/codecs/ilbc/do_plc.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
-#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
-#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
-#include "modules/audio_coding/codecs/ilbc/decode_residual.h"
-#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
-#include "modules/audio_coding/codecs/ilbc/hp_output.h"
-#include "modules/audio_coding/codecs/ilbc/init_decode.h"
 #ifndef WEBRTC_ARCH_BIG_ENDIAN
 #include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
 #endif
diff --git a/modules/audio_coding/codecs/ilbc/decode_residual.c b/modules/audio_coding/codecs/ilbc/decode_residual.c
index 3c113ae..a9668e2 100644
--- a/modules/audio_coding/codecs/ilbc/decode_residual.c
+++ b/modules/audio_coding/codecs/ilbc/decode_residual.c
@@ -20,15 +20,15 @@
 
 #include <string.h>
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/state_construct.h"
 #include "modules/audio_coding/codecs/ilbc/cb_construct.h"
-#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
-#include "modules/audio_coding/codecs/ilbc/do_plc.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/do_plc.h"
 #include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
-#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
 #include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/state_construct.h"
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
 
 /*----------------------------------------------------------------*
  *  frame residual decoder function (subrutine to iLBC_decode)
diff --git a/modules/audio_coding/codecs/ilbc/decode_residual.h b/modules/audio_coding/codecs/ilbc/decode_residual.h
index d54aada..30eb35f 100644
--- a/modules/audio_coding/codecs/ilbc/decode_residual.h
+++ b/modules/audio_coding/codecs/ilbc/decode_residual.h
@@ -20,6 +20,7 @@
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODE_RESIDUAL_H_
 
 #include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 
 #include "modules/audio_coding/codecs/ilbc/defines.h"
diff --git a/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c b/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c
index 8413a73..d96bb9b 100644
--- a/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c
+++ b/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.c
@@ -16,10 +16,12 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h"
+#include "modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h"
+
 #include "modules/audio_coding/codecs/ilbc/bw_expand.h"
-#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h"
 
 /*----------------------------------------------------------------*
  *  obtain synthesis and weighting filters form lsf coefficients
diff --git a/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h b/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h
index 48d43ec..8b08114 100644
--- a/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h
+++ b/modules/audio_coding/codecs/ilbc/decoder_interpolate_lsf.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DECODER_INTERPOLATE_LSF_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/defines.h b/modules/audio_coding/codecs/ilbc/defines.h
index 43948a2..64135c4 100644
--- a/modules/audio_coding/codecs/ilbc/defines.h
+++ b/modules/audio_coding/codecs/ilbc/defines.h
@@ -18,6 +18,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DEFINES_H_
 
+#include <stdint.h>
 #include <string.h>
 
 #include "common_audio/signal_processing/include/signal_processing_library.h"
diff --git a/modules/audio_coding/codecs/ilbc/do_plc.c b/modules/audio_coding/codecs/ilbc/do_plc.c
index 26ec03f..9ca6ca4 100644
--- a/modules/audio_coding/codecs/ilbc/do_plc.c
+++ b/modules/audio_coding/codecs/ilbc/do_plc.c
@@ -16,10 +16,12 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
+#include "modules/audio_coding/codecs/ilbc/do_plc.h"
+
 #include "modules/audio_coding/codecs/ilbc/bw_expand.h"
+#include "modules/audio_coding/codecs/ilbc/comp_corr.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Packet loss concealment routine. Conceals a residual signal
diff --git a/modules/audio_coding/codecs/ilbc/do_plc.h b/modules/audio_coding/codecs/ilbc/do_plc.h
index 2fbae1d..c19c4ec 100644
--- a/modules/audio_coding/codecs/ilbc/do_plc.h
+++ b/modules/audio_coding/codecs/ilbc/do_plc.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_DO_PLC_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/encode.c b/modules/audio_coding/codecs/ilbc/encode.c
index 912e23c..8e53622 100644
--- a/modules/audio_coding/codecs/ilbc/encode.c
+++ b/modules/audio_coding/codecs/ilbc/encode.c
@@ -16,28 +16,29 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/encode.h"
+
 #include <string.h>
 
-// Defines WEBRTC_ARCH_BIG_ENDIAN, used below.
-#include "rtc_base/system/arch.h"
-
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
-#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
-#include "modules/audio_coding/codecs/ilbc/state_search.h"
-#include "modules/audio_coding/codecs/ilbc/state_construct.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "modules/audio_coding/codecs/ilbc/cb_search.h"
 #include "modules/audio_coding/codecs/ilbc/cb_construct.h"
-#include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
-#include "modules/audio_coding/codecs/ilbc/pack_bits.h"
+#include "modules/audio_coding/codecs/ilbc/cb_search.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
 #include "modules/audio_coding/codecs/ilbc/hp_input.h"
+#include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
+#include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
+#include "modules/audio_coding/codecs/ilbc/pack_bits.h"
+#include "modules/audio_coding/codecs/ilbc/state_construct.h"
+#include "modules/audio_coding/codecs/ilbc/state_search.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/system/arch.h"
 
 #ifdef SPLIT_10MS
 #include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
 #include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
 #endif
+
 #ifndef WEBRTC_ARCH_BIG_ENDIAN
 #include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
 #endif
diff --git a/modules/audio_coding/codecs/ilbc/encode.h b/modules/audio_coding/codecs/ilbc/encode.h
index db00e2c..bc3e187 100644
--- a/modules/audio_coding/codecs/ilbc/encode.h
+++ b/modules/audio_coding/codecs/ilbc/encode.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENCODE_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/energy_inverse.h b/modules/audio_coding/codecs/ilbc/energy_inverse.h
index 359a9e2..15391cf 100644
--- a/modules/audio_coding/codecs/ilbc/energy_inverse.h
+++ b/modules/audio_coding/codecs/ilbc/energy_inverse.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENERGY_INVERSE_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /* Inverses the in vector in into Q29 domain */
diff --git a/modules/audio_coding/codecs/ilbc/enh_upsample.c b/modules/audio_coding/codecs/ilbc/enh_upsample.c
index 0a5f044..cd3d0a4 100644
--- a/modules/audio_coding/codecs/ilbc/enh_upsample.c
+++ b/modules/audio_coding/codecs/ilbc/enh_upsample.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/enh_upsample.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  * upsample finite array assuming zeros outside bounds
diff --git a/modules/audio_coding/codecs/ilbc/enhancer.c b/modules/audio_coding/codecs/ilbc/enhancer.c
index d5cd977..bd4e600 100644
--- a/modules/audio_coding/codecs/ilbc/enhancer.c
+++ b/modules/audio_coding/codecs/ilbc/enhancer.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/enhancer.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/get_sync_seq.h"
 #include "modules/audio_coding/codecs/ilbc/smooth.h"
 
diff --git a/modules/audio_coding/codecs/ilbc/enhancer.h b/modules/audio_coding/codecs/ilbc/enhancer.h
index 1a6131b..3869493 100644
--- a/modules/audio_coding/codecs/ilbc/enhancer.h
+++ b/modules/audio_coding/codecs/ilbc/enhancer.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * perform enhancement on idata+centerStartPos through
diff --git a/modules/audio_coding/codecs/ilbc/enhancer_interface.c b/modules/audio_coding/codecs/ilbc/enhancer_interface.c
index f85df6d..fb9740e 100644
--- a/modules/audio_coding/codecs/ilbc/enhancer_interface.c
+++ b/modules/audio_coding/codecs/ilbc/enhancer_interface.c
@@ -16,13 +16,15 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/enhancer_interface.h"
+
 #include <string.h>
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/enhancer.h"
 #include "modules/audio_coding/codecs/ilbc/hp_output.h"
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
 
 
 
@@ -201,11 +203,13 @@
     regressor=in+tlag-1;
 
     /* scaling */
-    max16 = WebRtcSpl_MaxAbsValueW16(regressor, plc_blockl + 3 - 1);
-    if (max16>5000)
-      shifts=2;
-    else
-      shifts=0;
+    // Note that this is not abs-max, but it doesn't matter since we use only
+    // the square of it.
+    max16 = regressor[WebRtcSpl_MaxAbsIndexW16(regressor, plc_blockl + 3 - 1)];
+
+    const int64_t max_val = plc_blockl * max16 * max16;
+    const int32_t factor = max_val >> 31;
+    shifts = factor == 0 ? 0 : 31 - WebRtcSpl_NormW32(factor);
 
     /* compute cross correlation */
     WebRtcSpl_CrossCorrelation(corr32, target, regressor, plc_blockl, 3, shifts,
diff --git a/modules/audio_coding/codecs/ilbc/enhancer_interface.h b/modules/audio_coding/codecs/ilbc/enhancer_interface.h
index de45715..5022a47 100644
--- a/modules/audio_coding/codecs/ilbc/enhancer_interface.h
+++ b/modules/audio_coding/codecs/ilbc/enhancer_interface.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_ENHANCER_INTERFACE_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c b/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c
index 4624211..6b4f30c 100644
--- a/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c
+++ b/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Construct an additional codebook vector by filtering the
diff --git a/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h b/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h
index c51ac39..661262e 100644
--- a/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h
+++ b/modules/audio_coding/codecs/ilbc/filtered_cb_vecs.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FILTERED_CB_VECS_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Construct an additional codebook vector by filtering the
diff --git a/modules/audio_coding/codecs/ilbc/frame_classify.c b/modules/audio_coding/codecs/ilbc/frame_classify.c
index 6edf921..c1084b1 100644
--- a/modules/audio_coding/codecs/ilbc/frame_classify.c
+++ b/modules/audio_coding/codecs/ilbc/frame_classify.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/frame_classify.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Classification of subframes to localize start state
diff --git a/modules/audio_coding/codecs/ilbc/frame_classify.h b/modules/audio_coding/codecs/ilbc/frame_classify.h
index 43c6e57..7615106 100644
--- a/modules/audio_coding/codecs/ilbc/frame_classify.h
+++ b/modules/audio_coding/codecs/ilbc/frame_classify.h
@@ -19,6 +19,11 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_FRAME_CLASSIFY_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+
 size_t WebRtcIlbcfix_FrameClassify(
     /* (o) Index to the max-energy sub frame */
     IlbcEncoder* iLBCenc_inst,
diff --git a/modules/audio_coding/codecs/ilbc/gain_dequant.c b/modules/audio_coding/codecs/ilbc/gain_dequant.c
index cb405ae..1357dec 100644
--- a/modules/audio_coding/codecs/ilbc/gain_dequant.c
+++ b/modules/audio_coding/codecs/ilbc/gain_dequant.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/gain_dequant.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  decoder for quantized gains in the gain-shape coding of
diff --git a/modules/audio_coding/codecs/ilbc/gain_dequant.h b/modules/audio_coding/codecs/ilbc/gain_dequant.h
index 86cc787..2b97550 100644
--- a/modules/audio_coding/codecs/ilbc/gain_dequant.h
+++ b/modules/audio_coding/codecs/ilbc/gain_dequant.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_DEQUANT_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  decoder for quantized gains in the gain-shape coding of
diff --git a/modules/audio_coding/codecs/ilbc/gain_quant.c b/modules/audio_coding/codecs/ilbc/gain_quant.c
index 2472239..9a6d49d 100644
--- a/modules/audio_coding/codecs/ilbc/gain_quant.c
+++ b/modules/audio_coding/codecs/ilbc/gain_quant.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/gain_quant.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  quantizer for the gain in the gain-shape coding of residual
diff --git a/modules/audio_coding/codecs/ilbc/gain_quant.h b/modules/audio_coding/codecs/ilbc/gain_quant.h
index 51c0bc9..761f7d2 100644
--- a/modules/audio_coding/codecs/ilbc/gain_quant.h
+++ b/modules/audio_coding/codecs/ilbc/gain_quant.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GAIN_QUANT_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  quantizer for the gain in the gain-shape coding of residual
diff --git a/modules/audio_coding/codecs/ilbc/get_cd_vec.c b/modules/audio_coding/codecs/ilbc/get_cd_vec.c
index d3479ec..145cb96 100644
--- a/modules/audio_coding/codecs/ilbc/get_cd_vec.c
+++ b/modules/audio_coding/codecs/ilbc/get_cd_vec.c
@@ -18,9 +18,9 @@
 
 #include "modules/audio_coding/codecs/ilbc/get_cd_vec.h"
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
 #include "modules/audio_coding/codecs/ilbc/create_augmented_vec.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Construct codebook vector for given index.
diff --git a/modules/audio_coding/codecs/ilbc/get_lsp_poly.c b/modules/audio_coding/codecs/ilbc/get_lsp_poly.c
index ecf5770..e0fb21c 100644
--- a/modules/audio_coding/codecs/ilbc/get_lsp_poly.c
+++ b/modules/audio_coding/codecs/ilbc/get_lsp_poly.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/get_lsp_poly.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/get_lsp_poly.h b/modules/audio_coding/codecs/ilbc/get_lsp_poly.h
index d469409..70c9c4d 100644
--- a/modules/audio_coding/codecs/ilbc/get_lsp_poly.h
+++ b/modules/audio_coding/codecs/ilbc/get_lsp_poly.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_LSP_POLY_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * Construct the polynomials F1(z) and F2(z) from the LSP
diff --git a/modules/audio_coding/codecs/ilbc/get_sync_seq.c b/modules/audio_coding/codecs/ilbc/get_sync_seq.c
index c5b11f1..68a569a 100644
--- a/modules/audio_coding/codecs/ilbc/get_sync_seq.c
+++ b/modules/audio_coding/codecs/ilbc/get_sync_seq.c
@@ -16,10 +16,12 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/get_sync_seq.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "modules/audio_coding/codecs/ilbc/refiner.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/nearest_neighbor.h"
+#include "modules/audio_coding/codecs/ilbc/refiner.h"
 
 /*----------------------------------------------------------------*
  * get the pitch-synchronous sample sequence
diff --git a/modules/audio_coding/codecs/ilbc/get_sync_seq.h b/modules/audio_coding/codecs/ilbc/get_sync_seq.h
index 2281b06..90962fa 100644
--- a/modules/audio_coding/codecs/ilbc/get_sync_seq.h
+++ b/modules/audio_coding/codecs/ilbc/get_sync_seq.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_GET_SYNC_SEQ_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * get the pitch-synchronous sample sequence
diff --git a/modules/audio_coding/codecs/ilbc/hp_input.c b/modules/audio_coding/codecs/ilbc/hp_input.c
index dd6e20b..be582f2 100644
--- a/modules/audio_coding/codecs/ilbc/hp_input.c
+++ b/modules/audio_coding/codecs/ilbc/hp_input.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/hp_input.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/hp_input.h b/modules/audio_coding/codecs/ilbc/hp_input.h
index 682441a..9143d8e 100644
--- a/modules/audio_coding/codecs/ilbc/hp_input.h
+++ b/modules/audio_coding/codecs/ilbc/hp_input.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_INPUT_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 // clang-format off
 // Bad job here. https://bugs.llvm.org/show_bug.cgi?id=34274
diff --git a/modules/audio_coding/codecs/ilbc/hp_output.c b/modules/audio_coding/codecs/ilbc/hp_output.c
index 0628e58..cc5f6dc 100644
--- a/modules/audio_coding/codecs/ilbc/hp_output.c
+++ b/modules/audio_coding/codecs/ilbc/hp_output.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/hp_output.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/hp_output.h b/modules/audio_coding/codecs/ilbc/hp_output.h
index 54d9763..6d1bd3c 100644
--- a/modules/audio_coding/codecs/ilbc/hp_output.h
+++ b/modules/audio_coding/codecs/ilbc/hp_output.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_HP_OUTPUT_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 // clang-format off
 // Bad job here. https://bugs.llvm.org/show_bug.cgi?id=34274
diff --git a/modules/audio_coding/codecs/ilbc/ilbc.c b/modules/audio_coding/codecs/ilbc/ilbc.c
index 326c766..ba6c3e4 100644
--- a/modules/audio_coding/codecs/ilbc/ilbc.c
+++ b/modules/audio_coding/codecs/ilbc/ilbc.c
@@ -16,14 +16,15 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+
 #include <stdlib.h>
 
-#include "modules/audio_coding/codecs/ilbc/ilbc.h"
+#include "modules/audio_coding/codecs/ilbc/decode.h"
 #include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/init_encode.h"
 #include "modules/audio_coding/codecs/ilbc/encode.h"
 #include "modules/audio_coding/codecs/ilbc/init_decode.h"
-#include "modules/audio_coding/codecs/ilbc/decode.h"
+#include "modules/audio_coding/codecs/ilbc/init_encode.h"
 #include "rtc_base/checks.h"
 
 int16_t WebRtcIlbcfix_EncoderAssign(IlbcEncoderInstance** iLBC_encinst,
@@ -260,9 +261,10 @@
   for (i=0;i<noOfLostFrames;i++) {
     // PLC decoding shouldn't fail, because there is no external input data
     // that can be bad.
-    RTC_CHECK(WebRtcIlbcfix_DecodeImpl(
+    int result = WebRtcIlbcfix_DecodeImpl(
         &decoded[i * ((IlbcDecoder*)iLBCdec_inst)->blockl], &dummy,
-        (IlbcDecoder*)iLBCdec_inst, 0));
+        (IlbcDecoder*)iLBCdec_inst, 0);
+    RTC_CHECK_EQ(result, 0);
   }
   return (noOfLostFrames*((IlbcDecoder*)iLBCdec_inst)->blockl);
 }
diff --git a/modules/audio_coding/codecs/ilbc/index_conv_dec.c b/modules/audio_coding/codecs/ilbc/index_conv_dec.c
index ad12cee..d78f81a 100644
--- a/modules/audio_coding/codecs/ilbc/index_conv_dec.c
+++ b/modules/audio_coding/codecs/ilbc/index_conv_dec.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/index_conv_dec.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 void WebRtcIlbcfix_IndexConvDec(
diff --git a/modules/audio_coding/codecs/ilbc/index_conv_enc.c b/modules/audio_coding/codecs/ilbc/index_conv_enc.c
index 6cf164e..8314415 100644
--- a/modules/audio_coding/codecs/ilbc/index_conv_enc.c
+++ b/modules/audio_coding/codecs/ilbc/index_conv_enc.c
@@ -16,7 +16,10 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/index_conv_enc.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
+
 /*----------------------------------------------------------------*
  *  Convert the codebook indexes to make the search easier
  *---------------------------------------------------------------*/
diff --git a/modules/audio_coding/codecs/ilbc/index_conv_enc.h b/modules/audio_coding/codecs/ilbc/index_conv_enc.h
index f899499..4fbf980 100644
--- a/modules/audio_coding/codecs/ilbc/index_conv_enc.h
+++ b/modules/audio_coding/codecs/ilbc/index_conv_enc.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INDEX_CONV_ENC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INDEX_CONV_ENC_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Convert the codebook indexes to make the search easier
diff --git a/modules/audio_coding/codecs/ilbc/init_decode.c b/modules/audio_coding/codecs/ilbc/init_decode.c
index c63cc7c..3eb41e3 100644
--- a/modules/audio_coding/codecs/ilbc/init_decode.c
+++ b/modules/audio_coding/codecs/ilbc/init_decode.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/init_decode.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Initiation of decoder instance.
diff --git a/modules/audio_coding/codecs/ilbc/init_decode.h b/modules/audio_coding/codecs/ilbc/init_decode.h
index fdcf9f0..a2b7b91 100644
--- a/modules/audio_coding/codecs/ilbc/init_decode.h
+++ b/modules/audio_coding/codecs/ilbc/init_decode.h
@@ -19,6 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_DECODE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_DECODE_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/init_encode.c b/modules/audio_coding/codecs/ilbc/init_encode.c
index b21f77e..aa858e9 100644
--- a/modules/audio_coding/codecs/ilbc/init_encode.c
+++ b/modules/audio_coding/codecs/ilbc/init_encode.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/init_encode.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  Initiation of encoder instance.
diff --git a/modules/audio_coding/codecs/ilbc/init_encode.h b/modules/audio_coding/codecs/ilbc/init_encode.h
index f91a9b0..4ada6a3 100644
--- a/modules/audio_coding/codecs/ilbc/init_encode.h
+++ b/modules/audio_coding/codecs/ilbc/init_encode.h
@@ -19,6 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_ENCODE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INIT_ENCODE_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/interpolate.c b/modules/audio_coding/codecs/ilbc/interpolate.c
index 3ce480e..17ed244 100644
--- a/modules/audio_coding/codecs/ilbc/interpolate.c
+++ b/modules/audio_coding/codecs/ilbc/interpolate.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/interpolate.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  interpolation between vectors
diff --git a/modules/audio_coding/codecs/ilbc/interpolate.h b/modules/audio_coding/codecs/ilbc/interpolate.h
index 9f03236..892082b 100644
--- a/modules/audio_coding/codecs/ilbc/interpolate.h
+++ b/modules/audio_coding/codecs/ilbc/interpolate.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  interpolation between vectors
diff --git a/modules/audio_coding/codecs/ilbc/interpolate_samples.c b/modules/audio_coding/codecs/ilbc/interpolate_samples.c
index 9ca38a4..6dddd6f 100644
--- a/modules/audio_coding/codecs/ilbc/interpolate_samples.c
+++ b/modules/audio_coding/codecs/ilbc/interpolate_samples.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/interpolate_samples.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 void WebRtcIlbcfix_InterpolateSamples(
     int16_t *interpSamples, /* (o) The interpolated samples */
diff --git a/modules/audio_coding/codecs/ilbc/interpolate_samples.h b/modules/audio_coding/codecs/ilbc/interpolate_samples.h
index 264a101..bc665d7 100644
--- a/modules/audio_coding/codecs/ilbc/interpolate_samples.h
+++ b/modules/audio_coding/codecs/ilbc/interpolate_samples.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_SAMPLES_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_INTERPOLATE_SAMPLES_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Construct the interpolated samples for the Augmented CB
diff --git a/modules/audio_coding/codecs/ilbc/lpc_encode.c b/modules/audio_coding/codecs/ilbc/lpc_encode.c
index 9b2a0c0..89f6d29 100644
--- a/modules/audio_coding/codecs/ilbc/lpc_encode.c
+++ b/modules/audio_coding/codecs/ilbc/lpc_encode.c
@@ -16,12 +16,14 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h"
-#include "modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h"
-#include "modules/audio_coding/codecs/ilbc/simple_lsf_quant.h"
-#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/lpc_encode.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+#include "modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_quant.h"
 
 /*----------------------------------------------------------------*
  *  lpc encoder
diff --git a/modules/audio_coding/codecs/ilbc/lpc_encode.h b/modules/audio_coding/codecs/ilbc/lpc_encode.h
index 256fa49..a67b77a 100644
--- a/modules/audio_coding/codecs/ilbc/lpc_encode.h
+++ b/modules/audio_coding/codecs/ilbc/lpc_encode.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LPC_ENCODE_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LPC_ENCODE_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/lsf_check.c b/modules/audio_coding/codecs/ilbc/lsf_check.c
index 684b2ce..9f0e19a 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_check.c
+++ b/modules/audio_coding/codecs/ilbc/lsf_check.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_check.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  check for stability of lsf coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsf_check.h b/modules/audio_coding/codecs/ilbc/lsf_check.h
index d367c1d..9ba90a3 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_check.h
+++ b/modules/audio_coding/codecs/ilbc/lsf_check.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_CHECK_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_CHECK_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  check for stability of lsf coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c
index e501f3c..04de5e7 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c
+++ b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.c
@@ -16,9 +16,11 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h"
+
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/interpolate.h"
 #include "modules/audio_coding/codecs/ilbc/lsf_to_poly.h"
-#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  interpolation of lsf coefficients for the decoder
diff --git a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h
index 016897a..6cc9d97 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h
+++ b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_dec.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_DEC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_DEC_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  interpolation of lsf coefficients for the decoder
diff --git a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c
index a660c4f..6188212 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c
+++ b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/interpolate.h"
 #include "modules/audio_coding/codecs/ilbc/lsf_to_poly.h"
diff --git a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h
index 9cb0dd9..b278a10 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h
+++ b/modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_ENC_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_INTERPOLATE_TO_POLY_ENC_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  lsf interpolator and conversion from lsf to a coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c b/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c
index 8767e2d..ee8292f 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c
+++ b/modules/audio_coding/codecs/ilbc/lsf_to_lsp.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_to_lsp.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  conversion from lsf to lsp coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h b/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h
index 921101a..6bc6c44 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h
+++ b/modules/audio_coding/codecs/ilbc/lsf_to_lsp.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_LSP_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_LSP_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  conversion from lsf to lsp coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsf_to_poly.c b/modules/audio_coding/codecs/ilbc/lsf_to_poly.c
index 4dbf96d..8ca91d8 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_to_poly.c
+++ b/modules/audio_coding/codecs/ilbc/lsf_to_poly.c
@@ -16,10 +16,12 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/lsf_to_lsp.h"
-#include "modules/audio_coding/codecs/ilbc/get_lsp_poly.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_to_poly.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/get_lsp_poly.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_to_lsp.h"
 
 void WebRtcIlbcfix_Lsf2Poly(
     int16_t *a,     /* (o) predictor coefficients (order = 10) in Q12 */
diff --git a/modules/audio_coding/codecs/ilbc/lsf_to_poly.h b/modules/audio_coding/codecs/ilbc/lsf_to_poly.h
index e551836..f26d3a8 100644
--- a/modules/audio_coding/codecs/ilbc/lsf_to_poly.h
+++ b/modules/audio_coding/codecs/ilbc/lsf_to_poly.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_POLY_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSF_TO_POLY_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  Convert from LSF coefficients to A coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c b/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c
index db11cfe..227f4d4 100644
--- a/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c
+++ b/modules/audio_coding/codecs/ilbc/lsp_to_lsf.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsp_to_lsf.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  conversion from LSP coefficients to LSF coefficients
diff --git a/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h b/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h
index 358786e..c2f4b76 100644
--- a/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h
+++ b/modules/audio_coding/codecs/ilbc/lsp_to_lsf.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSP_TO_LSF_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_LSP_TO_LSF_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  conversion from LSP coefficients to LSF coefficients
diff --git a/modules/audio_coding/codecs/ilbc/my_corr.c b/modules/audio_coding/codecs/ilbc/my_corr.c
index 2f2a058..9b870e0 100644
--- a/modules/audio_coding/codecs/ilbc/my_corr.c
+++ b/modules/audio_coding/codecs/ilbc/my_corr.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/my_corr.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/my_corr.h b/modules/audio_coding/codecs/ilbc/my_corr.h
index 21deea5..c0c2fa4 100644
--- a/modules/audio_coding/codecs/ilbc/my_corr.h
+++ b/modules/audio_coding/codecs/ilbc/my_corr.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_MY_CORR_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_MY_CORR_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * compute cross correlation between sequences
diff --git a/modules/audio_coding/codecs/ilbc/nearest_neighbor.c b/modules/audio_coding/codecs/ilbc/nearest_neighbor.c
index 9d78528..1ecdd96 100644
--- a/modules/audio_coding/codecs/ilbc/nearest_neighbor.c
+++ b/modules/audio_coding/codecs/ilbc/nearest_neighbor.c
@@ -16,7 +16,7 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/nearest_neighbor.h"
 
 void WebRtcIlbcfix_NearestNeighbor(size_t* index,
                                    const size_t* array,
diff --git a/modules/audio_coding/codecs/ilbc/nearest_neighbor.h b/modules/audio_coding/codecs/ilbc/nearest_neighbor.h
index 68b5c59..704cf2a 100644
--- a/modules/audio_coding/codecs/ilbc/nearest_neighbor.h
+++ b/modules/audio_coding/codecs/ilbc/nearest_neighbor.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_NEAREST_NEIGHBOR_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_NEAREST_NEIGHBOR_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * Find index in array such that the array element with said
diff --git a/modules/audio_coding/codecs/ilbc/pack_bits.c b/modules/audio_coding/codecs/ilbc/pack_bits.c
index 507e25e..dd44eb8 100644
--- a/modules/audio_coding/codecs/ilbc/pack_bits.c
+++ b/modules/audio_coding/codecs/ilbc/pack_bits.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/pack_bits.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/poly_to_lsf.c b/modules/audio_coding/codecs/ilbc/poly_to_lsf.c
index 92aa165..7192eaa 100644
--- a/modules/audio_coding/codecs/ilbc/poly_to_lsf.c
+++ b/modules/audio_coding/codecs/ilbc/poly_to_lsf.c
@@ -16,10 +16,11 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsf.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
-#include "modules/audio_coding/codecs/ilbc/poly_to_lsp.h"
 #include "modules/audio_coding/codecs/ilbc/lsp_to_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsp.h"
 
 void WebRtcIlbcfix_Poly2Lsf(
     int16_t *lsf,   /* (o) lsf coefficients (Q13) */
diff --git a/modules/audio_coding/codecs/ilbc/poly_to_lsf.h b/modules/audio_coding/codecs/ilbc/poly_to_lsf.h
index 8a68d07..363e392 100644
--- a/modules/audio_coding/codecs/ilbc/poly_to_lsf.h
+++ b/modules/audio_coding/codecs/ilbc/poly_to_lsf.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSF_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSF_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  conversion from lpc coefficients to lsf coefficients
diff --git a/modules/audio_coding/codecs/ilbc/poly_to_lsp.c b/modules/audio_coding/codecs/ilbc/poly_to_lsp.c
index 88df639..ad0ecd7 100644
--- a/modules/audio_coding/codecs/ilbc/poly_to_lsp.c
+++ b/modules/audio_coding/codecs/ilbc/poly_to_lsp.c
@@ -16,9 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsp.h"
+
 #include "modules/audio_coding/codecs/ilbc/chebyshev.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
 
 /*----------------------------------------------------------------*
  * conversion from lpc coefficients to lsp coefficients
diff --git a/modules/audio_coding/codecs/ilbc/poly_to_lsp.h b/modules/audio_coding/codecs/ilbc/poly_to_lsp.h
index 76378f2..928ee4e 100644
--- a/modules/audio_coding/codecs/ilbc/poly_to_lsp.h
+++ b/modules/audio_coding/codecs/ilbc/poly_to_lsp.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSP_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_POLY_TO_LSP_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * conversion from lpc coefficients to lsp coefficients
diff --git a/modules/audio_coding/codecs/ilbc/refiner.c b/modules/audio_coding/codecs/ilbc/refiner.c
index d8a9bfb..5bdab7a 100644
--- a/modules/audio_coding/codecs/ilbc/refiner.c
+++ b/modules/audio_coding/codecs/ilbc/refiner.c
@@ -16,7 +16,8 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/refiner.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
 #include "modules/audio_coding/codecs/ilbc/enh_upsample.h"
 #include "modules/audio_coding/codecs/ilbc/my_corr.h"
diff --git a/modules/audio_coding/codecs/ilbc/refiner.h b/modules/audio_coding/codecs/ilbc/refiner.h
index 87d0de7..564c9d9 100644
--- a/modules/audio_coding/codecs/ilbc/refiner.h
+++ b/modules/audio_coding/codecs/ilbc/refiner.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_REFINER_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_REFINER_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * find segment starting near idata+estSegPos that has highest
diff --git a/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c b/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c
index df41b28..7343530 100644
--- a/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c
+++ b/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.c
@@ -16,10 +16,12 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h"
+#include "modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h"
+
 #include "modules/audio_coding/codecs/ilbc/bw_expand.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/lsf_interpolate_to_poly_enc.h"
 
 /*----------------------------------------------------------------*
  *  lsf interpolator (subrutine to LPCencode)
diff --git a/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h b/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h
index 317f613..ee53e4b 100644
--- a/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h
+++ b/modules/audio_coding/codecs/ilbc/simple_interpolate_lsf.h
@@ -19,6 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_INTERPOLATE_LSF_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_INTERPOLATE_LSF_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c b/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c
index 09e64ac..fdc4553 100644
--- a/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c
+++ b/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.c
@@ -16,11 +16,13 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/window32_w32.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h"
+
 #include "modules/audio_coding/codecs/ilbc/bw_expand.h"
-#include "modules/audio_coding/codecs/ilbc/poly_to_lsf.h"
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/poly_to_lsf.h"
+#include "modules/audio_coding/codecs/ilbc/window32_w32.h"
 
 /*----------------------------------------------------------------*
  *  lpc analysis (subrutine to LPCencode)
diff --git a/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h b/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h
index 3b0548d..b5c839b 100644
--- a/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h
+++ b/modules/audio_coding/codecs/ilbc/simple_lpc_analysis.h
@@ -19,6 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LPC_ANALYSIS_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LPC_ANALYSIS_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c b/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c
index 90673a2..e7494ce 100644
--- a/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c
+++ b/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  obtain dequantized lsf coefficients from quantization index
diff --git a/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h b/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h
index ee18486..6d97d3d 100644
--- a/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h
+++ b/modules/audio_coding/codecs/ilbc/simple_lsf_dequant.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_DEQUANT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_DEQUANT_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  obtain dequantized lsf coefficients from quantization index
diff --git a/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c b/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c
index 45373a9..1291d14 100644
--- a/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c
+++ b/modules/audio_coding/codecs/ilbc/simple_lsf_quant.c
@@ -16,9 +16,11 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/simple_lsf_quant.h"
+
+#include "modules/audio_coding/codecs/ilbc/constants.h"
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/split_vq.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
 
 /*----------------------------------------------------------------*
  *  lsf quantizer (subrutine to LPCencode)
diff --git a/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h b/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h
index 74fb0be..66b5532 100644
--- a/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h
+++ b/modules/audio_coding/codecs/ilbc/simple_lsf_quant.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_QUANT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SIMPLE_LSF_QUANT_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  lsf quantizer (subrutine to LPCencode)
diff --git a/modules/audio_coding/codecs/ilbc/smooth.c b/modules/audio_coding/codecs/ilbc/smooth.c
index edafb0c..631b2f4 100644
--- a/modules/audio_coding/codecs/ilbc/smooth.c
+++ b/modules/audio_coding/codecs/ilbc/smooth.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/smooth.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/smooth_out_data.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/smooth.h b/modules/audio_coding/codecs/ilbc/smooth.h
index 52e7ff9..c8752be 100644
--- a/modules/audio_coding/codecs/ilbc/smooth.h
+++ b/modules/audio_coding/codecs/ilbc/smooth.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * find the smoothed output data
diff --git a/modules/audio_coding/codecs/ilbc/smooth_out_data.c b/modules/audio_coding/codecs/ilbc/smooth_out_data.c
index 72b3a47..9f952bf 100644
--- a/modules/audio_coding/codecs/ilbc/smooth_out_data.c
+++ b/modules/audio_coding/codecs/ilbc/smooth_out_data.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/smooth_out_data.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "rtc_base/sanitizer.h"
 
 // An s32 + s32 -> s32 addition that's allowed to overflow. (It's still
diff --git a/modules/audio_coding/codecs/ilbc/smooth_out_data.h b/modules/audio_coding/codecs/ilbc/smooth_out_data.h
index df946e3..318e7b0 100644
--- a/modules/audio_coding/codecs/ilbc/smooth_out_data.h
+++ b/modules/audio_coding/codecs/ilbc/smooth_out_data.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_OUT_DATA_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SMOOTH_OUT_DATA_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * help function to WebRtcIlbcfix_Smooth()
diff --git a/modules/audio_coding/codecs/ilbc/sort_sq.c b/modules/audio_coding/codecs/ilbc/sort_sq.c
index dd3ca80..c3a2475 100644
--- a/modules/audio_coding/codecs/ilbc/sort_sq.c
+++ b/modules/audio_coding/codecs/ilbc/sort_sq.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/sort_sq.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/sort_sq.h b/modules/audio_coding/codecs/ilbc/sort_sq.h
index 1fe7fbf..02028da 100644
--- a/modules/audio_coding/codecs/ilbc/sort_sq.h
+++ b/modules/audio_coding/codecs/ilbc/sort_sq.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SORT_SQ_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SORT_SQ_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  scalar quantization
diff --git a/modules/audio_coding/codecs/ilbc/split_vq.c b/modules/audio_coding/codecs/ilbc/split_vq.c
index 2f218ed..c1f04d2 100644
--- a/modules/audio_coding/codecs/ilbc/split_vq.c
+++ b/modules/audio_coding/codecs/ilbc/split_vq.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/split_vq.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 #include "modules/audio_coding/codecs/ilbc/vq3.h"
 #include "modules/audio_coding/codecs/ilbc/vq4.h"
 
diff --git a/modules/audio_coding/codecs/ilbc/split_vq.h b/modules/audio_coding/codecs/ilbc/split_vq.h
index 6bc2db6..e4b02a2 100644
--- a/modules/audio_coding/codecs/ilbc/split_vq.h
+++ b/modules/audio_coding/codecs/ilbc/split_vq.h
@@ -19,7 +19,7 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SPLIT_VQ_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SPLIT_VQ_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  split vector quantization
diff --git a/modules/audio_coding/codecs/ilbc/state_construct.c b/modules/audio_coding/codecs/ilbc/state_construct.c
index 753415b..c58086c 100644
--- a/modules/audio_coding/codecs/ilbc/state_construct.c
+++ b/modules/audio_coding/codecs/ilbc/state_construct.c
@@ -16,8 +16,10 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/state_construct.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  decoding of the start state
diff --git a/modules/audio_coding/codecs/ilbc/state_construct.h b/modules/audio_coding/codecs/ilbc/state_construct.h
index 0dadf48..4c30119 100644
--- a/modules/audio_coding/codecs/ilbc/state_construct.h
+++ b/modules/audio_coding/codecs/ilbc/state_construct.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_CONSTRUCT_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_CONSTRUCT_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 /*----------------------------------------------------------------*
  *  Generate the start state from the quantized indexes
  *---------------------------------------------------------------*/
diff --git a/modules/audio_coding/codecs/ilbc/state_search.c b/modules/audio_coding/codecs/ilbc/state_search.c
index 5e8a2f5..7227ac9 100644
--- a/modules/audio_coding/codecs/ilbc/state_search.c
+++ b/modules/audio_coding/codecs/ilbc/state_search.c
@@ -16,9 +16,11 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
-#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/state_search.h"
+
 #include "modules/audio_coding/codecs/ilbc/abs_quant.h"
+#include "modules/audio_coding/codecs/ilbc/constants.h"
+#include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
  *  encoding of start state
diff --git a/modules/audio_coding/codecs/ilbc/state_search.h b/modules/audio_coding/codecs/ilbc/state_search.h
index 1ad27ce..6469138 100644
--- a/modules/audio_coding/codecs/ilbc/state_search.h
+++ b/modules/audio_coding/codecs/ilbc/state_search.h
@@ -19,6 +19,9 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_SEARCH_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_STATE_SEARCH_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/swap_bytes.c b/modules/audio_coding/codecs/ilbc/swap_bytes.c
index 806cc2a..bbafc1a 100644
--- a/modules/audio_coding/codecs/ilbc/swap_bytes.c
+++ b/modules/audio_coding/codecs/ilbc/swap_bytes.c
@@ -16,7 +16,7 @@
 
 ******************************************************************/
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include "modules/audio_coding/codecs/ilbc/swap_bytes.h"
 
 /*----------------------------------------------------------------*
  * Swap bytes (to simplify operations on Little Endian machines)
diff --git a/modules/audio_coding/codecs/ilbc/swap_bytes.h b/modules/audio_coding/codecs/ilbc/swap_bytes.h
index 381b73a..c59bf30 100644
--- a/modules/audio_coding/codecs/ilbc/swap_bytes.h
+++ b/modules/audio_coding/codecs/ilbc/swap_bytes.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SWAP_BYTES_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_SWAP_BYTES_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * Swap bytes (to simplify operations on Little Endian machines)
diff --git a/modules/audio_coding/codecs/ilbc/unpack_bits.c b/modules/audio_coding/codecs/ilbc/unpack_bits.c
index ad6a7ee..a9a0147 100644
--- a/modules/audio_coding/codecs/ilbc/unpack_bits.c
+++ b/modules/audio_coding/codecs/ilbc/unpack_bits.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/unpack_bits.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/unpack_bits.h b/modules/audio_coding/codecs/ilbc/unpack_bits.h
index 4fd0a80..1a63280 100644
--- a/modules/audio_coding/codecs/ilbc/unpack_bits.h
+++ b/modules/audio_coding/codecs/ilbc/unpack_bits.h
@@ -19,6 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_UNPACK_BITS_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_UNPACK_BITS_H_
 
+#include <stdint.h>
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/vq3.c b/modules/audio_coding/codecs/ilbc/vq3.c
index b63a7a8..d9375fb 100644
--- a/modules/audio_coding/codecs/ilbc/vq3.c
+++ b/modules/audio_coding/codecs/ilbc/vq3.c
@@ -17,6 +17,7 @@
 ******************************************************************/
 
 #include "modules/audio_coding/codecs/ilbc/vq3.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/vq4.c b/modules/audio_coding/codecs/ilbc/vq4.c
index 2522ac2..c9a65ae 100644
--- a/modules/audio_coding/codecs/ilbc/vq4.c
+++ b/modules/audio_coding/codecs/ilbc/vq4.c
@@ -17,6 +17,7 @@
 ******************************************************************/
 
 #include "modules/audio_coding/codecs/ilbc/vq4.h"
+
 #include "modules/audio_coding/codecs/ilbc/constants.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/window32_w32.c b/modules/audio_coding/codecs/ilbc/window32_w32.c
index fe19de6..e82d167 100644
--- a/modules/audio_coding/codecs/ilbc/window32_w32.c
+++ b/modules/audio_coding/codecs/ilbc/window32_w32.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/window32_w32.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/window32_w32.h b/modules/audio_coding/codecs/ilbc/window32_w32.h
index 0cef084..15d72c5 100644
--- a/modules/audio_coding/codecs/ilbc/window32_w32.h
+++ b/modules/audio_coding/codecs/ilbc/window32_w32.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_WINDOW32_W32_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_WINDOW32_W32_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  *  window multiplication
diff --git a/modules/audio_coding/codecs/ilbc/xcorr_coef.c b/modules/audio_coding/codecs/ilbc/xcorr_coef.c
index f6375df..9dc880b 100644
--- a/modules/audio_coding/codecs/ilbc/xcorr_coef.c
+++ b/modules/audio_coding/codecs/ilbc/xcorr_coef.c
@@ -16,6 +16,8 @@
 
 ******************************************************************/
 
+#include "modules/audio_coding/codecs/ilbc/xcorr_coef.h"
+
 #include "modules/audio_coding/codecs/ilbc/defines.h"
 
 /*----------------------------------------------------------------*
diff --git a/modules/audio_coding/codecs/ilbc/xcorr_coef.h b/modules/audio_coding/codecs/ilbc/xcorr_coef.h
index e6c3d3f..3be5a29 100644
--- a/modules/audio_coding/codecs/ilbc/xcorr_coef.h
+++ b/modules/audio_coding/codecs/ilbc/xcorr_coef.h
@@ -19,7 +19,8 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_XCORR_COEF_H_
 #define MODULES_AUDIO_CODING_CODECS_ILBC_MAIN_SOURCE_XCORR_COEF_H_
 
-#include "modules/audio_coding/codecs/ilbc/defines.h"
+#include <stddef.h>
+#include <stdint.h>
 
 /*----------------------------------------------------------------*
  * cross correlation which finds the optimal lag for the
diff --git a/modules/audio_coding/neteq/buffer_level_filter.cc b/modules/audio_coding/neteq/buffer_level_filter.cc
index 7ad0065..5d503e9 100644
--- a/modules/audio_coding/neteq/buffer_level_filter.cc
+++ b/modules/audio_coding/neteq/buffer_level_filter.cc
@@ -45,6 +45,10 @@
       filtered_current_level - (int64_t{time_stretched_samples} * (1 << 8))));
 }
 
+void BufferLevelFilter::SetFilteredBufferLevel(int buffer_size_samples) {
+  filtered_current_level_ = buffer_size_samples * 256;
+}
+
 void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level_ms) {
   if (target_buffer_level_ms <= 20) {
     level_factor_ = 251;
diff --git a/modules/audio_coding/neteq/buffer_level_filter.h b/modules/audio_coding/neteq/buffer_level_filter.h
index bb31856..89fcaf4 100644
--- a/modules/audio_coding/neteq/buffer_level_filter.h
+++ b/modules/audio_coding/neteq/buffer_level_filter.h
@@ -28,6 +28,11 @@
   // bypassing the filter operation).
   virtual void Update(size_t buffer_size_samples, int time_stretched_samples);
 
+  // Set the filtered buffer level to a particular value directly. This should
+  // only be used in case of large changes in buffer size, such as buffer
+  // flushes.
+  virtual void SetFilteredBufferLevel(int buffer_size_samples);
+
   // The target level is used to select the appropriate filter coefficient.
   virtual void SetTargetBufferLevel(int target_buffer_level_ms);
 
diff --git a/modules/audio_coding/neteq/cross_correlation.cc b/modules/audio_coding/neteq/cross_correlation.cc
index 2a03d4a..7ee867a 100644
--- a/modules/audio_coding/neteq/cross_correlation.cc
+++ b/modules/audio_coding/neteq/cross_correlation.cc
@@ -26,31 +26,22 @@
                                   int cross_correlation_step,
                                   int32_t* cross_correlation) {
   // Find the maximum absolute value of sequence_1 and 2.
-  const int16_t max_1 = WebRtcSpl_MaxAbsValueW16(sequence_1, sequence_1_length);
+  const int32_t max_1 =
+      abs(sequence_1[WebRtcSpl_MaxAbsIndexW16(sequence_1, sequence_1_length)]);
   const int sequence_2_shift =
       cross_correlation_step * (static_cast<int>(cross_correlation_length) - 1);
   const int16_t* sequence_2_start =
       sequence_2_shift >= 0 ? sequence_2 : sequence_2 + sequence_2_shift;
   const size_t sequence_2_length =
       sequence_1_length + std::abs(sequence_2_shift);
-  const int16_t max_2 =
-      WebRtcSpl_MaxAbsValueW16(sequence_2_start, sequence_2_length);
+  const int32_t max_2 = abs(sequence_2_start[WebRtcSpl_MaxAbsIndexW16(
+      sequence_2_start, sequence_2_length)]);
 
   // In order to avoid overflow when computing the sum we should scale the
   // samples so that (in_vector_length * max_1 * max_2) will not overflow.
-  // Expected scaling fulfills
-  // 1) sufficient:
-  //    sequence_1_length * (max_1 * max_2 >> scaling) <= 0x7fffffff;
-  // 2) necessary:
-  //    if (scaling > 0)
-  //      sequence_1_length * (max_1 * max_2 >> (scaling - 1)) > 0x7fffffff;
-  // The following calculation fulfills 1) and almost fulfills 2).
-  // There are some corner cases that 2) is not satisfied, e.g.,
-  // max_1 = 17, max_2 = 30848, sequence_1_length = 4095, in such case,
-  // optimal scaling is 0, while the following calculation results in 1.
-  const int32_t factor =
-      (max_1 * max_2) / (std::numeric_limits<int32_t>::max() /
-                         static_cast<int32_t>(sequence_1_length));
+  const int64_t max_value =
+      max_1 * max_2 * static_cast<int64_t>(sequence_1_length);
+  const int32_t factor = max_value >> 31;
   const int scaling = factor == 0 ? 0 : 31 - WebRtcSpl_NormW32(factor);
 
   WebRtcSpl_CrossCorrelation(cross_correlation, sequence_1, sequence_2,
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index 9c0ee96..266e675 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -211,6 +211,7 @@
     int fs_hz,
     bool should_update_stats,
     const PacketArrivedInfo& info) {
+  buffer_flush_ = buffer_flush_ || info.buffer_flush;
   if (info.is_cng_or_dtmf) {
     last_pack_cng_or_dtmf_ = true;
     return absl::nullopt;
@@ -238,7 +239,12 @@
     timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
   }
 
-  buffer_level_filter_->Update(buffer_size_samples, time_stretched_samples);
+  if (buffer_flush_) {
+    buffer_level_filter_->SetFilteredBufferLevel(buffer_size_samples);
+    buffer_flush_ = false;
+  } else {
+    buffer_level_filter_->Update(buffer_size_samples, time_stretched_samples);
+  }
   prev_time_scale_ = false;
   time_stretched_cn_samples_ = 0;
 }
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index 08feba6..8be4511 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -188,6 +188,7 @@
   int num_consecutive_expands_ = 0;
   int time_stretched_cn_samples_ = 0;
   bool last_pack_cng_or_dtmf_ = true;
+  bool buffer_flush_ = false;
   FieldTrialParameter<bool> estimate_dtx_delay_;
   FieldTrialParameter<bool> time_stretch_cn_;
   FieldTrialConstrained<int> target_level_window_ms_;
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index 33eeb96..aec80cf 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -158,7 +158,8 @@
   }
 
   const int expected_iat_ms =
-      1000 * static_cast<int32_t>(timestamp - last_timestamp_) / sample_rate_hz;
+      1000ll * static_cast<int32_t>(timestamp - last_timestamp_) /
+      sample_rate_hz;
   const int iat_ms = packet_iat_stopwatch_->ElapsedMs();
   const int iat_delay_ms = iat_ms - expected_iat_ms;
   int relative_delay;
diff --git a/modules/audio_coding/neteq/merge.cc b/modules/audio_coding/neteq/merge.cc
index f1f2cc9..5bf239b 100644
--- a/modules/audio_coding/neteq/merge.cc
+++ b/modules/audio_coding/neteq/merge.cc
@@ -50,6 +50,9 @@
   assert(fs_hz_ == 8000 || fs_hz_ == 16000 || fs_hz_ == 32000 ||
          fs_hz_ == 48000);
   assert(fs_hz_ <= kMaxSampleRate);  // Should not be possible.
+  if (input_length == 0) {
+    return 0;
+  }
 
   size_t old_length;
   size_t expand_period;
diff --git a/modules/audio_coding/neteq/mock/mock_neteq_controller.h b/modules/audio_coding/neteq/mock/mock_neteq_controller.h
index fdfdbb4..6d88e09 100644
--- a/modules/audio_coding/neteq/mock/mock_neteq_controller.h
+++ b/modules/audio_coding/neteq/mock/mock_neteq_controller.h
@@ -48,6 +48,7 @@
                bool should_update_stats,
                const PacketArrivedInfo& info),
               (override));
+  MOCK_METHOD(void, NotifyMutedState, (), (override));
   MOCK_METHOD(bool, PeakFound, (), (const, override));
   MOCK_METHOD(int, GetFilteredBufferLevel, (), (const, override));
   MOCK_METHOD(void, set_sample_memory, (int32_t value), (override));
diff --git a/modules/audio_coding/neteq/mock/mock_packet_buffer.h b/modules/audio_coding/neteq/mock/mock_packet_buffer.h
index e466ea6..48357ea 100644
--- a/modules/audio_coding/neteq/mock/mock_packet_buffer.h
+++ b/modules/audio_coding/neteq/mock/mock_packet_buffer.h
@@ -22,11 +22,23 @@
       : PacketBuffer(max_number_of_packets, tick_timer) {}
   ~MockPacketBuffer() override { Die(); }
   MOCK_METHOD(void, Die, ());
-  MOCK_METHOD(void, Flush, (), (override));
+  MOCK_METHOD(void, Flush, (StatisticsCalculator * stats), (override));
+  MOCK_METHOD(void,
+              PartialFlush,
+              (int target_level_ms,
+               size_t sample_rate,
+               size_t last_decoded_length,
+               StatisticsCalculator* stats),
+              (override));
   MOCK_METHOD(bool, Empty, (), (const, override));
   MOCK_METHOD(int,
               InsertPacket,
-              (Packet && packet, StatisticsCalculator* stats),
+              (Packet && packet,
+               StatisticsCalculator* stats,
+               size_t last_decoded_length,
+               size_t sample_rate,
+               int target_level_ms,
+               const DecoderDatabase& decoder_database),
               (override));
   MOCK_METHOD(int,
               InsertPacketList,
@@ -34,7 +46,10 @@
                const DecoderDatabase& decoder_database,
                absl::optional<uint8_t>* current_rtp_payload_type,
                absl::optional<uint8_t>* current_cng_rtp_payload_type,
-               StatisticsCalculator* stats),
+               StatisticsCalculator* stats,
+               size_t last_decoded_length,
+               size_t sample_rate,
+               int target_level_ms),
               (override));
   MOCK_METHOD(int,
               NextTimestamp,
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index f8d5d9d..9ec7bd5 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -499,7 +499,7 @@
 void NetEqImpl::FlushBuffers() {
   MutexLock lock(&mutex_);
   RTC_LOG(LS_VERBOSE) << "FlushBuffers";
-  packet_buffer_->Flush();
+  packet_buffer_->Flush(stats_.get());
   assert(sync_buffer_.get());
   assert(expand_.get());
   sync_buffer_->Flush();
@@ -607,7 +607,7 @@
     // the packet has been successfully inserted into the packet buffer.
 
     // Flush the packet buffer and DTMF buffer.
-    packet_buffer_->Flush();
+    packet_buffer_->Flush(stats_.get());
     dtmf_buffer_->Flush();
 
     // Update audio buffer timestamp.
@@ -746,13 +746,23 @@
   }
 
   // Insert packets in buffer.
+  const int target_level_ms = controller_->TargetLevelMs();
   const int ret = packet_buffer_->InsertPacketList(
       &parsed_packet_list, *decoder_database_, &current_rtp_payload_type_,
-      &current_cng_rtp_payload_type_, stats_.get());
+      &current_cng_rtp_payload_type_, stats_.get(), decoder_frame_length_,
+      last_output_sample_rate_hz_, target_level_ms);
+  bool buffer_flush_occured = false;
   if (ret == PacketBuffer::kFlushed) {
     // Reset DSP timestamp etc. if packet buffer flushed.
     new_codec_ = true;
     update_sample_rate_and_channels = true;
+    buffer_flush_occured = true;
+  } else if (ret == PacketBuffer::kPartialFlush) {
+    // Forward sync buffer timestamp
+    timestamp_ = packet_buffer_->PeekNextPacket()->timestamp;
+    sync_buffer_->IncreaseEndTimestamp(timestamp_ -
+                                       sync_buffer_->end_timestamp());
+    buffer_flush_occured = true;
   } else if (ret != PacketBuffer::kOK) {
     return kOtherError;
   }
@@ -810,6 +820,7 @@
   info.main_timestamp = main_timestamp;
   info.main_sequence_number = main_sequence_number;
   info.is_dtx = is_dtx;
+  info.buffer_flush = buffer_flush_occured;
   // Only update statistics if incoming packet is not older than last played
   // out packet or RTX handling is enabled, and if new codec flag is not
   // set.
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 28dd8f0..c66a0e2 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -328,8 +328,8 @@
   // Expectations for packet buffer.
   EXPECT_CALL(*mock_packet_buffer_, Empty())
       .WillOnce(Return(false));  // Called once after first packet is inserted.
-  EXPECT_CALL(*mock_packet_buffer_, Flush()).Times(1);
-  EXPECT_CALL(*mock_packet_buffer_, InsertPacketList(_, _, _, _, _))
+  EXPECT_CALL(*mock_packet_buffer_, Flush(_)).Times(1);
+  EXPECT_CALL(*mock_packet_buffer_, InsertPacketList(_, _, _, _, _, _, _, _))
       .Times(2)
       .WillRepeatedly(DoAll(SetArgPointee<2>(kPayloadType),
                             WithArg<0>(Invoke(DeletePacketsAndReturnOk))));
diff --git a/modules/audio_coding/neteq/packet_buffer.cc b/modules/audio_coding/neteq/packet_buffer.cc
index 059308f..86ae847 100644
--- a/modules/audio_coding/neteq/packet_buffer.cc
+++ b/modules/audio_coding/neteq/packet_buffer.cc
@@ -25,8 +25,10 @@
 #include "modules/audio_coding/neteq/decoder_database.h"
 #include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/experiments/struct_parameters_parser.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 namespace {
@@ -61,27 +63,80 @@
   }
 }
 
+absl::optional<SmartFlushingConfig> GetSmartflushingConfig() {
+  absl::optional<SmartFlushingConfig> result;
+  std::string field_trial_string =
+      field_trial::FindFullName("WebRTC-Audio-NetEqSmartFlushing");
+  result = SmartFlushingConfig();
+  bool enabled = false;
+  auto parser = StructParametersParser::Create(
+      "enabled", &enabled, "target_level_threshold_ms",
+      &result->target_level_threshold_ms, "target_level_multiplier",
+      &result->target_level_multiplier);
+  parser->Parse(field_trial_string);
+  if (!enabled) {
+    return absl::nullopt;
+  }
+  RTC_LOG(LS_INFO) << "Using smart flushing, target_level_threshold_ms: "
+                   << result->target_level_threshold_ms
+                   << ", target_level_multiplier: "
+                   << result->target_level_multiplier;
+  return result;
+}
+
 }  // namespace
 
 PacketBuffer::PacketBuffer(size_t max_number_of_packets,
                            const TickTimer* tick_timer)
-    : max_number_of_packets_(max_number_of_packets), tick_timer_(tick_timer) {}
+    : smart_flushing_config_(GetSmartflushingConfig()),
+      max_number_of_packets_(max_number_of_packets),
+      tick_timer_(tick_timer) {}
 
 // Destructor. All packets in the buffer will be destroyed.
 PacketBuffer::~PacketBuffer() {
-  Flush();
+  buffer_.clear();
 }
 
 // Flush the buffer. All packets in the buffer will be destroyed.
-void PacketBuffer::Flush() {
+void PacketBuffer::Flush(StatisticsCalculator* stats) {
+  for (auto& p : buffer_) {
+    LogPacketDiscarded(p.priority.codec_level, stats);
+  }
   buffer_.clear();
+  stats->FlushedPacketBuffer();
+}
+
+void PacketBuffer::PartialFlush(int target_level_ms,
+                                size_t sample_rate,
+                                size_t last_decoded_length,
+                                StatisticsCalculator* stats) {
+  // Make sure that at least half the packet buffer capacity will be available
+  // after the flush. This is done to avoid getting stuck if the target level is
+  // very high.
+  int target_level_samples =
+      std::min(target_level_ms * sample_rate / 1000,
+               max_number_of_packets_ * last_decoded_length / 2);
+  // We should avoid flushing to very low levels.
+  target_level_samples = std::max(
+      target_level_samples, smart_flushing_config_->target_level_threshold_ms);
+  while (GetSpanSamples(last_decoded_length, sample_rate, true) >
+             static_cast<size_t>(target_level_samples) ||
+         buffer_.size() > max_number_of_packets_ / 2) {
+    LogPacketDiscarded(PeekNextPacket()->priority.codec_level, stats);
+    buffer_.pop_front();
+  }
 }
 
 bool PacketBuffer::Empty() const {
   return buffer_.empty();
 }
 
-int PacketBuffer::InsertPacket(Packet&& packet, StatisticsCalculator* stats) {
+int PacketBuffer::InsertPacket(Packet&& packet,
+                               StatisticsCalculator* stats,
+                               size_t last_decoded_length,
+                               size_t sample_rate,
+                               int target_level_ms,
+                               const DecoderDatabase& decoder_database) {
   if (packet.empty()) {
     RTC_LOG(LS_WARNING) << "InsertPacket invalid packet";
     return kInvalidPacket;
@@ -94,12 +149,32 @@
 
   packet.waiting_time = tick_timer_->GetNewStopwatch();
 
-  if (buffer_.size() >= max_number_of_packets_) {
-    // Buffer is full. Flush it.
-    Flush();
-    stats->FlushedPacketBuffer();
-    RTC_LOG(LS_WARNING) << "Packet buffer flushed";
-    return_val = kFlushed;
+  // Perform a smart flush if the buffer size exceeds a multiple of the target
+  // level.
+  const size_t span_threshold =
+      smart_flushing_config_
+          ? smart_flushing_config_->target_level_multiplier *
+                std::max(smart_flushing_config_->target_level_threshold_ms,
+                         target_level_ms) *
+                sample_rate / 1000
+          : 0;
+  const bool smart_flush =
+      smart_flushing_config_.has_value() &&
+      GetSpanSamples(last_decoded_length, sample_rate, true) >= span_threshold;
+  if (buffer_.size() >= max_number_of_packets_ || smart_flush) {
+    size_t buffer_size_before_flush = buffer_.size();
+    if (smart_flushing_config_.has_value()) {
+      // Flush down to the target level.
+      PartialFlush(target_level_ms, sample_rate, last_decoded_length, stats);
+      return_val = kPartialFlush;
+    } else {
+      // Buffer is full.
+      Flush(stats);
+      return_val = kFlushed;
+    }
+    RTC_LOG(LS_WARNING) << "Packet buffer flushed, "
+                        << (buffer_size_before_flush - buffer_.size())
+                        << " packets discarded.";
   }
 
   // Get an iterator pointing to the place in the buffer where the new packet
@@ -134,7 +209,10 @@
     const DecoderDatabase& decoder_database,
     absl::optional<uint8_t>* current_rtp_payload_type,
     absl::optional<uint8_t>* current_cng_rtp_payload_type,
-    StatisticsCalculator* stats) {
+    StatisticsCalculator* stats,
+    size_t last_decoded_length,
+    size_t sample_rate,
+    int target_level_ms) {
   RTC_DCHECK(stats);
   bool flushed = false;
   for (auto& packet : *packet_list) {
@@ -143,7 +221,7 @@
           **current_cng_rtp_payload_type != packet.payload_type) {
         // New CNG payload type implies new codec type.
         *current_rtp_payload_type = absl::nullopt;
-        Flush();
+        Flush(stats);
         flushed = true;
       }
       *current_cng_rtp_payload_type = packet.payload_type;
@@ -156,12 +234,14 @@
                              **current_cng_rtp_payload_type,
                              decoder_database))) {
         *current_cng_rtp_payload_type = absl::nullopt;
-        Flush();
+        Flush(stats);
         flushed = true;
       }
       *current_rtp_payload_type = packet.payload_type;
     }
-    int return_val = InsertPacket(std::move(packet), stats);
+    int return_val =
+        InsertPacket(std::move(packet), stats, last_decoded_length, sample_rate,
+                     target_level_ms, decoder_database);
     if (return_val == kFlushed) {
       // The buffer flushed, but this is not an error. We can still continue.
       flushed = true;
diff --git a/modules/audio_coding/neteq/packet_buffer.h b/modules/audio_coding/neteq/packet_buffer.h
index c00db29..cd2adf7 100644
--- a/modules/audio_coding/neteq/packet_buffer.h
+++ b/modules/audio_coding/neteq/packet_buffer.h
@@ -22,6 +22,14 @@
 class DecoderDatabase;
 class StatisticsCalculator;
 class TickTimer;
+struct SmartFlushingConfig {
+  // When calculating the flushing threshold, the maximum between the target
+  // level and this value is used.
+  int target_level_threshold_ms = 500;
+  // A smart flush is triggered when the packet buffer contains a multiple of
+  // the target level.
+  int target_level_multiplier = 3;
+};
 
 // This is the actual buffer holding the packets before decoding.
 class PacketBuffer {
@@ -29,6 +37,7 @@
   enum BufferReturnCodes {
     kOK = 0,
     kFlushed,
+    kPartialFlush,
     kNotFound,
     kBufferEmpty,
     kInvalidPacket,
@@ -43,7 +52,13 @@
   virtual ~PacketBuffer();
 
   // Flushes the buffer and deletes all packets in it.
-  virtual void Flush();
+  virtual void Flush(StatisticsCalculator* stats);
+
+  // Partial flush. Flush packets but leave some packets behind.
+  virtual void PartialFlush(int target_level_ms,
+                            size_t sample_rate,
+                            size_t last_decoded_length,
+                            StatisticsCalculator* stats);
 
   // Returns true for an empty buffer.
   virtual bool Empty() const;
@@ -52,7 +67,12 @@
   // the packet object.
   // Returns PacketBuffer::kOK on success, PacketBuffer::kFlushed if the buffer
   // was flushed due to overfilling.
-  virtual int InsertPacket(Packet&& packet, StatisticsCalculator* stats);
+  virtual int InsertPacket(Packet&& packet,
+                           StatisticsCalculator* stats,
+                           size_t last_decoded_length,
+                           size_t sample_rate,
+                           int target_level_ms,
+                           const DecoderDatabase& decoder_database);
 
   // Inserts a list of packets into the buffer. The buffer will take over
   // ownership of the packet objects.
@@ -67,7 +87,10 @@
       const DecoderDatabase& decoder_database,
       absl::optional<uint8_t>* current_rtp_payload_type,
       absl::optional<uint8_t>* current_cng_rtp_payload_type,
-      StatisticsCalculator* stats);
+      StatisticsCalculator* stats,
+      size_t last_decoded_length,
+      size_t sample_rate,
+      int target_level_ms);
 
   // Gets the timestamp for the first packet in the buffer and writes it to the
   // output variable |next_timestamp|.
@@ -146,6 +169,7 @@
   }
 
  private:
+  absl::optional<SmartFlushingConfig> smart_flushing_config_;
   size_t max_number_of_packets_;
   PacketList buffer_;
   const TickTimer* tick_timer_;
diff --git a/modules/audio_coding/neteq/packet_buffer_unittest.cc b/modules/audio_coding/neteq/packet_buffer_unittest.cc
index 40e7d53..4286006 100644
--- a/modules/audio_coding/neteq/packet_buffer_unittest.cc
+++ b/modules/audio_coding/neteq/packet_buffer_unittest.cc
@@ -19,6 +19,7 @@
 #include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
 #include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
 #include "modules/audio_coding/neteq/packet.h"
+#include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
@@ -117,10 +118,16 @@
   PacketBuffer buffer(10, &tick_timer);  // 10 packets.
   PacketGenerator gen(17u, 4711u, 0, 10);
   StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
 
   const int payload_len = 100;
   const Packet packet = gen.NextPacket(payload_len, nullptr);
-  EXPECT_EQ(0, buffer.InsertPacket(packet.Clone(), &mock_stats));
+  EXPECT_EQ(0, buffer.InsertPacket(/*packet=*/packet.Clone(),
+                                   /*stats=*/&mock_stats,
+                                   /*last_decoded_length=*/payload_len,
+                                   /*sample_rate=*/10000,
+                                   /*target_level_ms=*/60,
+                                   /*decoder_database=*/decoder_database));
   uint32_t next_ts;
   EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
   EXPECT_EQ(4711u, next_ts);
@@ -128,6 +135,7 @@
   EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
   const Packet* next_packet = buffer.PeekNextPacket();
   EXPECT_EQ(packet, *next_packet);  // Compare contents.
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 
   // Do not explicitly flush buffer or delete packet to test that it is deleted
   // with the buffer. (Tested with Valgrind or similar tool.)
@@ -140,20 +148,28 @@
   PacketGenerator gen(0, 0, 0, 10);
   const int payload_len = 10;
   StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
 
   // Insert 10 small packets; should be ok.
   for (int i = 0; i < 10; ++i) {
     EXPECT_EQ(
         PacketBuffer::kOK,
-        buffer.InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats));
+        buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
+                            /*stats=*/&mock_stats,
+                            /*last_decoded_length=*/payload_len,
+                            /*sample_rate=*/1000,
+                            /*target_level_ms=*/60,
+                            /*decoder_database=*/decoder_database));
   }
   EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
   EXPECT_FALSE(buffer.Empty());
 
-  buffer.Flush();
+  EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
+  buffer.Flush(&mock_stats);
   // Buffer should delete the payloads itself.
   EXPECT_EQ(0u, buffer.NumPacketsInBuffer());
   EXPECT_TRUE(buffer.Empty());
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
 // Test to fill the buffer over the limits, and verify that it flushes.
@@ -162,6 +178,7 @@
   PacketBuffer buffer(10, &tick_timer);  // 10 packets.
   PacketGenerator gen(0, 0, 0, 10);
   StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
 
   // Insert 10 small packets; should be ok.
   const int payload_len = 10;
@@ -169,7 +186,99 @@
   for (i = 0; i < 10; ++i) {
     EXPECT_EQ(
         PacketBuffer::kOK,
-        buffer.InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats));
+        buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
+                            /*stats=*/&mock_stats,
+                            /*last_decoded_length=*/payload_len,
+                            /*sample_rate=*/1000,
+                            /*target_level_ms=*/60,
+                            /*decoder_database=*/decoder_database));
+  }
+  EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
+  uint32_t next_ts;
+  EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
+  EXPECT_EQ(0u, next_ts);  // Expect first inserted packet to be first in line.
+
+  EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
+  const Packet packet = gen.NextPacket(payload_len, nullptr);
+  // Insert 11th packet; should flush the buffer and insert it after flushing.
+  EXPECT_EQ(PacketBuffer::kFlushed,
+            buffer.InsertPacket(/*packet=*/packet.Clone(),
+                                /*stats=*/&mock_stats,
+                                /*last_decoded_length=*/payload_len,
+                                /*sample_rate=*/1000,
+                                /*target_level_ms=*/60,
+                                /*decoder_database=*/decoder_database));
+  EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
+  EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
+  // Expect last inserted packet to be first in line.
+  EXPECT_EQ(packet.timestamp, next_ts);
+
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
+}
+
+// Test a partial buffer flush.
+TEST(PacketBuffer, PartialFlush) {
+  // Use a field trial to configure smart flushing.
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-Audio-NetEqSmartFlushing/enabled:true,"
+      "target_level_threshold_ms:0,target_level_multiplier:2/");
+  TickTimer tick_timer;
+  PacketBuffer buffer(10, &tick_timer);  // 10 packets.
+  PacketGenerator gen(0, 0, 0, 10);
+  const int payload_len = 10;
+  StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
+
+  // Insert 10 small packets; should be ok.
+  for (int i = 0; i < 10; ++i) {
+    EXPECT_EQ(
+        PacketBuffer::kOK,
+        buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
+                            /*stats=*/&mock_stats,
+                            /*last_decoded_length=*/payload_len,
+                            /*sample_rate=*/1000,
+                            /*target_level_ms=*/100,
+                            /*decoder_database=*/decoder_database));
+  }
+  EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
+  EXPECT_FALSE(buffer.Empty());
+
+  EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(7);
+  buffer.PartialFlush(/*target_level_ms=*/30,
+                      /*sample_rate=*/1000,
+                      /*last_decoded_length=*/payload_len,
+                      /*stats=*/&mock_stats);
+  // There should still be some packets left in the buffer.
+  EXPECT_EQ(3u, buffer.NumPacketsInBuffer());
+  EXPECT_FALSE(buffer.Empty());
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
+}
+
+// Test to fill the buffer over the limits, and verify that the smart flush
+// functionality works as expected.
+TEST(PacketBuffer, SmartFlushOverfillBuffer) {
+  // Use a field trial to configure smart flushing.
+  test::ScopedFieldTrials field_trials(
+      "WebRTC-Audio-NetEqSmartFlushing/enabled:true,"
+      "target_level_threshold_ms:0,target_level_multiplier:2/");
+  TickTimer tick_timer;
+  PacketBuffer buffer(10, &tick_timer);  // 10 packets.
+  PacketGenerator gen(0, 0, 0, 10);
+  StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
+
+  // Insert 10 small packets; should be ok.
+  const int payload_len = 10;
+  int i;
+  for (i = 0; i < 10; ++i) {
+    EXPECT_EQ(
+        PacketBuffer::kOK,
+        buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
+                            /*stats=*/&mock_stats,
+                            /*last_decoded_length=*/payload_len,
+                            /*sample_rate=*/1000,
+                            /*target_level_ms=*/100,
+                            /*decoder_database=*/decoder_database));
   }
   EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
   uint32_t next_ts;
@@ -177,16 +286,18 @@
   EXPECT_EQ(0u, next_ts);  // Expect first inserted packet to be first in line.
 
   const Packet packet = gen.NextPacket(payload_len, nullptr);
-  // Insert 11th packet; should flush the buffer and insert it after flushing.
-  EXPECT_EQ(PacketBuffer::kFlushed,
-            buffer.InsertPacket(packet.Clone(), &mock_stats));
-  EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
-  EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
-  // Expect last inserted packet to be first in line.
-  EXPECT_EQ(packet.timestamp, next_ts);
-
-  // Flush buffer to delete all packets.
-  buffer.Flush();
+  EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(6);
+  // Insert 11th packet; should cause a partial flush and insert the packet
+  // after flushing.
+  EXPECT_EQ(PacketBuffer::kPartialFlush,
+            buffer.InsertPacket(/*packet=*/packet.Clone(),
+                                /*stats=*/&mock_stats,
+                                /*last_decoded_length=*/payload_len,
+                                /*sample_rate=*/1000,
+                                /*target_level_ms=*/40,
+                                /*decoder_database=*/decoder_database));
+  EXPECT_EQ(5u, buffer.NumPacketsInBuffer());
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
 // Test inserting a list of packets.
@@ -213,16 +324,21 @@
 
   absl::optional<uint8_t> current_pt;
   absl::optional<uint8_t> current_cng_pt;
-  EXPECT_EQ(PacketBuffer::kOK,
-            buffer.InsertPacketList(&list, decoder_database, &current_pt,
-                                    &current_cng_pt, &mock_stats));
+  EXPECT_EQ(
+      PacketBuffer::kOK,
+      buffer.InsertPacketList(/*packet_list=*/&list,
+                              /*decoder_database=*/decoder_database,
+                              /*current_rtp_payload_type=*/&current_pt,
+                              /*current_cng_rtp_payload_type=*/&current_cng_pt,
+                              /*stats=*/&mock_stats,
+                              /*last_decoded_length=*/payload_len,
+                              /*sample_rate=*/1000,
+                              /*target_level_ms=*/30));
   EXPECT_TRUE(list.empty());  // The PacketBuffer should have depleted the list.
   EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
   EXPECT_EQ(0, current_pt);  // Current payload type changed to 0.
   EXPECT_EQ(absl::nullopt, current_cng_pt);  // CNG payload type not changed.
 
-  buffer.Flush();  // Clean up.
-
   EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
@@ -262,16 +378,22 @@
 
   absl::optional<uint8_t> current_pt;
   absl::optional<uint8_t> current_cng_pt;
-  EXPECT_EQ(PacketBuffer::kFlushed,
-            buffer.InsertPacketList(&list, decoder_database, &current_pt,
-                                    &current_cng_pt, &mock_stats));
+  EXPECT_CALL(mock_stats, PacketsDiscarded(1)).Times(10);
+  EXPECT_EQ(
+      PacketBuffer::kFlushed,
+      buffer.InsertPacketList(/*packet_list=*/&list,
+                              /*decoder_database=*/decoder_database,
+                              /*current_rtp_payload_type=*/&current_pt,
+                              /*current_cng_rtp_payload_type=*/&current_cng_pt,
+                              /*stats=*/&mock_stats,
+                              /*last_decoded_length=*/payload_len,
+                              /*sample_rate=*/1000,
+                              /*target_level_ms=*/30));
   EXPECT_TRUE(list.empty());  // The PacketBuffer should have depleted the list.
   EXPECT_EQ(1u, buffer.NumPacketsInBuffer());  // Only the last packet.
   EXPECT_EQ(1, current_pt);  // Current payload type changed to 1.
   EXPECT_EQ(absl::nullopt, current_cng_pt);  // CNG payload type not changed.
 
-  buffer.Flush();  // Clean up.
-
   EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
@@ -293,6 +415,7 @@
       {0x0005, 0x0000001E, 0, true, -1},  {0x0005, 0x00000014, 1, false, -1},
       {0x0006, 0x00000028, 0, true, 8},   {0x0006, 0x0000001E, 1, false, -1},
   };
+  MockDecoderDatabase decoder_database;
 
   const size_t kExpectPacketsInBuffer = 9;
 
@@ -321,7 +444,12 @@
     }
     EXPECT_CALL(check, Call(i));
     EXPECT_EQ(PacketBuffer::kOK,
-              buffer.InsertPacket(packet.Clone(), &mock_stats));
+              buffer.InsertPacket(/*packet=*/packet.Clone(),
+                                  /*stats=*/&mock_stats,
+                                  /*last_decoded_length=*/kPayloadLength,
+                                  /*sample_rate=*/1000,
+                                  /*target_level_ms=*/60,
+                                  /*decoder_database=*/decoder_database));
     if (packet_facts[i].extract_order >= 0) {
       expect_order[packet_facts[i].extract_order] = std::move(packet);
     }
@@ -335,6 +463,7 @@
     EXPECT_EQ(packet, expect_order[i]);  // Compare contents.
   }
   EXPECT_TRUE(buffer.Empty());
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
 TEST(PacketBuffer, DiscardPackets) {
@@ -347,11 +476,17 @@
   PacketList list;
   const int payload_len = 10;
   StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
 
   constexpr int kTotalPackets = 10;
   // Insert 10 small packets.
   for (int i = 0; i < kTotalPackets; ++i) {
-    buffer.InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats);
+    buffer.InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
+                        /*stats=*/&mock_stats,
+                        /*last_decoded_length=*/payload_len,
+                        /*sample_rate=*/1000,
+                        /*target_level_ms=*/60,
+                        /*decoder_database=*/decoder_database);
   }
   EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
 
@@ -399,6 +534,7 @@
                               &mock_stats);
 
   EXPECT_TRUE(buffer.Empty());
+  EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
 TEST(PacketBuffer, Reordering) {
@@ -434,9 +570,16 @@
 
   StrictMock<MockStatisticsCalculator> mock_stats;
 
-  EXPECT_EQ(PacketBuffer::kOK,
-            buffer.InsertPacketList(&list, decoder_database, &current_pt,
-                                    &current_cng_pt, &mock_stats));
+  EXPECT_EQ(
+      PacketBuffer::kOK,
+      buffer.InsertPacketList(/*packet_list=*/&list,
+                              /*decoder_database=*/decoder_database,
+                              /*current_rtp_payload_type=*/&current_pt,
+                              /*current_cng_rtp_payload_type=*/&current_cng_pt,
+                              /*stats=*/&mock_stats,
+                              /*last_decoded_length=*/payload_len,
+                              /*sample_rate=*/1000,
+                              /*target_level_ms=*/30));
   EXPECT_EQ(10u, buffer.NumPacketsInBuffer());
 
   // Extract them and make sure that come out in the right order.
@@ -483,9 +626,16 @@
 
   StrictMock<MockStatisticsCalculator> mock_stats;
 
-  EXPECT_EQ(PacketBuffer::kOK,
-            buffer.InsertPacketList(&list, decoder_database, &current_pt,
-                                    &current_cng_pt, &mock_stats));
+  EXPECT_EQ(
+      PacketBuffer::kOK,
+      buffer.InsertPacketList(/*packet_list=*/&list,
+                              /*decoder_database=*/decoder_database,
+                              /*current_rtp_payload_type=*/&current_pt,
+                              /*current_cng_rtp_payload_type=*/&current_cng_pt,
+                              /*stats=*/&mock_stats,
+                              /*last_decoded_length=*/kPayloadLen,
+                              /*sample_rate=*/1000,
+                              /*target_level_ms=*/30));
   EXPECT_TRUE(list.empty());
   EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
   ASSERT_TRUE(buffer.PeekNextPacket());
@@ -501,9 +651,17 @@
   }
   // Expect the buffer to flush out the CNG packet, since it does not match the
   // new speech sample rate.
-  EXPECT_EQ(PacketBuffer::kFlushed,
-            buffer.InsertPacketList(&list, decoder_database, &current_pt,
-                                    &current_cng_pt, &mock_stats));
+  EXPECT_CALL(mock_stats, PacketsDiscarded(1));
+  EXPECT_EQ(
+      PacketBuffer::kFlushed,
+      buffer.InsertPacketList(/*packet_list=*/&list,
+                              /*decoder_database=*/decoder_database,
+                              /*current_rtp_payload_type=*/&current_pt,
+                              /*current_cng_rtp_payload_type=*/&current_cng_pt,
+                              /*stats=*/&mock_stats,
+                              /*last_decoded_length=*/kPayloadLen,
+                              /*sample_rate=*/1000,
+                              /*target_level_ms=*/30));
   EXPECT_TRUE(list.empty());
   EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
   ASSERT_TRUE(buffer.PeekNextPacket());
@@ -512,7 +670,6 @@
   EXPECT_EQ(kSpeechPt, current_pt);          // Current payload type set.
   EXPECT_EQ(absl::nullopt, current_cng_pt);  // CNG payload type reset.
 
-  buffer.Flush();                        // Clean up.
   EXPECT_CALL(decoder_database, Die());  // Called when object is deleted.
 }
 
@@ -524,13 +681,19 @@
   PacketGenerator gen(start_seq_no, start_ts, 0, ts_increment);
   TickTimer tick_timer;
   StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
 
   PacketBuffer* buffer = new PacketBuffer(100, &tick_timer);  // 100 packets.
   {
     Packet packet = gen.NextPacket(payload_len, nullptr);
     packet.payload.Clear();
     EXPECT_EQ(PacketBuffer::kInvalidPacket,
-              buffer->InsertPacket(std::move(packet), &mock_stats));
+              buffer->InsertPacket(/*packet=*/std::move(packet),
+                                   /*stats=*/&mock_stats,
+                                   /*last_decoded_length=*/payload_len,
+                                   /*sample_rate=*/1000,
+                                   /*target_level_ms=*/60,
+                                   /*decoder_database=*/decoder_database));
   }
   // Buffer should still be empty. Test all empty-checks.
   uint32_t temp_ts;
@@ -548,7 +711,12 @@
   // Insert one packet to make the buffer non-empty.
   EXPECT_EQ(
       PacketBuffer::kOK,
-      buffer->InsertPacket(gen.NextPacket(payload_len, nullptr), &mock_stats));
+      buffer->InsertPacket(/*packet=*/gen.NextPacket(payload_len, nullptr),
+                           /*stats=*/&mock_stats,
+                           /*last_decoded_length=*/payload_len,
+                           /*sample_rate=*/1000,
+                           /*target_level_ms=*/60,
+                           /*decoder_database=*/decoder_database));
   EXPECT_EQ(PacketBuffer::kInvalidPointer, buffer->NextTimestamp(NULL));
   EXPECT_EQ(PacketBuffer::kInvalidPointer,
             buffer->NextHigherTimestamp(0, NULL));
@@ -566,7 +734,6 @@
     list.push_back(std::move(packet));
   }
   list.push_back(gen.NextPacket(payload_len, nullptr));  // Valid packet.
-  MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
   const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
@@ -574,9 +741,16 @@
       .WillRepeatedly(Return(&info));
   absl::optional<uint8_t> current_pt;
   absl::optional<uint8_t> current_cng_pt;
-  EXPECT_EQ(PacketBuffer::kInvalidPacket,
-            buffer->InsertPacketList(&list, decoder_database, &current_pt,
-                                     &current_cng_pt, &mock_stats));
+  EXPECT_EQ(
+      PacketBuffer::kInvalidPacket,
+      buffer->InsertPacketList(/*packet_list=*/&list,
+                               /*decoder_database=*/decoder_database,
+                               /*current_rtp_payload_type=*/&current_pt,
+                               /*current_cng_rtp_payload_type=*/&current_cng_pt,
+                               /*stats=*/&mock_stats,
+                               /*last_decoded_length=*/payload_len,
+                               /*sample_rate=*/1000,
+                               /*target_level_ms=*/30));
   EXPECT_TRUE(list.empty());  // The PacketBuffer should have depleted the list.
   EXPECT_EQ(1u, buffer->NumPacketsInBuffer());
   delete buffer;
@@ -702,6 +876,7 @@
   PacketBuffer buffer(3, &tick_timer);
   PacketGenerator gen(0, kStartTimeStamp, 0, kFrameSizeSamples);
   StrictMock<MockStatisticsCalculator> mock_stats;
+  MockDecoderDatabase decoder_database;
 
   Packet packet_1 = gen.NextPacket(kPayloadSizeBytes, nullptr);
 
@@ -716,7 +891,12 @@
                 packet_2.timestamp);  // Tmestamp wrapped around.
 
   EXPECT_EQ(PacketBuffer::kOK,
-            buffer.InsertPacket(std::move(packet_1), &mock_stats));
+            buffer.InsertPacket(/*packet=*/std::move(packet_1),
+                                /*stats=*/&mock_stats,
+                                /*last_decoded_length=*/kFrameSizeSamples,
+                                /*sample_rate=*/1000,
+                                /*target_level_ms=*/60,
+                                /*decoder_database=*/decoder_database));
 
   constexpr size_t kLastDecodedSizeSamples = 2;
   // packet_1 has no access to duration, and relies last decoded duration as
@@ -726,7 +906,12 @@
                                   KCountDtxWaitingTime));
 
   EXPECT_EQ(PacketBuffer::kOK,
-            buffer.InsertPacket(std::move(packet_2), &mock_stats));
+            buffer.InsertPacket(/*packet=*/std::move(packet_2),
+                                /*stats=*/&mock_stats,
+                                /*last_decoded_length=*/kFrameSizeSamples,
+                                /*sample_rate=*/1000,
+                                /*target_level_ms=*/60,
+                                /*decoder_database=*/decoder_database));
 
   EXPECT_EQ(kFrameSizeSamples * 2,
             buffer.GetSpanSamples(0, kSampleRateHz, KCountDtxWaitingTime));
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
index 80e3be2..3f3077f 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
@@ -107,7 +107,7 @@
 // Common validator for file names.
 static bool ValidateFilename(const std::string& value, bool is_output) {
   if (!is_output) {
-    RTC_CHECK_NE(value.substr(value.find_last_of(".") + 1), "wav")
+    RTC_CHECK_NE(value.substr(value.find_last_of('.') + 1), "wav")
         << "WAV file input is not supported";
   }
   FILE* fid =
diff --git a/modules/audio_coding/neteq/tools/neteq_test.cc b/modules/audio_coding/neteq/tools/neteq_test.cc
index 997b034..0988d2c 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test.cc
@@ -51,12 +51,12 @@
     const NetEqInput::PacketData& packet) {
   std::cerr << "InsertPacket returned an error." << std::endl;
   std::cerr << "Packet data: " << packet.ToString() << std::endl;
-  FATAL();
+  RTC_FATAL();
 }
 
 void DefaultNetEqTestErrorCallback::OnGetAudioError() {
   std::cerr << "GetAudio returned an error." << std::endl;
-  FATAL();
+  RTC_FATAL();
 }
 
 NetEqTest::NetEqTest(const NetEq::Config& config,
diff --git a/modules/audio_coding/neteq/tools/rtp_file_source.cc b/modules/audio_coding/neteq/tools/rtp_file_source.cc
index f578065..7852330 100644
--- a/modules/audio_coding/neteq/tools/rtp_file_source.cc
+++ b/modules/audio_coding/neteq/tools/rtp_file_source.cc
@@ -91,8 +91,9 @@
     return true;
   rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kPcap, file_name));
   if (!rtp_reader_) {
-    FATAL() << "Couldn't open input file as either a rtpdump or .pcap. Note "
-               "that .pcapng is not supported.";
+    RTC_FATAL()
+        << "Couldn't open input file as either a rtpdump or .pcap. Note "
+        << "that .pcapng is not supported.";
   }
   return true;
 }
diff --git a/modules/audio_processing/aec3/aec_state.cc b/modules/audio_processing/aec3/aec_state.cc
index c736109..5b31e3c 100644
--- a/modules/audio_processing/aec3/aec_state.cc
+++ b/modules/audio_processing/aec3/aec_state.cc
@@ -322,6 +322,11 @@
                         external_delay ? 1 : 0);
   data_dumper_->DumpRaw("aec3_filter_tail_freq_resp_est",
                         GetReverbFrequencyResponse());
+  data_dumper_->DumpRaw("aec3_subtractor_y2", subtractor_output[0].y2);
+  data_dumper_->DumpRaw("aec3_subtractor_e2_coarse",
+                        subtractor_output[0].e2_coarse);
+  data_dumper_->DumpRaw("aec3_subtractor_e2_refined",
+                        subtractor_output[0].e2_refined);
 }
 
 AecState::InitialState::InitialState(const EchoCanceller3Config& config)
diff --git a/modules/audio_processing/aec3/erle_estimator_unittest.cc b/modules/audio_processing/aec3/erle_estimator_unittest.cc
index 7fbad90..2a5a98d 100644
--- a/modules/audio_processing/aec3/erle_estimator_unittest.cc
+++ b/modules/audio_processing/aec3/erle_estimator_unittest.cc
@@ -47,7 +47,7 @@
     float reference_lf,
     float reference_hf) {
   VerifyErleBands(erle, reference_lf, reference_hf);
-  EXPECT_NEAR(reference_lf, erle_time_domain, 0.5);
+  EXPECT_NEAR(kTrueErle, erle_time_domain, 0.5);
 }
 
 void FormFarendTimeFrame(std::vector<std::vector<std::vector<float>>>* x) {
@@ -172,7 +172,7 @@
   // Verifies that the ERLE estimate is properly increased to higher values.
   FormFarendFrame(*render_delay_buffer->GetRenderBuffer(), kTrueErle, &X2, E2,
                   Y2);
-  for (size_t k = 0; k < 200; ++k) {
+  for (size_t k = 0; k < 1000; ++k) {
     render_delay_buffer->Insert(x);
     render_delay_buffer->PrepareCaptureProcessing();
     estimator.Update(*render_delay_buffer->GetRenderBuffer(),
@@ -237,7 +237,7 @@
     }
     FormFarendFrame(*render_delay_buffer->GetRenderBuffer(), kTrueErle, &X2, E2,
                     Y2);
-    for (size_t k = 0; k < 200; ++k) {
+    for (size_t k = 0; k < 1000; ++k) {
       render_delay_buffer->Insert(x);
       render_delay_buffer->PrepareCaptureProcessing();
       estimator.Update(*render_delay_buffer->GetRenderBuffer(),
diff --git a/modules/audio_processing/aec3/fullband_erle_estimator.cc b/modules/audio_processing/aec3/fullband_erle_estimator.cc
index e421214..e56674e 100644
--- a/modules/audio_processing/aec3/fullband_erle_estimator.cc
+++ b/modules/audio_processing/aec3/fullband_erle_estimator.cc
@@ -34,8 +34,8 @@
     const EchoCanceller3Config::Erle& config,
     size_t num_capture_channels)
     : min_erle_log2_(FastApproxLog2f(config.min + kEpsilon)),
-      max_erle_lf_log2(FastApproxLog2f(config.max_l + kEpsilon)),
-      hold_counters_time_domain_(num_capture_channels, 0),
+      max_erle_lf_log2_(FastApproxLog2f(config.max_l + kEpsilon)),
+      hold_counters_instantaneous_erle_(num_capture_channels, 0),
       erle_time_domain_log2_(num_capture_channels, min_erle_log2_),
       instantaneous_erle_(num_capture_channels, ErleInstantaneous(config)),
       linear_filters_qualities_(num_capture_channels) {
@@ -52,8 +52,8 @@
   UpdateQualityEstimates();
   std::fill(erle_time_domain_log2_.begin(), erle_time_domain_log2_.end(),
             min_erle_log2_);
-  std::fill(hold_counters_time_domain_.begin(),
-            hold_counters_time_domain_.end(), 0);
+  std::fill(hold_counters_instantaneous_erle_.begin(),
+            hold_counters_instantaneous_erle_.end(), 0);
 }
 
 void FullBandErleEstimator::Update(
@@ -71,21 +71,17 @@
         const float E2_sum =
             std::accumulate(E2[ch].begin(), E2[ch].end(), 0.0f);
         if (instantaneous_erle_[ch].Update(Y2_sum, E2_sum)) {
-          hold_counters_time_domain_[ch] = kBlocksToHoldErle;
+          hold_counters_instantaneous_erle_[ch] = kBlocksToHoldErle;
           erle_time_domain_log2_[ch] +=
-              0.1f * ((instantaneous_erle_[ch].GetInstErleLog2().value()) -
-                      erle_time_domain_log2_[ch]);
-          erle_time_domain_log2_[ch] = rtc::SafeClamp(
-              erle_time_domain_log2_[ch], min_erle_log2_, max_erle_lf_log2);
+              0.05f * ((instantaneous_erle_[ch].GetInstErleLog2().value()) -
+                       erle_time_domain_log2_[ch]);
+          erle_time_domain_log2_[ch] =
+              std::max(erle_time_domain_log2_[ch], min_erle_log2_);
         }
       }
     }
-    --hold_counters_time_domain_[ch];
-    if (hold_counters_time_domain_[ch] <= 0) {
-      erle_time_domain_log2_[ch] =
-          std::max(min_erle_log2_, erle_time_domain_log2_[ch] - 0.044f);
-    }
-    if (hold_counters_time_domain_[ch] == 0) {
+    --hold_counters_instantaneous_erle_[ch];
+    if (hold_counters_instantaneous_erle_[ch] == 0) {
       instantaneous_erle_[ch].ResetAccumulators();
     }
   }
@@ -166,17 +162,12 @@
 
 void FullBandErleEstimator::ErleInstantaneous::UpdateMaxMin() {
   RTC_DCHECK(erle_log2_);
-  if (erle_log2_.value() > max_erle_log2_) {
-    max_erle_log2_ = erle_log2_.value();
-  } else {
-    max_erle_log2_ -= 0.0004;  // Forget factor, approx 1dB every 3 sec.
-  }
-
-  if (erle_log2_.value() < min_erle_log2_) {
-    min_erle_log2_ = erle_log2_.value();
-  } else {
-    min_erle_log2_ += 0.0004;  // Forget factor, approx 1dB every 3 sec.
-  }
+  // Adding the forgetting factors for the maximum and minimum and capping the
+  // result to the incoming value.
+  max_erle_log2_ -= 0.0004f;  // Forget factor, approx 1dB every 3 sec.
+  max_erle_log2_ = std::max(max_erle_log2_, erle_log2_.value());
+  min_erle_log2_ += 0.0004f;  // Forget factor, approx 1dB every 3 sec.
+  min_erle_log2_ = std::min(min_erle_log2_, erle_log2_.value());
 }
 
 void FullBandErleEstimator::ErleInstantaneous::UpdateQualityEstimate() {
diff --git a/modules/audio_processing/aec3/fullband_erle_estimator.h b/modules/audio_processing/aec3/fullband_erle_estimator.h
index 1580f1a..2b720a4 100644
--- a/modules/audio_processing/aec3/fullband_erle_estimator.h
+++ b/modules/audio_processing/aec3/fullband_erle_estimator.h
@@ -106,8 +106,8 @@
   };
 
   const float min_erle_log2_;
-  const float max_erle_lf_log2;
-  std::vector<int> hold_counters_time_domain_;
+  const float max_erle_lf_log2_;
+  std::vector<int> hold_counters_instantaneous_erle_;
   std::vector<float> erle_time_domain_log2_;
   std::vector<ErleInstantaneous> instantaneous_erle_;
   std::vector<absl::optional<float>> linear_filters_qualities_;
diff --git a/modules/audio_processing/aec3/refined_filter_update_gain.cc b/modules/audio_processing/aec3/refined_filter_update_gain.cc
index 138329a..db5203d 100644
--- a/modules/audio_processing/aec3/refined_filter_update_gain.cc
+++ b/modules/audio_processing/aec3/refined_filter_update_gain.cc
@@ -73,6 +73,7 @@
     rtc::ArrayView<const float> erl,
     size_t size_partitions,
     bool saturated_capture_signal,
+    bool disallow_leakage_diverged,
     FftData* gain_fft) {
   RTC_DCHECK(gain_fft);
   // Introducing shorter notation to improve readability.
@@ -125,7 +126,7 @@
 
   // H_error = H_error + factor * erl.
   for (size_t k = 0; k < kFftLengthBy2Plus1; ++k) {
-    if (E2_coarse[k] >= E2_refined[k]) {
+    if (E2_refined[k] <= E2_coarse[k] || disallow_leakage_diverged) {
       H_error_[k] += current_config_.leakage_converged * erl[k];
     } else {
       H_error_[k] += current_config_.leakage_diverged * erl[k];
diff --git a/modules/audio_processing/aec3/refined_filter_update_gain.h b/modules/audio_processing/aec3/refined_filter_update_gain.h
index 5730979..ae4fe84 100644
--- a/modules/audio_processing/aec3/refined_filter_update_gain.h
+++ b/modules/audio_processing/aec3/refined_filter_update_gain.h
@@ -51,6 +51,7 @@
                rtc::ArrayView<const float> erl,
                size_t size_partitions,
                bool saturated_capture_signal,
+               bool disallow_leakage_diverged,
                FftData* gain_fft);
 
   // Sets a new config.
diff --git a/modules/audio_processing/aec3/refined_filter_update_gain_unittest.cc b/modules/audio_processing/aec3/refined_filter_update_gain_unittest.cc
index 2393fdd..6fce858 100644
--- a/modules/audio_processing/aec3/refined_filter_update_gain_unittest.cc
+++ b/modules/audio_processing/aec3/refined_filter_update_gain_unittest.cc
@@ -196,7 +196,8 @@
     std::array<float, kFftLengthBy2Plus1> erl;
     ComputeErl(optimization, H2[0], erl);
     refined_gain.Compute(render_power, render_signal_analyzer, output[0], erl,
-                         refined_filter.SizePartitions(), saturation, &G);
+                         refined_filter.SizePartitions(), saturation, false,
+                         &G);
     refined_filter.Adapt(*render_delay_buffer->GetRenderBuffer(), G, &h[0]);
 
     // Update the delay.
@@ -247,7 +248,7 @@
   erl.fill(0.f);
   EXPECT_DEATH(
       gain.Compute(render_power, analyzer, output, erl,
-                   config.filter.refined.length_blocks, false, nullptr),
+                   config.filter.refined.length_blocks, false, false, nullptr),
       "");
 }
 
diff --git a/modules/audio_processing/aec3/subtractor.cc b/modules/audio_processing/aec3/subtractor.cc
index d152299..d10e4ff 100644
--- a/modules/audio_processing/aec3/subtractor.cc
+++ b/modules/audio_processing/aec3/subtractor.cc
@@ -19,11 +19,17 @@
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_minmax.h"
+#include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
 
 namespace {
 
+bool UseCoarseFilterResetHangover() {
+  return !field_trial::IsEnabled(
+      "WebRTC-Aec3CoarseFilterResetHangoverKillSwitch");
+}
+
 void PredictionError(const Aec3Fft& fft,
                      const FftData& S,
                      rtc::ArrayView<const float> y,
@@ -66,12 +72,14 @@
       optimization_(optimization),
       config_(config),
       num_capture_channels_(num_capture_channels),
+      use_coarse_filter_reset_hangover_(UseCoarseFilterResetHangover()),
       refined_filters_(num_capture_channels_),
       coarse_filter_(num_capture_channels_),
       refined_gains_(num_capture_channels_),
       coarse_gains_(num_capture_channels_),
       filter_misadjustment_estimators_(num_capture_channels_),
       poor_coarse_filter_counters_(num_capture_channels_, 0),
+      coarse_filter_reset_hangover_(num_capture_channels_, 0),
       refined_frequency_responses_(
           num_capture_channels_,
           std::vector<std::array<float, kFftLengthBy2Plus1>>(
@@ -228,11 +236,19 @@
 
     // Update the refined filter.
     if (!refined_filters_adjusted) {
+      // Do not allow the performance of the coarse filter to affect the
+      // adaptation speed of the refined filter just after the coarse filter has
+      // been reset.
+      const bool disallow_leakage_diverged =
+          coarse_filter_reset_hangover_[ch] > 0 &&
+          use_coarse_filter_reset_hangover_;
+
       std::array<float, kFftLengthBy2Plus1> erl;
       ComputeErl(optimization_, refined_frequency_responses_[ch], erl);
       refined_gains_[ch]->Compute(X2_refined, render_signal_analyzer, output,
                                   erl, refined_filters_[ch]->SizePartitions(),
-                                  aec_state.SaturatedCapture(), &G);
+                                  aec_state.SaturatedCapture(),
+                                  disallow_leakage_diverged, &G);
     } else {
       G.re.fill(0.f);
       G.im.fill(0.f);
@@ -256,6 +272,8 @@
       coarse_gains_[ch]->Compute(X2_coarse, render_signal_analyzer, E_coarse,
                                  coarse_filter_[ch]->SizePartitions(),
                                  aec_state.SaturatedCapture(), &G);
+      coarse_filter_reset_hangover_[ch] =
+          std::max(coarse_filter_reset_hangover_[ch] - 1, 0);
     } else {
       poor_coarse_filter_counters_[ch] = 0;
       coarse_filter_[ch]->SetFilter(refined_filters_[ch]->SizePartitions(),
@@ -263,6 +281,8 @@
       coarse_gains_[ch]->Compute(X2_coarse, render_signal_analyzer, E_refined,
                                  coarse_filter_[ch]->SizePartitions(),
                                  aec_state.SaturatedCapture(), &G);
+      coarse_filter_reset_hangover_[ch] =
+          config_.filter.coarse_reset_hangover_blocks;
     }
 
     coarse_filter_[ch]->Adapt(render_buffer, G);
diff --git a/modules/audio_processing/aec3/subtractor.h b/modules/audio_processing/aec3/subtractor.h
index 42ca372..560f656 100644
--- a/modules/audio_processing/aec3/subtractor.h
+++ b/modules/audio_processing/aec3/subtractor.h
@@ -120,6 +120,7 @@
   const Aec3Optimization optimization_;
   const EchoCanceller3Config config_;
   const size_t num_capture_channels_;
+  const bool use_coarse_filter_reset_hangover_;
 
   std::vector<std::unique_ptr<AdaptiveFirFilter>> refined_filters_;
   std::vector<std::unique_ptr<AdaptiveFirFilter>> coarse_filter_;
@@ -127,6 +128,7 @@
   std::vector<std::unique_ptr<CoarseFilterUpdateGain>> coarse_gains_;
   std::vector<FilterMisadjustmentEstimator> filter_misadjustment_estimators_;
   std::vector<size_t> poor_coarse_filter_counters_;
+  std::vector<int> coarse_filter_reset_hangover_;
   std::vector<std::vector<std::array<float, kFftLengthBy2Plus1>>>
       refined_frequency_responses_;
   std::vector<std::vector<float>> refined_impulse_responses_;
diff --git a/modules/audio_processing/aec3/transparent_mode.cc b/modules/audio_processing/aec3/transparent_mode.cc
index 3ed0980..7cfa3e8 100644
--- a/modules/audio_processing/aec3/transparent_mode.cc
+++ b/modules/audio_processing/aec3/transparent_mode.cc
@@ -23,8 +23,8 @@
   return field_trial::IsEnabled("WebRTC-Aec3TransparentModeKillSwitch");
 }
 
-bool DeactivateTransparentModeHmm() {
-  return field_trial::IsEnabled("WebRTC-Aec3TransparentModeHmmKillSwitch");
+bool ActivateTransparentModeHmm() {
+  return field_trial::IsEnabled("WebRTC-Aec3TransparentModeHmm");
 }
 
 }  // namespace
@@ -230,10 +230,10 @@
   if (config.ep_strength.bounded_erl || DeactivateTransparentMode()) {
     return nullptr;
   }
-  if (DeactivateTransparentModeHmm()) {
-    return std::make_unique<LegacyTransparentModeImpl>(config);
+  if (ActivateTransparentModeHmm()) {
+    return std::make_unique<TransparentModeImpl>();
   }
-  return std::make_unique<TransparentModeImpl>();
+  return std::make_unique<LegacyTransparentModeImpl>(config);
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/BUILD.gn b/modules/audio_processing/agc2/BUILD.gn
index bf09533..7b71f6a 100644
--- a/modules/audio_processing/agc2/BUILD.gn
+++ b/modules/audio_processing/agc2/BUILD.gn
@@ -56,6 +56,7 @@
 
   deps = [
     ":common",
+    ":cpu_features",
     ":gain_applier",
     ":noise_level_estimator",
     ":rnn_vad_with_level",
@@ -161,8 +162,16 @@
     "vad_with_level.cc",
     "vad_with_level.h",
   ]
+
+  defines = []
+  if (rtc_build_with_neon && current_cpu != "arm64") {
+    suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+    cflags = [ "-mfpu=neon" ]
+  }
+
   deps = [
     ":common",
+    ":cpu_features",
     "..:audio_frame_view",
     "../../../api:array_view",
     "../../../common_audio",
@@ -172,6 +181,19 @@
   ]
 }
 
+rtc_library("cpu_features") {
+  sources = [
+    "cpu_features.cc",
+    "cpu_features.h",
+  ]
+  visibility = [ "./*" ]
+  deps = [
+    "../../../rtc_base:stringutils",
+    "../../../rtc_base/system:arch",
+    "../../../system_wrappers",
+  ]
+}
+
 rtc_library("adaptive_digital_unittests") {
   testonly = true
   configs += [ "..:apm_debug_dump" ]
diff --git a/modules/audio_processing/agc2/adaptive_agc.cc b/modules/audio_processing/agc2/adaptive_agc.cc
index 0372ccf..e72942a 100644
--- a/modules/audio_processing/agc2/adaptive_agc.cc
+++ b/modules/audio_processing/agc2/adaptive_agc.cc
@@ -11,6 +11,7 @@
 #include "modules/audio_processing/agc2/adaptive_agc.h"
 
 #include "common_audio/include/audio_util.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/vad_with_level.h"
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/checks.h"
@@ -32,6 +33,22 @@
 constexpr float kMaxGainChangePerSecondDb = 3.f;
 constexpr float kMaxOutputNoiseLevelDbfs = -50.f;
 
+// Detects the available CPU features and applies any kill-switches.
+AvailableCpuFeatures GetAllowedCpuFeatures(
+    const AudioProcessing::Config::GainController2::AdaptiveDigital& config) {
+  AvailableCpuFeatures features = GetAvailableCpuFeatures();
+  if (!config.sse2_allowed) {
+    features.sse2 = false;
+  }
+  if (!config.avx2_allowed) {
+    features.avx2 = false;
+  }
+  if (!config.neon_allowed) {
+    features.neon = false;
+  }
+  return features;
+}
+
 }  // namespace
 
 AdaptiveAgc::AdaptiveAgc(ApmDataDumper* apm_data_dumper)
@@ -54,7 +71,8 @@
               .level_estimator_adjacent_speech_frames_threshold,
           config.adaptive_digital.initial_saturation_margin_db,
           config.adaptive_digital.extra_saturation_margin_db),
-      vad_(config.adaptive_digital.vad_probability_attack),
+      vad_(config.adaptive_digital.vad_probability_attack,
+           GetAllowedCpuFeatures(config.adaptive_digital)),
       gain_applier_(
           apm_data_dumper,
           config.adaptive_digital.gain_applier_adjacent_speech_frames_threshold,
diff --git a/modules/audio_processing/agc2/cpu_features.cc b/modules/audio_processing/agc2/cpu_features.cc
new file mode 100644
index 0000000..cced761
--- /dev/null
+++ b/modules/audio_processing/agc2/cpu_features.cc
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/agc2/cpu_features.h"
+
+#include "rtc_base/strings/string_builder.h"
+#include "rtc_base/system/arch.h"
+#include "system_wrappers/include/cpu_features_wrapper.h"
+
+namespace webrtc {
+
+std::string AvailableCpuFeatures::ToString() const {
+  char buf[64];
+  rtc::SimpleStringBuilder builder(buf);
+  bool first = true;
+  if (sse2) {
+    builder << (first ? "SSE2" : "_SSE2");
+    first = false;
+  }
+  if (avx2) {
+    builder << (first ? "AVX2" : "_AVX2");
+    first = false;
+  }
+  if (neon) {
+    builder << (first ? "NEON" : "_NEON");
+    first = false;
+  }
+  if (first) {
+    return "none";
+  }
+  return builder.str();
+}
+
+// Detects available CPU features.
+AvailableCpuFeatures GetAvailableCpuFeatures() {
+#if defined(WEBRTC_ARCH_X86_FAMILY)
+  return {/*sse2=*/GetCPUInfo(kSSE2) != 0,
+          /*avx2=*/GetCPUInfo(kAVX2) != 0,
+          /*neon=*/false};
+#elif defined(WEBRTC_HAS_NEON)
+  return {/*sse2=*/false,
+          /*avx2=*/false,
+          /*neon=*/true};
+#else
+  return {/*sse2=*/false,
+          /*avx2=*/false,
+          /*neon=*/false};
+#endif
+}
+
+AvailableCpuFeatures NoAvailableCpuFeatures() {
+  return {/*sse2=*/false, /*avx2=*/false, /*neon=*/false};
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/cpu_features.h b/modules/audio_processing/agc2/cpu_features.h
new file mode 100644
index 0000000..54ddfb3
--- /dev/null
+++ b/modules/audio_processing/agc2/cpu_features.h
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_AGC2_CPU_FEATURES_H_
+#define MODULES_AUDIO_PROCESSING_AGC2_CPU_FEATURES_H_
+
+#include <string>
+
+namespace webrtc {
+
+// Collection of flags indicating which CPU features are available on the
+// current platform. True means available.
+struct AvailableCpuFeatures {
+  AvailableCpuFeatures(bool sse2, bool avx2, bool neon)
+      : sse2(sse2), avx2(avx2), neon(neon) {}
+  // Intel.
+  bool sse2;
+  bool avx2;
+  // ARM.
+  bool neon;
+  std::string ToString() const;
+};
+
+// Detects what CPU features are available.
+AvailableCpuFeatures GetAvailableCpuFeatures();
+
+// Returns the CPU feature flags all set to false.
+AvailableCpuFeatures NoAvailableCpuFeatures();
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AGC2_CPU_FEATURES_H_
diff --git a/modules/audio_processing/agc2/fixed_gain_controller.cc b/modules/audio_processing/agc2/fixed_gain_controller.cc
deleted file mode 100644
index ef908dc..0000000
--- a/modules/audio_processing/agc2/fixed_gain_controller.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_processing/agc2/fixed_gain_controller.h"
-
-#include "api/array_view.h"
-#include "common_audio/include/audio_util.h"
-#include "modules/audio_processing/agc2/agc2_common.h"
-#include "modules/audio_processing/logging/apm_data_dumper.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_minmax.h"
-
-namespace webrtc {
-namespace {
-
-// Returns true when the gain factor is so close to 1 that it would
-// not affect int16 samples.
-bool CloseToOne(float gain_factor) {
-  return 1.f - 1.f / kMaxFloatS16Value <= gain_factor &&
-         gain_factor <= 1.f + 1.f / kMaxFloatS16Value;
-}
-}  // namespace
-
-FixedGainController::FixedGainController(ApmDataDumper* apm_data_dumper)
-    : FixedGainController(apm_data_dumper, "Agc2") {}
-
-FixedGainController::FixedGainController(ApmDataDumper* apm_data_dumper,
-                                         std::string histogram_name_prefix)
-    : apm_data_dumper_(apm_data_dumper),
-      limiter_(48000, apm_data_dumper_, histogram_name_prefix) {
-  // Do update histograms.xml when adding name prefixes.
-  RTC_DCHECK(histogram_name_prefix == "" || histogram_name_prefix == "Test" ||
-             histogram_name_prefix == "AudioMixer" ||
-             histogram_name_prefix == "Agc2");
-}
-
-void FixedGainController::SetGain(float gain_to_apply_db) {
-  // Changes in gain_to_apply_ cause discontinuities. We assume
-  // gain_to_apply_ is set in the beginning of the call. If it is
-  // frequently changed, we should add interpolation between the
-  // values.
-  // The gain
-  RTC_DCHECK_LE(-50.f, gain_to_apply_db);
-  RTC_DCHECK_LE(gain_to_apply_db, 50.f);
-  const float previous_applied_gained = gain_to_apply_;
-  gain_to_apply_ = DbToRatio(gain_to_apply_db);
-  RTC_DCHECK_LT(0.f, gain_to_apply_);
-  RTC_DLOG(LS_INFO) << "Gain to apply: " << gain_to_apply_db << " db.";
-  // Reset the gain curve applier to quickly react on abrupt level changes
-  // caused by large changes of the applied gain.
-  if (previous_applied_gained != gain_to_apply_) {
-    limiter_.Reset();
-  }
-}
-
-void FixedGainController::SetSampleRate(size_t sample_rate_hz) {
-  limiter_.SetSampleRate(sample_rate_hz);
-}
-
-void FixedGainController::Process(AudioFrameView<float> signal) {
-  // Apply fixed digital gain. One of the
-  // planned usages of the FGC is to only use the limiter. In that
-  // case, the gain would be 1.0. Not doing the multiplications speeds
-  // it up considerably. Hence the check.
-  if (!CloseToOne(gain_to_apply_)) {
-    for (size_t k = 0; k < signal.num_channels(); ++k) {
-      rtc::ArrayView<float> channel_view = signal.channel(k);
-      for (auto& sample : channel_view) {
-        sample *= gain_to_apply_;
-      }
-    }
-  }
-
-  // Use the limiter.
-  limiter_.Process(signal);
-
-  // Dump data for debug.
-  const auto channel_view = signal.channel(0);
-  apm_data_dumper_->DumpRaw("agc2_fixed_digital_gain_curve_applier",
-                            channel_view.size(), channel_view.data());
-  // Hard-clipping.
-  for (size_t k = 0; k < signal.num_channels(); ++k) {
-    rtc::ArrayView<float> channel_view = signal.channel(k);
-    for (auto& sample : channel_view) {
-      sample = rtc::SafeClamp(sample, kMinFloatS16Value, kMaxFloatS16Value);
-    }
-  }
-}
-
-float FixedGainController::LastAudioLevel() const {
-  return limiter_.LastAudioLevel();
-}
-}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/interpolated_gain_curve.cc b/modules/audio_processing/agc2/interpolated_gain_curve.cc
index 502e702..3dd5010 100644
--- a/modules/audio_processing/agc2/interpolated_gain_curve.cc
+++ b/modules/audio_processing/agc2/interpolated_gain_curve.cc
@@ -28,8 +28,9 @@
 constexpr std::array<float, kInterpolatedGainCurveTotalPoints>
     InterpolatedGainCurve::approximation_params_q_;
 
-InterpolatedGainCurve::InterpolatedGainCurve(ApmDataDumper* apm_data_dumper,
-                                             std::string histogram_name_prefix)
+InterpolatedGainCurve::InterpolatedGainCurve(
+    ApmDataDumper* apm_data_dumper,
+    const std::string& histogram_name_prefix)
     : region_logger_("WebRTC.Audio." + histogram_name_prefix +
                          ".FixedDigitalGainCurveRegion.Identity",
                      "WebRTC.Audio." + histogram_name_prefix +
@@ -56,10 +57,10 @@
 }
 
 InterpolatedGainCurve::RegionLogger::RegionLogger(
-    std::string identity_histogram_name,
-    std::string knee_histogram_name,
-    std::string limiter_histogram_name,
-    std::string saturation_histogram_name)
+    const std::string& identity_histogram_name,
+    const std::string& knee_histogram_name,
+    const std::string& limiter_histogram_name,
+    const std::string& saturation_histogram_name)
     : identity_histogram(
           metrics::HistogramFactoryGetCounts(identity_histogram_name,
                                              1,
diff --git a/modules/audio_processing/agc2/interpolated_gain_curve.h b/modules/audio_processing/agc2/interpolated_gain_curve.h
index ef1c027..69652c5 100644
--- a/modules/audio_processing/agc2/interpolated_gain_curve.h
+++ b/modules/audio_processing/agc2/interpolated_gain_curve.h
@@ -61,7 +61,7 @@
   };
 
   InterpolatedGainCurve(ApmDataDumper* apm_data_dumper,
-                        std::string histogram_name_prefix);
+                        const std::string& histogram_name_prefix);
   ~InterpolatedGainCurve();
 
   Stats get_stats() const { return stats_; }
@@ -84,10 +84,10 @@
     metrics::Histogram* limiter_histogram;
     metrics::Histogram* saturation_histogram;
 
-    RegionLogger(std::string identity_histogram_name,
-                 std::string knee_histogram_name,
-                 std::string limiter_histogram_name,
-                 std::string saturation_histogram_name);
+    RegionLogger(const std::string& identity_histogram_name,
+                 const std::string& knee_histogram_name,
+                 const std::string& limiter_histogram_name,
+                 const std::string& saturation_histogram_name);
 
     ~RegionLogger();
 
diff --git a/modules/audio_processing/agc2/limiter.cc b/modules/audio_processing/agc2/limiter.cc
index 1589f07..1147332 100644
--- a/modules/audio_processing/agc2/limiter.cc
+++ b/modules/audio_processing/agc2/limiter.cc
@@ -94,7 +94,7 @@
 
 Limiter::Limiter(size_t sample_rate_hz,
                  ApmDataDumper* apm_data_dumper,
-                 std::string histogram_name)
+                 const std::string& histogram_name)
     : interp_gain_curve_(apm_data_dumper, histogram_name),
       level_estimator_(sample_rate_hz, apm_data_dumper),
       apm_data_dumper_(apm_data_dumper) {
diff --git a/modules/audio_processing/agc2/limiter.h b/modules/audio_processing/agc2/limiter.h
index 599fd0f..df7b540 100644
--- a/modules/audio_processing/agc2/limiter.h
+++ b/modules/audio_processing/agc2/limiter.h
@@ -26,7 +26,7 @@
  public:
   Limiter(size_t sample_rate_hz,
           ApmDataDumper* apm_data_dumper,
-          std::string histogram_name_prefix);
+          const std::string& histogram_name_prefix);
   Limiter(const Limiter& limiter) = delete;
   Limiter& operator=(const Limiter& limiter) = delete;
   ~Limiter();
diff --git a/modules/audio_processing/agc2/rnn_vad/BUILD.gn b/modules/audio_processing/agc2/rnn_vad/BUILD.gn
index fae1d5a..4732efd 100644
--- a/modules/audio_processing/agc2/rnn_vad/BUILD.gn
+++ b/modules/audio_processing/agc2/rnn_vad/BUILD.gn
@@ -17,6 +17,7 @@
     "rnn.h",
   ]
 
+  defines = []
   if (rtc_build_with_neon && current_cpu != "arm64") {
     suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
     cflags = [ "-mfpu=neon" ]
@@ -24,18 +25,17 @@
 
   deps = [
     ":rnn_vad_common",
+    ":rnn_vad_layers",
     ":rnn_vad_lp_residual",
     ":rnn_vad_pitch",
     ":rnn_vad_sequence_buffer",
     ":rnn_vad_spectral_features",
     "..:biquad_filter",
+    "..:cpu_features",
     "../../../../api:array_view",
-    "../../../../api:function_view",
     "../../../../rtc_base:checks",
-    "../../../../rtc_base:logging",
     "../../../../rtc_base:safe_compare",
     "../../../../rtc_base:safe_conversions",
-    "../../../../rtc_base/system:arch",
     "//third_party/rnnoise:rnn_vad",
   ]
 }
@@ -53,16 +53,13 @@
   ]
 }
 
-rtc_library("rnn_vad_common") {
+rtc_source_set("rnn_vad_common") {
   # TODO(alessiob): Make this target visibility private.
   visibility = [
     ":*",
     "..:rnn_vad_with_level",
   ]
-  sources = [
-    "common.cc",
-    "common.h",
-  ]
+  sources = [ "common.h" ]
   deps = [
     "../../../../rtc_base/system:arch",
     "../../../../system_wrappers",
@@ -81,6 +78,67 @@
   ]
 }
 
+rtc_source_set("rnn_vad_layers") {
+  sources = [
+    "rnn_fc.cc",
+    "rnn_fc.h",
+    "rnn_gru.cc",
+    "rnn_gru.h",
+  ]
+
+  defines = []
+  if (rtc_build_with_neon && current_cpu != "arm64") {
+    suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+    cflags = [ "-mfpu=neon" ]
+  }
+
+  deps = [
+    ":rnn_vad_common",
+    ":vector_math",
+    "..:cpu_features",
+    "../../../../api:array_view",
+    "../../../../api:function_view",
+    "../../../../rtc_base:checks",
+    "../../../../rtc_base:safe_conversions",
+    "//third_party/rnnoise:rnn_vad",
+  ]
+  if (current_cpu == "x86" || current_cpu == "x64") {
+    deps += [ ":vector_math_avx2" ]
+  }
+  absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
+}
+
+rtc_source_set("vector_math") {
+  sources = [ "vector_math.h" ]
+  deps = [
+    "..:cpu_features",
+    "../../../../api:array_view",
+    "../../../../rtc_base:checks",
+    "../../../../rtc_base:safe_conversions",
+    "../../../../rtc_base/system:arch",
+  ]
+}
+
+if (current_cpu == "x86" || current_cpu == "x64") {
+  rtc_library("vector_math_avx2") {
+    sources = [ "vector_math_avx2.cc" ]
+    if (is_win) {
+      cflags = [ "/arch:AVX2" ]
+    } else {
+      cflags = [
+        "-mavx2",
+        "-mfma",
+      ]
+    }
+    deps = [
+      ":vector_math",
+      "../../../../api:array_view",
+      "../../../../rtc_base:checks",
+      "../../../../rtc_base:safe_conversions",
+    ]
+  }
+}
+
 rtc_library("rnn_vad_pitch") {
   sources = [
     "pitch_search.cc",
@@ -88,15 +146,28 @@
     "pitch_search_internal.cc",
     "pitch_search_internal.h",
   ]
+
+  defines = []
+  if (rtc_build_with_neon && current_cpu != "arm64") {
+    suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+    cflags = [ "-mfpu=neon" ]
+  }
+
   deps = [
     ":rnn_vad_auto_correlation",
     ":rnn_vad_common",
+    ":vector_math",
+    "..:cpu_features",
     "../../../../api:array_view",
     "../../../../rtc_base:checks",
     "../../../../rtc_base:gtest_prod",
     "../../../../rtc_base:safe_compare",
     "../../../../rtc_base:safe_conversions",
+    "../../../../rtc_base/system:arch",
   ]
+  if (current_cpu == "x86" || current_cpu == "x64") {
+    deps += [ ":vector_math_avx2" ]
+  }
 }
 
 rtc_source_set("rnn_vad_ring_buffer") {
@@ -156,8 +227,6 @@
       "../../../../api:scoped_refptr",
       "../../../../rtc_base:checks",
       "../../../../rtc_base:safe_compare",
-      "../../../../rtc_base/system:arch",
-      "../../../../system_wrappers",
       "../../../../test:fileutils",
       "../../../../test:test_support",
     ]
@@ -189,17 +258,28 @@
       "pitch_search_internal_unittest.cc",
       "pitch_search_unittest.cc",
       "ring_buffer_unittest.cc",
+      "rnn_fc_unittest.cc",
+      "rnn_gru_unittest.cc",
       "rnn_unittest.cc",
       "rnn_vad_unittest.cc",
       "sequence_buffer_unittest.cc",
       "spectral_features_internal_unittest.cc",
       "spectral_features_unittest.cc",
       "symmetric_matrix_buffer_unittest.cc",
+      "vector_math_unittest.cc",
     ]
+
+    defines = []
+    if (rtc_build_with_neon && current_cpu != "arm64") {
+      suppressed_configs += [ "//build/config/compiler:compiler_arm_fpu" ]
+      cflags = [ "-mfpu=neon" ]
+    }
+
     deps = [
       ":rnn_vad",
       ":rnn_vad_auto_correlation",
       ":rnn_vad_common",
+      ":rnn_vad_layers",
       ":rnn_vad_lp_residual",
       ":rnn_vad_pitch",
       ":rnn_vad_ring_buffer",
@@ -207,6 +287,8 @@
       ":rnn_vad_spectral_features",
       ":rnn_vad_symmetric_matrix_buffer",
       ":test_utils",
+      ":vector_math",
+      "..:cpu_features",
       "../..:audioproc_test_utils",
       "../../../../api:array_view",
       "../../../../common_audio/",
@@ -214,11 +296,15 @@
       "../../../../rtc_base:logging",
       "../../../../rtc_base:safe_compare",
       "../../../../rtc_base:safe_conversions",
+      "../../../../rtc_base:stringutils",
       "../../../../rtc_base/system:arch",
       "../../../../test:test_support",
       "../../utility:pffft_wrapper",
       "//third_party/rnnoise:rnn_vad",
     ]
+    if (current_cpu == "x86" || current_cpu == "x64") {
+      deps += [ ":vector_math_avx2" ]
+    }
     absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
     data = unittest_resources
     if (is_ios) {
@@ -232,6 +318,7 @@
     deps = [
       ":rnn_vad",
       ":rnn_vad_common",
+      "..:cpu_features",
       "../../../../api:array_view",
       "../../../../common_audio",
       "../../../../rtc_base:rtc_base_approved",
diff --git a/modules/audio_processing/agc2/rnn_vad/auto_correlation_unittest.cc b/modules/audio_processing/agc2/rnn_vad/auto_correlation_unittest.cc
index ef3748d..76001ed 100644
--- a/modules/audio_processing/agc2/rnn_vad/auto_correlation_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/auto_correlation_unittest.cc
@@ -17,15 +17,15 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
+namespace {
 
 // Checks that the auto correlation function produces output within tolerance
 // given test input data.
 TEST(RnnVadTest, PitchBufferAutoCorrelationWithinTolerance) {
   PitchTestData test_data;
   std::array<float, kBufSize12kHz> pitch_buf_decimated;
-  Decimate2x(test_data.GetPitchBufView(), pitch_buf_decimated);
-  std::array<float, kNumPitchBufAutoCorrCoeffs> computed_output;
+  Decimate2x(test_data.PitchBuffer24kHzView(), pitch_buf_decimated);
+  std::array<float, kNumLags12kHz> computed_output;
   {
     // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
     // FloatingPointExceptionObserver fpe_observer;
@@ -33,7 +33,7 @@
     auto_corr_calculator.ComputeOnPitchBuffer(pitch_buf_decimated,
                                               computed_output);
   }
-  auto auto_corr_view = test_data.GetPitchBufAutoCorrCoeffsView();
+  auto auto_corr_view = test_data.AutoCorrelation12kHzView();
   ExpectNearAbsolute({auto_corr_view.data(), auto_corr_view.size()},
                      computed_output, 3e-3f);
 }
@@ -44,7 +44,7 @@
   // Create constant signal with no pitch.
   std::array<float, kBufSize12kHz> pitch_buf_decimated;
   std::fill(pitch_buf_decimated.begin(), pitch_buf_decimated.end(), 1.f);
-  std::array<float, kNumPitchBufAutoCorrCoeffs> computed_output;
+  std::array<float, kNumLags12kHz> computed_output;
   {
     // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
     // FloatingPointExceptionObserver fpe_observer;
@@ -55,12 +55,12 @@
   // The expected output is a vector filled with the same expected
   // auto-correlation value. The latter equals the length of a 20 ms frame.
   constexpr int kFrameSize20ms12kHz = kFrameSize20ms24kHz / 2;
-  std::array<float, kNumPitchBufAutoCorrCoeffs> expected_output;
+  std::array<float, kNumLags12kHz> expected_output;
   std::fill(expected_output.begin(), expected_output.end(),
             static_cast<float>(kFrameSize20ms12kHz));
   ExpectNearAbsolute(expected_output, computed_output, 4e-5f);
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/common.cc b/modules/audio_processing/agc2/rnn_vad/common.cc
deleted file mode 100644
index 5d76b52..0000000
--- a/modules/audio_processing/agc2/rnn_vad/common.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "modules/audio_processing/agc2/rnn_vad/common.h"
-
-#include "rtc_base/system/arch.h"
-#include "system_wrappers/include/cpu_features_wrapper.h"
-
-namespace webrtc {
-namespace rnn_vad {
-
-Optimization DetectOptimization() {
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-  if (GetCPUInfo(kSSE2) != 0) {
-    return Optimization::kSse2;
-  }
-#endif
-
-#if defined(WEBRTC_HAS_NEON)
-  return Optimization::kNeon;
-#endif
-
-  return Optimization::kNone;
-}
-
-}  // namespace rnn_vad
-}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/common.h b/modules/audio_processing/agc2/rnn_vad/common.h
index 36b366a..be5a2d5 100644
--- a/modules/audio_processing/agc2/rnn_vad/common.h
+++ b/modules/audio_processing/agc2/rnn_vad/common.h
@@ -71,11 +71,6 @@
 
 constexpr int kFeatureVectorSize = 42;
 
-enum class Optimization { kNone, kSse2, kNeon };
-
-// Detects what kind of optimizations to use for the code.
-Optimization DetectOptimization();
-
 }  // namespace rnn_vad
 }  // namespace webrtc
 
diff --git a/modules/audio_processing/agc2/rnn_vad/features_extraction.cc b/modules/audio_processing/agc2/rnn_vad/features_extraction.cc
index cdbbbc3..f86eba7 100644
--- a/modules/audio_processing/agc2/rnn_vad/features_extraction.cc
+++ b/modules/audio_processing/agc2/rnn_vad/features_extraction.cc
@@ -26,13 +26,13 @@
 
 }  // namespace
 
-FeaturesExtractor::FeaturesExtractor()
+FeaturesExtractor::FeaturesExtractor(const AvailableCpuFeatures& cpu_features)
     : use_high_pass_filter_(false),
       pitch_buf_24kHz_(),
       pitch_buf_24kHz_view_(pitch_buf_24kHz_.GetBufferView()),
       lp_residual_(kBufSize24kHz),
       lp_residual_view_(lp_residual_.data(), kBufSize24kHz),
-      pitch_estimator_(),
+      pitch_estimator_(cpu_features),
       reference_frame_view_(pitch_buf_24kHz_.GetMostRecentValuesView()) {
   RTC_DCHECK_EQ(kBufSize24kHz, lp_residual_.size());
   hpf_.Initialize(kHpfConfig24k);
diff --git a/modules/audio_processing/agc2/rnn_vad/features_extraction.h b/modules/audio_processing/agc2/rnn_vad/features_extraction.h
index e2c77d2..f4cea7a 100644
--- a/modules/audio_processing/agc2/rnn_vad/features_extraction.h
+++ b/modules/audio_processing/agc2/rnn_vad/features_extraction.h
@@ -26,7 +26,7 @@
 // Feature extractor to feed the VAD RNN.
 class FeaturesExtractor {
  public:
-  FeaturesExtractor();
+  explicit FeaturesExtractor(const AvailableCpuFeatures& cpu_features);
   FeaturesExtractor(const FeaturesExtractor&) = delete;
   FeaturesExtractor& operator=(const FeaturesExtractor&) = delete;
   ~FeaturesExtractor();
diff --git a/modules/audio_processing/agc2/rnn_vad/features_extraction_unittest.cc b/modules/audio_processing/agc2/rnn_vad/features_extraction_unittest.cc
index 9df5273..98da39e 100644
--- a/modules/audio_processing/agc2/rnn_vad/features_extraction_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/features_extraction_unittest.cc
@@ -13,7 +13,7 @@
 #include <cmath>
 #include <vector>
 
-#include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "rtc_base/numerics/safe_compare.h"
 #include "rtc_base/numerics/safe_conversions.h"
 // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
@@ -22,7 +22,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 constexpr int ceil(int n, int m) {
@@ -51,7 +50,7 @@
 // Feeds |features_extractor| with |samples| splitting it in 10 ms frames.
 // For every frame, the output is written into |feature_vector|. Returns true
 // if silence is detected in the last frame.
-bool FeedTestData(FeaturesExtractor* features_extractor,
+bool FeedTestData(FeaturesExtractor& features_extractor,
                   rtc::ArrayView<const float> samples,
                   rtc::ArrayView<float, kFeatureVectorSize> feature_vector) {
   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
@@ -59,15 +58,13 @@
   bool is_silence = true;
   const int num_frames = samples.size() / kFrameSize10ms24kHz;
   for (int i = 0; i < num_frames; ++i) {
-    is_silence = features_extractor->CheckSilenceComputeFeatures(
+    is_silence = features_extractor.CheckSilenceComputeFeatures(
         {samples.data() + i * kFrameSize10ms24kHz, kFrameSize10ms24kHz},
         feature_vector);
   }
   return is_silence;
 }
 
-}  // namespace
-
 // Extracts the features for two pure tones and verifies that the pitch field
 // values reflect the known tone frequencies.
 TEST(RnnVadTest, FeatureExtractionLowHighPitch) {
@@ -77,7 +74,8 @@
   ASSERT_TRUE(PitchIsValid(low_pitch_hz));
   ASSERT_TRUE(PitchIsValid(high_pitch_hz));
 
-  FeaturesExtractor features_extractor;
+  const AvailableCpuFeatures cpu_features = GetAvailableCpuFeatures();
+  FeaturesExtractor features_extractor(cpu_features);
   std::vector<float> samples(kNumTestDataSize);
   std::vector<float> feature_vector(kFeatureVectorSize);
   ASSERT_EQ(kFeatureVectorSize, rtc::dchecked_cast<int>(feature_vector.size()));
@@ -89,17 +87,17 @@
   constexpr int pitch_feature_index = kFeatureVectorSize - 2;
   // Low frequency tone - i.e., high period.
   CreatePureTone(amplitude, low_pitch_hz, samples);
-  ASSERT_FALSE(FeedTestData(&features_extractor, samples, feature_vector_view));
+  ASSERT_FALSE(FeedTestData(features_extractor, samples, feature_vector_view));
   float high_pitch_period = feature_vector_view[pitch_feature_index];
   // High frequency tone - i.e., low period.
   features_extractor.Reset();
   CreatePureTone(amplitude, high_pitch_hz, samples);
-  ASSERT_FALSE(FeedTestData(&features_extractor, samples, feature_vector_view));
+  ASSERT_FALSE(FeedTestData(features_extractor, samples, feature_vector_view));
   float low_pitch_period = feature_vector_view[pitch_feature_index];
   // Check.
   EXPECT_LT(low_pitch_period, high_pitch_period);
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/lp_residual.h b/modules/audio_processing/agc2/rnn_vad/lp_residual.h
index 2e54dd9..380d9f6 100644
--- a/modules/audio_processing/agc2/rnn_vad/lp_residual.h
+++ b/modules/audio_processing/agc2/rnn_vad/lp_residual.h
@@ -18,7 +18,7 @@
 namespace webrtc {
 namespace rnn_vad {
 
-// LPC inverse filter length.
+// Linear predictive coding (LPC) inverse filter length.
 constexpr int kNumLpcCoefficients = 5;
 
 // Given a frame |x|, computes a post-processed version of LPC coefficients
diff --git a/modules/audio_processing/agc2/rnn_vad/lp_residual_unittest.cc b/modules/audio_processing/agc2/rnn_vad/lp_residual_unittest.cc
index 1779776..7b3a4a3 100644
--- a/modules/audio_processing/agc2/rnn_vad/lp_residual_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/lp_residual_unittest.cc
@@ -22,7 +22,7 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
+namespace {
 
 // Checks that the LP residual can be computed on an empty frame.
 TEST(RnnVadTest, LpResidualOfEmptyFrame) {
@@ -33,55 +33,48 @@
   std::array<float, kFrameSize10ms24kHz> empty_frame;
   empty_frame.fill(0.f);
   // Compute inverse filter coefficients.
-  std::array<float, kNumLpcCoefficients> lpc_coeffs;
-  ComputeAndPostProcessLpcCoefficients(empty_frame, lpc_coeffs);
+  std::array<float, kNumLpcCoefficients> lpc;
+  ComputeAndPostProcessLpcCoefficients(empty_frame, lpc);
   // Compute LP residual.
   std::array<float, kFrameSize10ms24kHz> lp_residual;
-  ComputeLpResidual(lpc_coeffs, empty_frame, lp_residual);
+  ComputeLpResidual(lpc, empty_frame, lp_residual);
 }
 
 // Checks that the computed LP residual is bit-exact given test input data.
 TEST(RnnVadTest, LpResidualPipelineBitExactness) {
   // Input and expected output readers.
-  auto pitch_buf_24kHz_reader = CreatePitchBuffer24kHzReader();
-  auto lp_residual_reader = CreateLpResidualAndPitchPeriodGainReader();
+  ChunksFileReader pitch_buffer_reader = CreatePitchBuffer24kHzReader();
+  ChunksFileReader lp_pitch_reader = CreateLpResidualAndPitchInfoReader();
 
   // Buffers.
-  std::vector<float> pitch_buf_data(kBufSize24kHz);
-  std::array<float, kNumLpcCoefficients> lpc_coeffs;
+  std::vector<float> pitch_buffer_24kHz(kBufSize24kHz);
+  std::array<float, kNumLpcCoefficients> lpc;
   std::vector<float> computed_lp_residual(kBufSize24kHz);
   std::vector<float> expected_lp_residual(kBufSize24kHz);
 
   // Test length.
   const int num_frames =
-      std::min(pitch_buf_24kHz_reader.second, 300);  // Max 3 s.
-  ASSERT_GE(lp_residual_reader.second, num_frames);
+      std::min(pitch_buffer_reader.num_chunks, 300);  // Max 3 s.
+  ASSERT_GE(lp_pitch_reader.num_chunks, num_frames);
 
-  {
-    // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
-    // FloatingPointExceptionObserver fpe_observer;
-    for (int i = 0; i < num_frames; ++i) {
-      // Read input.
-      ASSERT_TRUE(pitch_buf_24kHz_reader.first->ReadChunk(pitch_buf_data));
-      // Read expected output (ignore pitch gain and period).
-      ASSERT_TRUE(lp_residual_reader.first->ReadChunk(expected_lp_residual));
-      float unused;
-      ASSERT_TRUE(lp_residual_reader.first->ReadValue(&unused));
-      ASSERT_TRUE(lp_residual_reader.first->ReadValue(&unused));
-
-      // Check every 200 ms.
-      if (i % 20 != 0) {
-        continue;
-      }
-
-      SCOPED_TRACE(i);
-      ComputeAndPostProcessLpcCoefficients(pitch_buf_data, lpc_coeffs);
-      ComputeLpResidual(lpc_coeffs, pitch_buf_data, computed_lp_residual);
+  // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
+  // FloatingPointExceptionObserver fpe_observer;
+  for (int i = 0; i < num_frames; ++i) {
+    SCOPED_TRACE(i);
+    // Read input.
+    ASSERT_TRUE(pitch_buffer_reader.reader->ReadChunk(pitch_buffer_24kHz));
+    // Read expected output (ignore pitch gain and period).
+    ASSERT_TRUE(lp_pitch_reader.reader->ReadChunk(expected_lp_residual));
+    lp_pitch_reader.reader->SeekForward(2);  // Pitch period and strength.
+    // Check every 200 ms.
+    if (i % 20 == 0) {
+      ComputeAndPostProcessLpcCoefficients(pitch_buffer_24kHz, lpc);
+      ComputeLpResidual(lpc, pitch_buffer_24kHz, computed_lp_residual);
       ExpectNearAbsolute(expected_lp_residual, computed_lp_residual, kFloatMin);
     }
   }
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/module.mk b/modules/audio_processing/agc2/rnn_vad/module.mk
index 37c23f4..18b8e43 100644
--- a/modules/audio_processing/agc2/rnn_vad/module.mk
+++ b/modules/audio_processing/agc2/rnn_vad/module.mk
@@ -3,3 +3,35 @@
 # found in the LICENSE file.
 
 include common.mk
+
+rnn_vad_avx2_CXX_OBJECTS = \
+	modules/audio_processing/agc2/rnn_vad/vector_math_avx2.o
+
+CXX_STATIC_LIBRARY(rnn_vad_avx2.pic.a): \
+	CPPFLAGS += -I. -mavx2 -mfma
+
+CXX_STATIC_LIBRARY(rnn_vad_avx2.pic.a): \
+	$(rnn_vad_avx2_CXX_OBJECTS)
+
+rnn_vad_avx2: CXX_STATIC_LIBRARY(rnn_vad_avx2.pic.a)
+
+rnn_vad_CXX_OBJECTS = \
+	modules/audio_processing/agc2/rnn_vad/auto_correlation.o \
+	modules/audio_processing/agc2/rnn_vad/features_extraction.o \
+	modules/audio_processing/agc2/rnn_vad/lp_residual.o \
+	modules/audio_processing/agc2/rnn_vad/pitch_search.o \
+	modules/audio_processing/agc2/rnn_vad/pitch_search_internal.o \
+	modules/audio_processing/agc2/rnn_vad/rnn.o \
+	modules/audio_processing/agc2/rnn_vad/rnn_fc.o \
+	modules/audio_processing/agc2/rnn_vad/rnn_gru.o \
+	modules/audio_processing/agc2/rnn_vad/spectral_features.o \
+	modules/audio_processing/agc2/rnn_vad/spectral_features_internal.o \
+	modules/audio_processing/agc2/cpu_features.o
+
+CXX_STATIC_LIBRARY(rnn_vad.pic.a): \
+	CPPFLAGS += -I.
+
+CXX_STATIC_LIBRARY(rnn_vad.pic.a): \
+	$(rnn_vad_CXX_OBJECTS)
+
+rnn_vad: CXX_STATIC_LIBRARY(rnn_vad.pic.a)
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search.cc
index c6c3e1b..77a1188 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search.cc
@@ -18,8 +18,9 @@
 namespace webrtc {
 namespace rnn_vad {
 
-PitchEstimator::PitchEstimator()
-    : y_energy_24kHz_(kRefineNumLags24kHz, 0.f),
+PitchEstimator::PitchEstimator(const AvailableCpuFeatures& cpu_features)
+    : cpu_features_(cpu_features),
+      y_energy_24kHz_(kRefineNumLags24kHz, 0.f),
       pitch_buffer_12kHz_(kBufSize12kHz),
       auto_correlation_12kHz_(kNumLags12kHz) {}
 
@@ -35,12 +36,13 @@
   RTC_DCHECK_EQ(auto_correlation_12kHz_.size(),
                 auto_correlation_12kHz_view.size());
 
+  // TODO(bugs.chromium.org/10480): Use `cpu_features_` to estimate pitch.
   // Perform the initial pitch search at 12 kHz.
   Decimate2x(pitch_buffer, pitch_buffer_12kHz_view);
   auto_corr_calculator_.ComputeOnPitchBuffer(pitch_buffer_12kHz_view,
                                              auto_correlation_12kHz_view);
   CandidatePitchPeriods pitch_periods = ComputePitchPeriod12kHz(
-      pitch_buffer_12kHz_view, auto_correlation_12kHz_view);
+      pitch_buffer_12kHz_view, auto_correlation_12kHz_view, cpu_features_);
   // The refinement is done using the pitch buffer that contains 24 kHz samples.
   // Therefore, adapt the inverted lags in |pitch_candidates_inv_lags| from 12
   // to 24 kHz.
@@ -52,14 +54,15 @@
   rtc::ArrayView<float, kRefineNumLags24kHz> y_energy_24kHz_view(
       y_energy_24kHz_.data(), kRefineNumLags24kHz);
   RTC_DCHECK_EQ(y_energy_24kHz_.size(), y_energy_24kHz_view.size());
-  ComputeSlidingFrameSquareEnergies24kHz(pitch_buffer, y_energy_24kHz_view);
+  ComputeSlidingFrameSquareEnergies24kHz(pitch_buffer, y_energy_24kHz_view,
+                                         cpu_features_);
   // Estimation at 48 kHz.
-  const int pitch_lag_48kHz =
-      ComputePitchPeriod48kHz(pitch_buffer, y_energy_24kHz_view, pitch_periods);
+  const int pitch_lag_48kHz = ComputePitchPeriod48kHz(
+      pitch_buffer, y_energy_24kHz_view, pitch_periods, cpu_features_);
   last_pitch_48kHz_ = ComputeExtendedPitchPeriod48kHz(
       pitch_buffer, y_energy_24kHz_view,
       /*initial_pitch_period_48kHz=*/kMaxPitch48kHz - pitch_lag_48kHz,
-      last_pitch_48kHz_);
+      last_pitch_48kHz_, cpu_features_);
   return last_pitch_48kHz_.period;
 }
 
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search.h b/modules/audio_processing/agc2/rnn_vad/pitch_search.h
index e96a2dc..42c448e 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search.h
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search.h
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include "api/array_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/rnn_vad/auto_correlation.h"
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
 #include "modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h"
@@ -26,7 +27,7 @@
 // Pitch estimator.
 class PitchEstimator {
  public:
-  PitchEstimator();
+  explicit PitchEstimator(const AvailableCpuFeatures& cpu_features);
   PitchEstimator(const PitchEstimator&) = delete;
   PitchEstimator& operator=(const PitchEstimator&) = delete;
   ~PitchEstimator();
@@ -39,6 +40,7 @@
     return last_pitch_48kHz_.strength;
   }
 
+  const AvailableCpuFeatures cpu_features_;
   PitchInfo last_pitch_48kHz_{};
   AutoCorrelationCalculator auto_corr_calculator_;
   std::vector<float> y_energy_24kHz_;
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc
index 262c386..0b8a77e 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.cc
@@ -18,9 +18,11 @@
 #include <numeric>
 
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
+#include "modules/audio_processing/agc2/rnn_vad/vector_math.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_compare.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/system/arch.h"
 
 namespace webrtc {
 namespace rnn_vad {
@@ -28,14 +30,14 @@
 
 float ComputeAutoCorrelation(
     int inverted_lag,
-    rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer) {
+    rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
+    const VectorMath& vector_math) {
   RTC_DCHECK_LT(inverted_lag, kBufSize24kHz);
   RTC_DCHECK_LT(inverted_lag, kRefineNumLags24kHz);
   static_assert(kMaxPitch24kHz < kBufSize24kHz, "");
-  // TODO(bugs.webrtc.org/9076): Maybe optimize using vectorization.
-  return std::inner_product(pitch_buffer.begin() + kMaxPitch24kHz,
-                            pitch_buffer.end(),
-                            pitch_buffer.begin() + inverted_lag, 0.f);
+  return vector_math.DotProduct(
+      pitch_buffer.subview(/*offset=*/kMaxPitch24kHz),
+      pitch_buffer.subview(inverted_lag, kFrameSize20ms24kHz));
 }
 
 // Given an auto-correlation coefficient `curr_auto_correlation` and its
@@ -66,15 +68,16 @@
 // output sample rate is twice as that of |lag|.
 int PitchPseudoInterpolationLagPitchBuf(
     int lag,
-    rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer) {
+    rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
+    const VectorMath& vector_math) {
   int offset = 0;
   // Cannot apply pseudo-interpolation at the boundaries.
   if (lag > 0 && lag < kMaxPitch24kHz) {
     const int inverted_lag = kMaxPitch24kHz - lag;
     offset = GetPitchPseudoInterpolationOffset(
-        ComputeAutoCorrelation(inverted_lag + 1, pitch_buffer),
-        ComputeAutoCorrelation(inverted_lag, pitch_buffer),
-        ComputeAutoCorrelation(inverted_lag - 1, pitch_buffer));
+        ComputeAutoCorrelation(inverted_lag + 1, pitch_buffer, vector_math),
+        ComputeAutoCorrelation(inverted_lag, pitch_buffer, vector_math),
+        ComputeAutoCorrelation(inverted_lag - 1, pitch_buffer, vector_math));
   }
   return 2 * lag + offset;
 }
@@ -153,7 +156,8 @@
     Range inverted_lags,
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
     rtc::ArrayView<float, kInitialNumLags24kHz> auto_correlation,
-    InvertedLagsIndex& inverted_lags_index) {
+    InvertedLagsIndex& inverted_lags_index,
+    const VectorMath& vector_math) {
   // Check valid range.
   RTC_DCHECK_LE(inverted_lags.min, inverted_lags.max);
   // Trick to avoid zero initialization of `auto_correlation`.
@@ -170,7 +174,7 @@
   for (int inverted_lag = inverted_lags.min; inverted_lag <= inverted_lags.max;
        ++inverted_lag) {
     auto_correlation[inverted_lag] =
-        ComputeAutoCorrelation(inverted_lag, pitch_buffer);
+        ComputeAutoCorrelation(inverted_lag, pitch_buffer, vector_math);
     inverted_lags_index.Append(inverted_lag);
   }
 }
@@ -181,7 +185,8 @@
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
     rtc::ArrayView<const int> inverted_lags,
     rtc::ArrayView<const float, kInitialNumLags24kHz> auto_correlation,
-    rtc::ArrayView<const float, kRefineNumLags24kHz> y_energy) {
+    rtc::ArrayView<const float, kRefineNumLags24kHz> y_energy,
+    const VectorMath& vector_math) {
   static_assert(kMaxPitch24kHz > kInitialNumLags24kHz, "");
   static_assert(kMaxPitch24kHz < kBufSize24kHz, "");
   int best_inverted_lag = 0;     // Pitch period.
@@ -289,10 +294,12 @@
 
 void ComputeSlidingFrameSquareEnergies24kHz(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
-    rtc::ArrayView<float, kRefineNumLags24kHz> y_energy) {
-  float yy = std::inner_product(pitch_buffer.begin(),
-                                pitch_buffer.begin() + kFrameSize20ms24kHz,
-                                pitch_buffer.begin(), 0.f);
+    rtc::ArrayView<float, kRefineNumLags24kHz> y_energy,
+    AvailableCpuFeatures cpu_features) {
+  VectorMath vector_math(cpu_features);
+  static_assert(kFrameSize20ms24kHz < kBufSize24kHz, "");
+  const auto frame_20ms_view = pitch_buffer.subview(0, kFrameSize20ms24kHz);
+  float yy = vector_math.DotProduct(frame_20ms_view, frame_20ms_view);
   y_energy[0] = yy;
   static_assert(kMaxPitch24kHz - 1 + kFrameSize20ms24kHz < kBufSize24kHz, "");
   static_assert(kMaxPitch24kHz < kRefineNumLags24kHz, "");
@@ -307,7 +314,8 @@
 
 CandidatePitchPeriods ComputePitchPeriod12kHz(
     rtc::ArrayView<const float, kBufSize12kHz> pitch_buffer,
-    rtc::ArrayView<const float, kNumLags12kHz> auto_correlation) {
+    rtc::ArrayView<const float, kNumLags12kHz> auto_correlation,
+    AvailableCpuFeatures cpu_features) {
   static_assert(kMaxPitch12kHz > kNumLags12kHz, "");
   static_assert(kMaxPitch12kHz < kBufSize12kHz, "");
 
@@ -326,10 +334,10 @@
     }
   };
 
-  // TODO(bugs.webrtc.org/9076): Maybe optimize using vectorization.
-  float denominator = std::inner_product(
-      pitch_buffer.begin(), pitch_buffer.begin() + kFrameSize20ms12kHz + 1,
-      pitch_buffer.begin(), 1.f);
+  VectorMath vector_math(cpu_features);
+  static_assert(kFrameSize20ms12kHz + 1 < kBufSize12kHz, "");
+  const auto frame_view = pitch_buffer.subview(0, kFrameSize20ms12kHz + 1);
+  float denominator = 1.f + vector_math.DotProduct(frame_view, frame_view);
   // Search best and second best pitches by looking at the scaled
   // auto-correlation.
   PitchCandidate best;
@@ -364,7 +372,8 @@
 int ComputePitchPeriod48kHz(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
     rtc::ArrayView<const float, kRefineNumLags24kHz> y_energy,
-    CandidatePitchPeriods pitch_candidates) {
+    CandidatePitchPeriods pitch_candidates,
+    AvailableCpuFeatures cpu_features) {
   // Compute the auto-correlation terms only for neighbors of the two pitch
   // candidates (best and second best).
   std::array<float, kInitialNumLags24kHz> auto_correlation;
@@ -382,26 +391,28 @@
   // Check `r1` precedes `r2`.
   RTC_DCHECK_LE(r1.min, r2.min);
   RTC_DCHECK_LE(r1.max, r2.max);
+  VectorMath vector_math(cpu_features);
   if (r1.max + 1 >= r2.min) {
     // Overlapping or adjacent ranges.
     ComputeAutoCorrelation({r1.min, r2.max}, pitch_buffer, auto_correlation,
-                           inverted_lags_index);
+                           inverted_lags_index, vector_math);
   } else {
     // Disjoint ranges.
     ComputeAutoCorrelation(r1, pitch_buffer, auto_correlation,
-                           inverted_lags_index);
+                           inverted_lags_index, vector_math);
     ComputeAutoCorrelation(r2, pitch_buffer, auto_correlation,
-                           inverted_lags_index);
+                           inverted_lags_index, vector_math);
   }
   return ComputePitchPeriod48kHz(pitch_buffer, inverted_lags_index,
-                                 auto_correlation, y_energy);
+                                 auto_correlation, y_energy, vector_math);
 }
 
 PitchInfo ComputeExtendedPitchPeriod48kHz(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
     rtc::ArrayView<const float, kRefineNumLags24kHz> y_energy,
     int initial_pitch_period_48kHz,
-    PitchInfo last_pitch_48kHz) {
+    PitchInfo last_pitch_48kHz,
+    AvailableCpuFeatures cpu_features) {
   RTC_DCHECK_LE(kMinPitch48kHz, initial_pitch_period_48kHz);
   RTC_DCHECK_LE(initial_pitch_period_48kHz, kMaxPitch48kHz);
 
@@ -419,13 +430,14 @@
     RTC_DCHECK_GE(x_energy * y_energy, 0.f);
     return xy / std::sqrt(1.f + x_energy * y_energy);
   };
+  VectorMath vector_math(cpu_features);
 
   // Initialize the best pitch candidate with `initial_pitch_period_48kHz`.
   RefinedPitchCandidate best_pitch;
   best_pitch.period =
       std::min(initial_pitch_period_48kHz / 2, kMaxPitch24kHz - 1);
-  best_pitch.xy =
-      ComputeAutoCorrelation(kMaxPitch24kHz - best_pitch.period, pitch_buffer);
+  best_pitch.xy = ComputeAutoCorrelation(kMaxPitch24kHz - best_pitch.period,
+                                         pitch_buffer, vector_math);
   best_pitch.y_energy = y_energy[kMaxPitch24kHz - best_pitch.period];
   best_pitch.strength = pitch_strength(best_pitch.xy, best_pitch.y_energy);
   // Keep a copy of the initial pitch candidate.
@@ -463,9 +475,11 @@
     // |alternative_pitch.period| by also looking at its possible sub-harmonic
     // |dual_alternative_period|.
     const float xy_primary_period = ComputeAutoCorrelation(
-        kMaxPitch24kHz - alternative_pitch.period, pitch_buffer);
+        kMaxPitch24kHz - alternative_pitch.period, pitch_buffer, vector_math);
+    // TODO(webrtc:10480): Copy `xy_primary_period` if the secondary period is
+    // equal to the primary one.
     const float xy_secondary_period = ComputeAutoCorrelation(
-        kMaxPitch24kHz - dual_alternative_period, pitch_buffer);
+        kMaxPitch24kHz - dual_alternative_period, pitch_buffer, vector_math);
     const float xy = 0.5f * (xy_primary_period + xy_secondary_period);
     const float yy =
         0.5f * (y_energy[kMaxPitch24kHz - alternative_pitch.period] +
@@ -489,8 +503,8 @@
           : best_pitch.xy / (best_pitch.y_energy + 1.f);
   final_pitch_strength = std::min(best_pitch.strength, final_pitch_strength);
   int final_pitch_period_48kHz = std::max(
-      kMinPitch48kHz,
-      PitchPseudoInterpolationLagPitchBuf(best_pitch.period, pitch_buffer));
+      kMinPitch48kHz, PitchPseudoInterpolationLagPitchBuf(
+                          best_pitch.period, pitch_buffer, vector_math));
 
   return {final_pitch_period_48kHz, final_pitch_strength};
 }
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h
index 0af55f8..aa2dd13 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h
@@ -17,6 +17,7 @@
 #include <utility>
 
 #include "api/array_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
 
 namespace webrtc {
@@ -65,7 +66,8 @@
 // buffer. The indexes of `y_energy` are inverted lags.
 void ComputeSlidingFrameSquareEnergies24kHz(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
-    rtc::ArrayView<float, kRefineNumLags24kHz> y_energy);
+    rtc::ArrayView<float, kRefineNumLags24kHz> y_energy,
+    AvailableCpuFeatures cpu_features);
 
 // Top-2 pitch period candidates. Unit: number of samples - i.e., inverted lags.
 struct CandidatePitchPeriods {
@@ -78,7 +80,8 @@
 // indexes).
 CandidatePitchPeriods ComputePitchPeriod12kHz(
     rtc::ArrayView<const float, kBufSize12kHz> pitch_buffer,
-    rtc::ArrayView<const float, kNumLags12kHz> auto_correlation);
+    rtc::ArrayView<const float, kNumLags12kHz> auto_correlation,
+    AvailableCpuFeatures cpu_features);
 
 // Computes the pitch period at 48 kHz given a view on the 24 kHz pitch buffer,
 // the energies for the sliding frames `y` at 24 kHz and the pitch period
@@ -86,7 +89,8 @@
 int ComputePitchPeriod48kHz(
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
     rtc::ArrayView<const float, kRefineNumLags24kHz> y_energy,
-    CandidatePitchPeriods pitch_candidates_24kHz);
+    CandidatePitchPeriods pitch_candidates_24kHz,
+    AvailableCpuFeatures cpu_features);
 
 struct PitchInfo {
   int period;
@@ -101,7 +105,8 @@
     rtc::ArrayView<const float, kBufSize24kHz> pitch_buffer,
     rtc::ArrayView<const float, kRefineNumLags24kHz> y_energy,
     int initial_pitch_period_48kHz,
-    PitchInfo last_pitch_48kHz);
+    PitchInfo last_pitch_48kHz,
+    AvailableCpuFeatures cpu_features);
 
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc
index 152d569..2a6e68f 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_internal_unittest.cc
@@ -11,181 +11,207 @@
 #include "modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h"
 
 #include <array>
+#include <string>
 #include <tuple>
 
 #include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
+#include "rtc_base/strings/string_builder.h"
 // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
 // #include "test/fpe_observer.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 constexpr int kTestPitchPeriodsLow = 3 * kMinPitch48kHz / 2;
 constexpr int kTestPitchPeriodsHigh = (3 * kMinPitch48kHz + kMaxPitch48kHz) / 2;
 
-constexpr float kTestPitchGainsLow = 0.35f;
-constexpr float kTestPitchGainsHigh = 0.75f;
+constexpr float kTestPitchStrengthLow = 0.35f;
+constexpr float kTestPitchStrengthHigh = 0.75f;
 
-}  // namespace
+template <class T>
+std::string PrintTestIndexAndCpuFeatures(
+    const ::testing::TestParamInfo<T>& info) {
+  rtc::StringBuilder builder;
+  builder << info.index << "_" << info.param.cpu_features.ToString();
+  return builder.str();
+}
+
+// Finds the relevant CPU features combinations to test.
+std::vector<AvailableCpuFeatures> GetCpuFeaturesToTest() {
+  std::vector<AvailableCpuFeatures> v;
+  v.push_back(NoAvailableCpuFeatures());
+  AvailableCpuFeatures available = GetAvailableCpuFeatures();
+  if (available.avx2) {
+    v.push_back({/*sse2=*/false, /*avx2=*/true, /*neon=*/false});
+  }
+  if (available.sse2) {
+    v.push_back({/*sse2=*/true, /*avx2=*/false, /*neon=*/false});
+  }
+  return v;
+}
 
 // Checks that the frame-wise sliding square energy function produces output
 // within tolerance given test input data.
 TEST(RnnVadTest, ComputeSlidingFrameSquareEnergies24kHzWithinTolerance) {
+  const AvailableCpuFeatures cpu_features = GetAvailableCpuFeatures();
+
   PitchTestData test_data;
-  std::array<float, kNumPitchBufSquareEnergies> computed_output;
+  std::array<float, kRefineNumLags24kHz> computed_output;
   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
   // FloatingPointExceptionObserver fpe_observer;
-  ComputeSlidingFrameSquareEnergies24kHz(test_data.GetPitchBufView(),
-                                         computed_output);
-  auto square_energies_view = test_data.GetPitchBufSquareEnergiesView();
+  ComputeSlidingFrameSquareEnergies24kHz(test_data.PitchBuffer24kHzView(),
+                                         computed_output, cpu_features);
+  auto square_energies_view = test_data.SquareEnergies24kHzView();
   ExpectNearAbsolute({square_energies_view.data(), square_energies_view.size()},
                      computed_output, 1e-3f);
 }
 
 // Checks that the estimated pitch period is bit-exact given test input data.
 TEST(RnnVadTest, ComputePitchPeriod12kHzBitExactness) {
+  const AvailableCpuFeatures cpu_features = GetAvailableCpuFeatures();
+
   PitchTestData test_data;
   std::array<float, kBufSize12kHz> pitch_buf_decimated;
-  Decimate2x(test_data.GetPitchBufView(), pitch_buf_decimated);
+  Decimate2x(test_data.PitchBuffer24kHzView(), pitch_buf_decimated);
   CandidatePitchPeriods pitch_candidates;
   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
   // FloatingPointExceptionObserver fpe_observer;
-  auto auto_corr_view = test_data.GetPitchBufAutoCorrCoeffsView();
-  pitch_candidates =
-      ComputePitchPeriod12kHz(pitch_buf_decimated, auto_corr_view);
+  pitch_candidates = ComputePitchPeriod12kHz(
+      pitch_buf_decimated, test_data.AutoCorrelation12kHzView(), cpu_features);
   EXPECT_EQ(pitch_candidates.best, 140);
   EXPECT_EQ(pitch_candidates.second_best, 142);
 }
 
 // Checks that the refined pitch period is bit-exact given test input data.
 TEST(RnnVadTest, ComputePitchPeriod48kHzBitExactness) {
+  const AvailableCpuFeatures cpu_features = GetAvailableCpuFeatures();
+
   PitchTestData test_data;
   std::vector<float> y_energy(kRefineNumLags24kHz);
   rtc::ArrayView<float, kRefineNumLags24kHz> y_energy_view(y_energy.data(),
                                                            kRefineNumLags24kHz);
-  ComputeSlidingFrameSquareEnergies24kHz(test_data.GetPitchBufView(),
-                                         y_energy_view);
+  ComputeSlidingFrameSquareEnergies24kHz(test_data.PitchBuffer24kHzView(),
+                                         y_energy_view, cpu_features);
   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
   // FloatingPointExceptionObserver fpe_observer;
-  EXPECT_EQ(ComputePitchPeriod48kHz(test_data.GetPitchBufView(), y_energy_view,
-                                    /*pitch_candidates=*/{280, 284}),
-            560);
-  EXPECT_EQ(ComputePitchPeriod48kHz(test_data.GetPitchBufView(), y_energy_view,
-                                    /*pitch_candidates=*/{260, 284}),
-            568);
+  EXPECT_EQ(
+      ComputePitchPeriod48kHz(test_data.PitchBuffer24kHzView(), y_energy_view,
+                              /*pitch_candidates=*/{280, 284}, cpu_features),
+      560);
+  EXPECT_EQ(
+      ComputePitchPeriod48kHz(test_data.PitchBuffer24kHzView(), y_energy_view,
+                              /*pitch_candidates=*/{260, 284}, cpu_features),
+      568);
 }
 
-class PitchCandidatesParametrization
-    : public ::testing::TestWithParam<CandidatePitchPeriods> {
- protected:
-  CandidatePitchPeriods GetPitchCandidates() const { return GetParam(); }
-  CandidatePitchPeriods GetSwappedPitchCandidates() const {
-    CandidatePitchPeriods candidate = GetParam();
-    return {candidate.second_best, candidate.best};
-  }
+struct PitchCandidatesParameters {
+  CandidatePitchPeriods pitch_candidates;
+  AvailableCpuFeatures cpu_features;
 };
 
+class PitchCandidatesParametrization
+    : public ::testing::TestWithParam<PitchCandidatesParameters> {};
+
 // Checks that the result of `ComputePitchPeriod48kHz()` does not depend on the
 // order of the input pitch candidates.
 TEST_P(PitchCandidatesParametrization,
        ComputePitchPeriod48kHzOrderDoesNotMatter) {
+  const PitchCandidatesParameters params = GetParam();
+  const CandidatePitchPeriods swapped_pitch_candidates{
+      params.pitch_candidates.second_best, params.pitch_candidates.best};
+
   PitchTestData test_data;
   std::vector<float> y_energy(kRefineNumLags24kHz);
   rtc::ArrayView<float, kRefineNumLags24kHz> y_energy_view(y_energy.data(),
                                                            kRefineNumLags24kHz);
-  ComputeSlidingFrameSquareEnergies24kHz(test_data.GetPitchBufView(),
-                                         y_energy_view);
-  EXPECT_EQ(ComputePitchPeriod48kHz(test_data.GetPitchBufView(), y_energy_view,
-                                    GetPitchCandidates()),
-            ComputePitchPeriod48kHz(test_data.GetPitchBufView(), y_energy_view,
-                                    GetSwappedPitchCandidates()));
+  ComputeSlidingFrameSquareEnergies24kHz(test_data.PitchBuffer24kHzView(),
+                                         y_energy_view, params.cpu_features);
+  EXPECT_EQ(
+      ComputePitchPeriod48kHz(test_data.PitchBuffer24kHzView(), y_energy_view,
+                              params.pitch_candidates, params.cpu_features),
+      ComputePitchPeriod48kHz(test_data.PitchBuffer24kHzView(), y_energy_view,
+                              swapped_pitch_candidates, params.cpu_features));
 }
 
-INSTANTIATE_TEST_SUITE_P(RnnVadTest,
-                         PitchCandidatesParametrization,
-                         ::testing::Values(CandidatePitchPeriods{0, 2},
-                                           CandidatePitchPeriods{260, 284},
-                                           CandidatePitchPeriods{280, 284},
-                                           CandidatePitchPeriods{
-                                               kInitialNumLags24kHz - 2,
-                                               kInitialNumLags24kHz - 1}));
+std::vector<PitchCandidatesParameters> CreatePitchCandidatesParameters() {
+  std::vector<PitchCandidatesParameters> v;
+  for (AvailableCpuFeatures cpu_features : GetCpuFeaturesToTest()) {
+    v.push_back({{0, 2}, cpu_features});
+    v.push_back({{260, 284}, cpu_features});
+    v.push_back({{280, 284}, cpu_features});
+    v.push_back(
+        {{kInitialNumLags24kHz - 2, kInitialNumLags24kHz - 1}, cpu_features});
+  }
+  return v;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    RnnVadTest,
+    PitchCandidatesParametrization,
+    ::testing::ValuesIn(CreatePitchCandidatesParameters()),
+    PrintTestIndexAndCpuFeatures<PitchCandidatesParameters>);
+
+struct ExtendedPitchPeriodSearchParameters {
+  int initial_pitch_period;
+  PitchInfo last_pitch;
+  PitchInfo expected_pitch;
+  AvailableCpuFeatures cpu_features;
+};
 
 class ExtendedPitchPeriodSearchParametrizaion
-    : public ::testing::TestWithParam<std::tuple<int, int, float, int, float>> {
- protected:
-  int GetInitialPitchPeriod() const { return std::get<0>(GetParam()); }
-  int GetLastPitchPeriod() const { return std::get<1>(GetParam()); }
-  float GetLastPitchStrength() const { return std::get<2>(GetParam()); }
-  int GetExpectedPitchPeriod() const { return std::get<3>(GetParam()); }
-  float GetExpectedPitchStrength() const { return std::get<4>(GetParam()); }
-};
+    : public ::testing::TestWithParam<ExtendedPitchPeriodSearchParameters> {};
 
 // Checks that the computed pitch period is bit-exact and that the computed
 // pitch strength is within tolerance given test input data.
 TEST_P(ExtendedPitchPeriodSearchParametrizaion,
        PeriodBitExactnessGainWithinTolerance) {
+  const ExtendedPitchPeriodSearchParameters params = GetParam();
+
   PitchTestData test_data;
   std::vector<float> y_energy(kRefineNumLags24kHz);
   rtc::ArrayView<float, kRefineNumLags24kHz> y_energy_view(y_energy.data(),
                                                            kRefineNumLags24kHz);
-  ComputeSlidingFrameSquareEnergies24kHz(test_data.GetPitchBufView(),
-                                         y_energy_view);
+  ComputeSlidingFrameSquareEnergies24kHz(test_data.PitchBuffer24kHzView(),
+                                         y_energy_view, params.cpu_features);
   // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
   // FloatingPointExceptionObserver fpe_observer;
   const auto computed_output = ComputeExtendedPitchPeriod48kHz(
-      test_data.GetPitchBufView(), y_energy_view, GetInitialPitchPeriod(),
-      {GetLastPitchPeriod(), GetLastPitchStrength()});
-  EXPECT_EQ(GetExpectedPitchPeriod(), computed_output.period);
-  EXPECT_NEAR(GetExpectedPitchStrength(), computed_output.strength, 1e-6f);
+      test_data.PitchBuffer24kHzView(), y_energy_view,
+      params.initial_pitch_period, params.last_pitch, params.cpu_features);
+  EXPECT_EQ(params.expected_pitch.period, computed_output.period);
+  EXPECT_NEAR(params.expected_pitch.strength, computed_output.strength, 1e-6f);
+}
+
+std::vector<ExtendedPitchPeriodSearchParameters>
+CreateExtendedPitchPeriodSearchParameters() {
+  std::vector<ExtendedPitchPeriodSearchParameters> v;
+  for (AvailableCpuFeatures cpu_features : GetCpuFeaturesToTest()) {
+    for (int last_pitch_period :
+         {kTestPitchPeriodsLow, kTestPitchPeriodsHigh}) {
+      for (float last_pitch_strength :
+           {kTestPitchStrengthLow, kTestPitchStrengthHigh}) {
+        v.push_back({kTestPitchPeriodsLow,
+                     {last_pitch_period, last_pitch_strength},
+                     {91, -0.0188608f},
+                     cpu_features});
+        v.push_back({kTestPitchPeriodsHigh,
+                     {last_pitch_period, last_pitch_strength},
+                     {475, -0.0904344f},
+                     cpu_features});
+      }
+    }
+  }
+  return v;
 }
 
 INSTANTIATE_TEST_SUITE_P(
     RnnVadTest,
     ExtendedPitchPeriodSearchParametrizaion,
-    ::testing::Values(std::make_tuple(kTestPitchPeriodsLow,
-                                      kTestPitchPeriodsLow,
-                                      kTestPitchGainsLow,
-                                      91,
-                                      -0.0188608f),
-                      std::make_tuple(kTestPitchPeriodsLow,
-                                      kTestPitchPeriodsLow,
-                                      kTestPitchGainsHigh,
-                                      91,
-                                      -0.0188608f),
-                      std::make_tuple(kTestPitchPeriodsLow,
-                                      kTestPitchPeriodsHigh,
-                                      kTestPitchGainsLow,
-                                      91,
-                                      -0.0188608f),
-                      std::make_tuple(kTestPitchPeriodsLow,
-                                      kTestPitchPeriodsHigh,
-                                      kTestPitchGainsHigh,
-                                      91,
-                                      -0.0188608f),
-                      std::make_tuple(kTestPitchPeriodsHigh,
-                                      kTestPitchPeriodsLow,
-                                      kTestPitchGainsLow,
-                                      475,
-                                      -0.0904344f),
-                      std::make_tuple(kTestPitchPeriodsHigh,
-                                      kTestPitchPeriodsLow,
-                                      kTestPitchGainsHigh,
-                                      475,
-                                      -0.0904344f),
-                      std::make_tuple(kTestPitchPeriodsHigh,
-                                      kTestPitchPeriodsHigh,
-                                      kTestPitchGainsLow,
-                                      475,
-                                      -0.0904344f),
-                      std::make_tuple(kTestPitchPeriodsHigh,
-                                      kTestPitchPeriodsHigh,
-                                      kTestPitchGainsHigh,
-                                      475,
-                                      -0.0904344f)));
+    ::testing::ValuesIn(CreateExtendedPitchPeriodSearchParameters()),
+    PrintTestIndexAndCpuFeatures<ExtendedPitchPeriodSearchParameters>);
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc b/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc
index 98b791e..79b44b9 100644
--- a/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/pitch_search_unittest.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 #include <vector>
 
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/rnn_vad/pitch_search_internal.h"
 #include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
 // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
@@ -25,19 +26,20 @@
 // Checks that the computed pitch period is bit-exact and that the computed
 // pitch gain is within tolerance given test input data.
 TEST(RnnVadTest, PitchSearchWithinTolerance) {
-  auto lp_residual_reader = test::CreateLpResidualAndPitchPeriodGainReader();
-  const int num_frames = std::min(lp_residual_reader.second, 300);  // Max 3 s.
+  ChunksFileReader reader = CreateLpResidualAndPitchInfoReader();
+  const int num_frames = std::min(reader.num_chunks, 300);  // Max 3 s.
   std::vector<float> lp_residual(kBufSize24kHz);
   float expected_pitch_period, expected_pitch_strength;
-  PitchEstimator pitch_estimator;
+  const AvailableCpuFeatures cpu_features = GetAvailableCpuFeatures();
+  PitchEstimator pitch_estimator(cpu_features);
   {
     // TODO(bugs.webrtc.org/8948): Add when the issue is fixed.
     // FloatingPointExceptionObserver fpe_observer;
     for (int i = 0; i < num_frames; ++i) {
       SCOPED_TRACE(i);
-      lp_residual_reader.first->ReadChunk(lp_residual);
-      lp_residual_reader.first->ReadValue(&expected_pitch_period);
-      lp_residual_reader.first->ReadValue(&expected_pitch_strength);
+      ASSERT_TRUE(reader.reader->ReadChunk(lp_residual));
+      ASSERT_TRUE(reader.reader->ReadValue(expected_pitch_period));
+      ASSERT_TRUE(reader.reader->ReadValue(expected_pitch_strength));
       int pitch_period =
           pitch_estimator.Estimate({lp_residual.data(), kBufSize24kHz});
       EXPECT_EQ(expected_pitch_period, pitch_period);
diff --git a/modules/audio_processing/agc2/rnn_vad/ring_buffer_unittest.cc b/modules/audio_processing/agc2/rnn_vad/ring_buffer_unittest.cc
index 8b061a9..d11d4ea 100644
--- a/modules/audio_processing/agc2/rnn_vad/ring_buffer_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/ring_buffer_unittest.cc
@@ -14,7 +14,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 // Compare the elements of two given array views.
@@ -64,8 +63,6 @@
   }
 }
 
-}  // namespace
-
 // Check that for different delays, different views are returned.
 TEST(RnnVadTest, RingBufferArrayViews) {
   constexpr int s = 3;
@@ -110,6 +107,6 @@
   TestRingBuffer<float, 5, 5>();
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn.cc b/modules/audio_processing/agc2/rnn_vad/rnn.cc
index 2072a68..475bef9 100644
--- a/modules/audio_processing/agc2/rnn_vad/rnn.cc
+++ b/modules/audio_processing/agc2/rnn_vad/rnn.cc
@@ -10,417 +10,81 @@
 
 #include "modules/audio_processing/agc2/rnn_vad/rnn.h"
 
-// Defines WEBRTC_ARCH_X86_FAMILY, used below.
-#include "rtc_base/system/arch.h"
-
-#if defined(WEBRTC_HAS_NEON)
-#include <arm_neon.h>
-#endif
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-#include <emmintrin.h>
-#endif
-#include <algorithm>
-#include <array>
-#include <cmath>
-#include <numeric>
-
 #include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_conversions.h"
-#include "third_party/rnnoise/src/rnn_activations.h"
 #include "third_party/rnnoise/src/rnn_vad_weights.h"
 
 namespace webrtc {
 namespace rnn_vad {
 namespace {
 
-using rnnoise::kWeightsScale;
-
-using rnnoise::kInputLayerInputSize;
+using ::rnnoise::kInputLayerInputSize;
 static_assert(kFeatureVectorSize == kInputLayerInputSize, "");
-using rnnoise::kInputDenseBias;
-using rnnoise::kInputDenseWeights;
-using rnnoise::kInputLayerOutputSize;
-static_assert(kInputLayerOutputSize <= kFullyConnectedLayersMaxUnits,
-              "Increase kFullyConnectedLayersMaxUnits.");
+using ::rnnoise::kInputDenseBias;
+using ::rnnoise::kInputDenseWeights;
+using ::rnnoise::kInputLayerOutputSize;
+static_assert(kInputLayerOutputSize <= kFullyConnectedLayerMaxUnits, "");
 
-using rnnoise::kHiddenGruBias;
-using rnnoise::kHiddenGruRecurrentWeights;
-using rnnoise::kHiddenGruWeights;
-using rnnoise::kHiddenLayerOutputSize;
-static_assert(kHiddenLayerOutputSize <= kRecurrentLayersMaxUnits,
-              "Increase kRecurrentLayersMaxUnits.");
+using ::rnnoise::kHiddenGruBias;
+using ::rnnoise::kHiddenGruRecurrentWeights;
+using ::rnnoise::kHiddenGruWeights;
+using ::rnnoise::kHiddenLayerOutputSize;
+static_assert(kHiddenLayerOutputSize <= kGruLayerMaxUnits, "");
 
-using rnnoise::kOutputDenseBias;
-using rnnoise::kOutputDenseWeights;
-using rnnoise::kOutputLayerOutputSize;
-static_assert(kOutputLayerOutputSize <= kFullyConnectedLayersMaxUnits,
-              "Increase kFullyConnectedLayersMaxUnits.");
-
-using rnnoise::SigmoidApproximated;
-using rnnoise::TansigApproximated;
-
-inline float RectifiedLinearUnit(float x) {
-  return x < 0.f ? 0.f : x;
-}
-
-std::vector<float> GetScaledParams(rtc::ArrayView<const int8_t> params) {
-  std::vector<float> scaled_params(params.size());
-  std::transform(params.begin(), params.end(), scaled_params.begin(),
-                 [](int8_t x) -> float {
-                   return rnnoise::kWeightsScale * static_cast<float>(x);
-                 });
-  return scaled_params;
-}
-
-// TODO(bugs.chromium.org/10480): Hard-code optimized layout and remove this
-// function to improve setup time.
-// Casts and scales |weights| and re-arranges the layout.
-std::vector<float> GetPreprocessedFcWeights(
-    rtc::ArrayView<const int8_t> weights,
-    int output_size) {
-  if (output_size == 1) {
-    return GetScaledParams(weights);
-  }
-  // Transpose, scale and cast.
-  const int input_size = rtc::CheckedDivExact(
-      rtc::dchecked_cast<int>(weights.size()), output_size);
-  std::vector<float> w(weights.size());
-  for (int o = 0; o < output_size; ++o) {
-    for (int i = 0; i < input_size; ++i) {
-      w[o * input_size + i] = rnnoise::kWeightsScale *
-                              static_cast<float>(weights[i * output_size + o]);
-    }
-  }
-  return w;
-}
-
-constexpr int kNumGruGates = 3;  // Update, reset, output.
-
-// TODO(bugs.chromium.org/10480): Hard-coded optimized layout and remove this
-// function to improve setup time.
-// Casts and scales |tensor_src| for a GRU layer and re-arranges the layout.
-// It works both for weights, recurrent weights and bias.
-std::vector<float> GetPreprocessedGruTensor(
-    rtc::ArrayView<const int8_t> tensor_src,
-    int output_size) {
-  // Transpose, cast and scale.
-  // |n| is the size of the first dimension of the 3-dim tensor |weights|.
-  const int n = rtc::CheckedDivExact(rtc::dchecked_cast<int>(tensor_src.size()),
-                                     output_size * kNumGruGates);
-  const int stride_src = kNumGruGates * output_size;
-  const int stride_dst = n * output_size;
-  std::vector<float> tensor_dst(tensor_src.size());
-  for (int g = 0; g < kNumGruGates; ++g) {
-    for (int o = 0; o < output_size; ++o) {
-      for (int i = 0; i < n; ++i) {
-        tensor_dst[g * stride_dst + o * n + i] =
-            rnnoise::kWeightsScale *
-            static_cast<float>(
-                tensor_src[i * stride_src + g * output_size + o]);
-      }
-    }
-  }
-  return tensor_dst;
-}
-
-void ComputeGruUpdateResetGates(int input_size,
-                                int output_size,
-                                rtc::ArrayView<const float> weights,
-                                rtc::ArrayView<const float> recurrent_weights,
-                                rtc::ArrayView<const float> bias,
-                                rtc::ArrayView<const float> input,
-                                rtc::ArrayView<const float> state,
-                                rtc::ArrayView<float> gate) {
-  for (int o = 0; o < output_size; ++o) {
-    gate[o] = bias[o];
-    for (int i = 0; i < input_size; ++i) {
-      gate[o] += input[i] * weights[o * input_size + i];
-    }
-    for (int s = 0; s < output_size; ++s) {
-      gate[o] += state[s] * recurrent_weights[o * output_size + s];
-    }
-    gate[o] = SigmoidApproximated(gate[o]);
-  }
-}
-
-void ComputeGruOutputGate(int input_size,
-                          int output_size,
-                          rtc::ArrayView<const float> weights,
-                          rtc::ArrayView<const float> recurrent_weights,
-                          rtc::ArrayView<const float> bias,
-                          rtc::ArrayView<const float> input,
-                          rtc::ArrayView<const float> state,
-                          rtc::ArrayView<const float> reset,
-                          rtc::ArrayView<float> gate) {
-  for (int o = 0; o < output_size; ++o) {
-    gate[o] = bias[o];
-    for (int i = 0; i < input_size; ++i) {
-      gate[o] += input[i] * weights[o * input_size + i];
-    }
-    for (int s = 0; s < output_size; ++s) {
-      gate[o] += state[s] * recurrent_weights[o * output_size + s] * reset[s];
-    }
-    gate[o] = RectifiedLinearUnit(gate[o]);
-  }
-}
-
-// Gated recurrent unit (GRU) layer un-optimized implementation.
-void ComputeGruLayerOutput(int input_size,
-                           int output_size,
-                           rtc::ArrayView<const float> input,
-                           rtc::ArrayView<const float> weights,
-                           rtc::ArrayView<const float> recurrent_weights,
-                           rtc::ArrayView<const float> bias,
-                           rtc::ArrayView<float> state) {
-  RTC_DCHECK_EQ(input_size, input.size());
-  // Stride and offset used to read parameter arrays.
-  const int stride_in = input_size * output_size;
-  const int stride_out = output_size * output_size;
-
-  // Update gate.
-  std::array<float, kRecurrentLayersMaxUnits> update;
-  ComputeGruUpdateResetGates(
-      input_size, output_size, weights.subview(0, stride_in),
-      recurrent_weights.subview(0, stride_out), bias.subview(0, output_size),
-      input, state, update);
-
-  // Reset gate.
-  std::array<float, kRecurrentLayersMaxUnits> reset;
-  ComputeGruUpdateResetGates(
-      input_size, output_size, weights.subview(stride_in, stride_in),
-      recurrent_weights.subview(stride_out, stride_out),
-      bias.subview(output_size, output_size), input, state, reset);
-
-  // Output gate.
-  std::array<float, kRecurrentLayersMaxUnits> output;
-  ComputeGruOutputGate(
-      input_size, output_size, weights.subview(2 * stride_in, stride_in),
-      recurrent_weights.subview(2 * stride_out, stride_out),
-      bias.subview(2 * output_size, output_size), input, state, reset, output);
-
-  // Update output through the update gates and update the state.
-  for (int o = 0; o < output_size; ++o) {
-    output[o] = update[o] * state[o] + (1.f - update[o]) * output[o];
-    state[o] = output[o];
-  }
-}
-
-// Fully connected layer un-optimized implementation.
-void ComputeFullyConnectedLayerOutput(
-    int input_size,
-    int output_size,
-    rtc::ArrayView<const float> input,
-    rtc::ArrayView<const float> bias,
-    rtc::ArrayView<const float> weights,
-    rtc::FunctionView<float(float)> activation_function,
-    rtc::ArrayView<float> output) {
-  RTC_DCHECK_EQ(input.size(), input_size);
-  RTC_DCHECK_EQ(bias.size(), output_size);
-  RTC_DCHECK_EQ(weights.size(), input_size * output_size);
-  for (int o = 0; o < output_size; ++o) {
-    output[o] = bias[o];
-    // TODO(bugs.chromium.org/9076): Benchmark how different layouts for
-    // |weights_| change the performance across different platforms.
-    for (int i = 0; i < input_size; ++i) {
-      output[o] += input[i] * weights[o * input_size + i];
-    }
-    output[o] = activation_function(output[o]);
-  }
-}
-
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-// Fully connected layer SSE2 implementation.
-void ComputeFullyConnectedLayerOutputSse2(
-    int input_size,
-    int output_size,
-    rtc::ArrayView<const float> input,
-    rtc::ArrayView<const float> bias,
-    rtc::ArrayView<const float> weights,
-    rtc::FunctionView<float(float)> activation_function,
-    rtc::ArrayView<float> output) {
-  RTC_DCHECK_EQ(input.size(), input_size);
-  RTC_DCHECK_EQ(bias.size(), output_size);
-  RTC_DCHECK_EQ(weights.size(), input_size * output_size);
-  const int input_size_by_4 = input_size >> 2;
-  const int offset = input_size & ~3;
-  __m128 sum_wx_128;
-  const float* v = reinterpret_cast<const float*>(&sum_wx_128);
-  for (int o = 0; o < output_size; ++o) {
-    // Perform 128 bit vector operations.
-    sum_wx_128 = _mm_set1_ps(0);
-    const float* x_p = input.data();
-    const float* w_p = weights.data() + o * input_size;
-    for (int i = 0; i < input_size_by_4; ++i, x_p += 4, w_p += 4) {
-      sum_wx_128 = _mm_add_ps(sum_wx_128,
-                              _mm_mul_ps(_mm_loadu_ps(x_p), _mm_loadu_ps(w_p)));
-    }
-    // Perform non-vector operations for any remaining items, sum up bias term
-    // and results from the vectorized code, and apply the activation function.
-    output[o] = activation_function(
-        std::inner_product(input.begin() + offset, input.end(),
-                           weights.begin() + o * input_size + offset,
-                           bias[o] + v[0] + v[1] + v[2] + v[3]));
-  }
-}
-#endif
+using ::rnnoise::kOutputDenseBias;
+using ::rnnoise::kOutputDenseWeights;
+using ::rnnoise::kOutputLayerOutputSize;
+static_assert(kOutputLayerOutputSize <= kFullyConnectedLayerMaxUnits, "");
 
 }  // namespace
 
-FullyConnectedLayer::FullyConnectedLayer(
-    const int input_size,
-    const int output_size,
-    const rtc::ArrayView<const int8_t> bias,
-    const rtc::ArrayView<const int8_t> weights,
-    rtc::FunctionView<float(float)> activation_function,
-    Optimization optimization)
-    : input_size_(input_size),
-      output_size_(output_size),
-      bias_(GetScaledParams(bias)),
-      weights_(GetPreprocessedFcWeights(weights, output_size)),
-      activation_function_(activation_function),
-      optimization_(optimization) {
-  RTC_DCHECK_LE(output_size_, kFullyConnectedLayersMaxUnits)
-      << "Static over-allocation of fully-connected layers output vectors is "
-         "not sufficient.";
-  RTC_DCHECK_EQ(output_size_, bias_.size())
-      << "Mismatching output size and bias terms array size.";
-  RTC_DCHECK_EQ(input_size_ * output_size_, weights_.size())
-      << "Mismatching input-output size and weight coefficients array size.";
-}
-
-FullyConnectedLayer::~FullyConnectedLayer() = default;
-
-rtc::ArrayView<const float> FullyConnectedLayer::GetOutput() const {
-  return rtc::ArrayView<const float>(output_.data(), output_size_);
-}
-
-void FullyConnectedLayer::ComputeOutput(rtc::ArrayView<const float> input) {
-  switch (optimization_) {
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-    case Optimization::kSse2:
-      ComputeFullyConnectedLayerOutputSse2(input_size_, output_size_, input,
-                                           bias_, weights_,
-                                           activation_function_, output_);
-      break;
-#endif
-#if defined(WEBRTC_HAS_NEON)
-    case Optimization::kNeon:
-      // TODO(bugs.chromium.org/10480): Handle Optimization::kNeon.
-      ComputeFullyConnectedLayerOutput(input_size_, output_size_, input, bias_,
-                                       weights_, activation_function_, output_);
-      break;
-#endif
-    default:
-      ComputeFullyConnectedLayerOutput(input_size_, output_size_, input, bias_,
-                                       weights_, activation_function_, output_);
-  }
-}
-
-GatedRecurrentLayer::GatedRecurrentLayer(
-    const int input_size,
-    const int output_size,
-    const rtc::ArrayView<const int8_t> bias,
-    const rtc::ArrayView<const int8_t> weights,
-    const rtc::ArrayView<const int8_t> recurrent_weights,
-    Optimization optimization)
-    : input_size_(input_size),
-      output_size_(output_size),
-      bias_(GetPreprocessedGruTensor(bias, output_size)),
-      weights_(GetPreprocessedGruTensor(weights, output_size)),
-      recurrent_weights_(
-          GetPreprocessedGruTensor(recurrent_weights, output_size)),
-      optimization_(optimization) {
-  RTC_DCHECK_LE(output_size_, kRecurrentLayersMaxUnits)
-      << "Static over-allocation of recurrent layers state vectors is not "
-         "sufficient.";
-  RTC_DCHECK_EQ(kNumGruGates * output_size_, bias_.size())
-      << "Mismatching output size and bias terms array size.";
-  RTC_DCHECK_EQ(kNumGruGates * input_size_ * output_size_, weights_.size())
-      << "Mismatching input-output size and weight coefficients array size.";
-  RTC_DCHECK_EQ(kNumGruGates * output_size_ * output_size_,
-                recurrent_weights_.size())
-      << "Mismatching input-output size and recurrent weight coefficients array"
-         " size.";
-  Reset();
-}
-
-GatedRecurrentLayer::~GatedRecurrentLayer() = default;
-
-rtc::ArrayView<const float> GatedRecurrentLayer::GetOutput() const {
-  return rtc::ArrayView<const float>(state_.data(), output_size_);
-}
-
-void GatedRecurrentLayer::Reset() {
-  state_.fill(0.f);
-}
-
-void GatedRecurrentLayer::ComputeOutput(rtc::ArrayView<const float> input) {
-  switch (optimization_) {
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-    case Optimization::kSse2:
-      // TODO(bugs.chromium.org/10480): Handle Optimization::kSse2.
-      ComputeGruLayerOutput(input_size_, output_size_, input, weights_,
-                            recurrent_weights_, bias_, state_);
-      break;
-#endif
-#if defined(WEBRTC_HAS_NEON)
-    case Optimization::kNeon:
-      // TODO(bugs.chromium.org/10480): Handle Optimization::kNeon.
-      ComputeGruLayerOutput(input_size_, output_size_, input, weights_,
-                            recurrent_weights_, bias_, state_);
-      break;
-#endif
-    default:
-      ComputeGruLayerOutput(input_size_, output_size_, input, weights_,
-                            recurrent_weights_, bias_, state_);
-  }
-}
-
-RnnBasedVad::RnnBasedVad()
-    : input_layer_(kInputLayerInputSize,
-                   kInputLayerOutputSize,
-                   kInputDenseBias,
-                   kInputDenseWeights,
-                   TansigApproximated,
-                   DetectOptimization()),
-      hidden_layer_(kInputLayerOutputSize,
-                    kHiddenLayerOutputSize,
-                    kHiddenGruBias,
-                    kHiddenGruWeights,
-                    kHiddenGruRecurrentWeights,
-                    DetectOptimization()),
-      output_layer_(kHiddenLayerOutputSize,
-                    kOutputLayerOutputSize,
-                    kOutputDenseBias,
-                    kOutputDenseWeights,
-                    SigmoidApproximated,
-                    DetectOptimization()) {
+RnnVad::RnnVad(const AvailableCpuFeatures& cpu_features)
+    : input_(kInputLayerInputSize,
+             kInputLayerOutputSize,
+             kInputDenseBias,
+             kInputDenseWeights,
+             ActivationFunction::kTansigApproximated,
+             cpu_features,
+             /*layer_name=*/"FC1"),
+      hidden_(kInputLayerOutputSize,
+              kHiddenLayerOutputSize,
+              kHiddenGruBias,
+              kHiddenGruWeights,
+              kHiddenGruRecurrentWeights,
+              cpu_features,
+              /*layer_name=*/"GRU1"),
+      output_(kHiddenLayerOutputSize,
+              kOutputLayerOutputSize,
+              kOutputDenseBias,
+              kOutputDenseWeights,
+              ActivationFunction::kSigmoidApproximated,
+              // The output layer is just 24x1. The unoptimized code is faster.
+              NoAvailableCpuFeatures(),
+              /*layer_name=*/"FC2") {
   // Input-output chaining size checks.
-  RTC_DCHECK_EQ(input_layer_.output_size(), hidden_layer_.input_size())
+  RTC_DCHECK_EQ(input_.size(), hidden_.input_size())
       << "The input and the hidden layers sizes do not match.";
-  RTC_DCHECK_EQ(hidden_layer_.output_size(), output_layer_.input_size())
+  RTC_DCHECK_EQ(hidden_.size(), output_.input_size())
       << "The hidden and the output layers sizes do not match.";
 }
 
-RnnBasedVad::~RnnBasedVad() = default;
+RnnVad::~RnnVad() = default;
 
-void RnnBasedVad::Reset() {
-  hidden_layer_.Reset();
+void RnnVad::Reset() {
+  hidden_.Reset();
 }
 
-float RnnBasedVad::ComputeVadProbability(
+float RnnVad::ComputeVadProbability(
     rtc::ArrayView<const float, kFeatureVectorSize> feature_vector,
     bool is_silence) {
   if (is_silence) {
     Reset();
     return 0.f;
   }
-  input_layer_.ComputeOutput(feature_vector);
-  hidden_layer_.ComputeOutput(input_layer_.GetOutput());
-  output_layer_.ComputeOutput(hidden_layer_.GetOutput());
-  const auto vad_output = output_layer_.GetOutput();
-  return vad_output[0];
+  input_.ComputeOutput(feature_vector);
+  hidden_.ComputeOutput(input_);
+  output_.ComputeOutput(hidden_);
+  RTC_DCHECK_EQ(output_.size(), 1);
+  return output_.data()[0];
 }
 
 }  // namespace rnn_vad
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn.h b/modules/audio_processing/agc2/rnn_vad/rnn.h
index 5b44f53..3148f1b 100644
--- a/modules/audio_processing/agc2/rnn_vad/rnn.h
+++ b/modules/audio_processing/agc2/rnn_vad/rnn.h
@@ -18,106 +18,33 @@
 #include <vector>
 
 #include "api/array_view.h"
-#include "api/function_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
-#include "rtc_base/system/arch.h"
+#include "modules/audio_processing/agc2/rnn_vad/rnn_fc.h"
+#include "modules/audio_processing/agc2/rnn_vad/rnn_gru.h"
 
 namespace webrtc {
 namespace rnn_vad {
 
-// Maximum number of units for a fully-connected layer. This value is used to
-// over-allocate space for fully-connected layers output vectors (implemented as
-// std::array). The value should equal the number of units of the largest
-// fully-connected layer.
-constexpr int kFullyConnectedLayersMaxUnits = 24;
-
-// Maximum number of units for a recurrent layer. This value is used to
-// over-allocate space for recurrent layers state vectors (implemented as
-// std::array). The value should equal the number of units of the largest
-// recurrent layer.
-constexpr int kRecurrentLayersMaxUnits = 24;
-
-// Fully-connected layer.
-class FullyConnectedLayer {
+// Recurrent network with hard-coded architecture and weights for voice activity
+// detection.
+class RnnVad {
  public:
-  FullyConnectedLayer(int input_size,
-                      int output_size,
-                      rtc::ArrayView<const int8_t> bias,
-                      rtc::ArrayView<const int8_t> weights,
-                      rtc::FunctionView<float(float)> activation_function,
-                      Optimization optimization);
-  FullyConnectedLayer(const FullyConnectedLayer&) = delete;
-  FullyConnectedLayer& operator=(const FullyConnectedLayer&) = delete;
-  ~FullyConnectedLayer();
-  int input_size() const { return input_size_; }
-  int output_size() const { return output_size_; }
-  Optimization optimization() const { return optimization_; }
-  rtc::ArrayView<const float> GetOutput() const;
-  // Computes the fully-connected layer output.
-  void ComputeOutput(rtc::ArrayView<const float> input);
-
- private:
-  const int input_size_;
-  const int output_size_;
-  const std::vector<float> bias_;
-  const std::vector<float> weights_;
-  rtc::FunctionView<float(float)> activation_function_;
-  // The output vector of a recurrent layer has length equal to |output_size_|.
-  // However, for efficiency, over-allocation is used.
-  std::array<float, kFullyConnectedLayersMaxUnits> output_;
-  const Optimization optimization_;
-};
-
-// Recurrent layer with gated recurrent units (GRUs) with sigmoid and ReLU as
-// activation functions for the update/reset and output gates respectively.
-class GatedRecurrentLayer {
- public:
-  GatedRecurrentLayer(int input_size,
-                      int output_size,
-                      rtc::ArrayView<const int8_t> bias,
-                      rtc::ArrayView<const int8_t> weights,
-                      rtc::ArrayView<const int8_t> recurrent_weights,
-                      Optimization optimization);
-  GatedRecurrentLayer(const GatedRecurrentLayer&) = delete;
-  GatedRecurrentLayer& operator=(const GatedRecurrentLayer&) = delete;
-  ~GatedRecurrentLayer();
-  int input_size() const { return input_size_; }
-  int output_size() const { return output_size_; }
-  Optimization optimization() const { return optimization_; }
-  rtc::ArrayView<const float> GetOutput() const;
+  explicit RnnVad(const AvailableCpuFeatures& cpu_features);
+  RnnVad(const RnnVad&) = delete;
+  RnnVad& operator=(const RnnVad&) = delete;
+  ~RnnVad();
   void Reset();
-  // Computes the recurrent layer output and updates the status.
-  void ComputeOutput(rtc::ArrayView<const float> input);
-
- private:
-  const int input_size_;
-  const int output_size_;
-  const std::vector<float> bias_;
-  const std::vector<float> weights_;
-  const std::vector<float> recurrent_weights_;
-  // The state vector of a recurrent layer has length equal to |output_size_|.
-  // However, to avoid dynamic allocation, over-allocation is used.
-  std::array<float, kRecurrentLayersMaxUnits> state_;
-  const Optimization optimization_;
-};
-
-// Recurrent network based VAD.
-class RnnBasedVad {
- public:
-  RnnBasedVad();
-  RnnBasedVad(const RnnBasedVad&) = delete;
-  RnnBasedVad& operator=(const RnnBasedVad&) = delete;
-  ~RnnBasedVad();
-  void Reset();
-  // Compute and returns the probability of voice (range: [0.0, 1.0]).
+  // Observes `feature_vector` and `is_silence`, updates the RNN and returns the
+  // current voice probability.
   float ComputeVadProbability(
       rtc::ArrayView<const float, kFeatureVectorSize> feature_vector,
       bool is_silence);
 
  private:
-  FullyConnectedLayer input_layer_;
-  GatedRecurrentLayer hidden_layer_;
-  FullyConnectedLayer output_layer_;
+  FullyConnectedLayer input_;
+  GatedRecurrentLayer hidden_;
+  FullyConnectedLayer output_;
 };
 
 }  // namespace rnn_vad
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_fc.cc b/modules/audio_processing/agc2/rnn_vad/rnn_fc.cc
new file mode 100644
index 0000000..b04807f
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_fc.cc
@@ -0,0 +1,105 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+#include <numeric>
+
+#include "modules/audio_processing/agc2/rnn_vad/rnn_fc.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "third_party/rnnoise/src/rnn_activations.h"
+#include "third_party/rnnoise/src/rnn_vad_weights.h"
+
+namespace webrtc {
+namespace rnn_vad {
+namespace {
+
+std::vector<float> GetScaledParams(rtc::ArrayView<const int8_t> params) {
+  std::vector<float> scaled_params(params.size());
+  std::transform(params.begin(), params.end(), scaled_params.begin(),
+                 [](int8_t x) -> float {
+                   return ::rnnoise::kWeightsScale * static_cast<float>(x);
+                 });
+  return scaled_params;
+}
+
+// TODO(bugs.chromium.org/10480): Hard-code optimized layout and remove this
+// function to improve setup time.
+// Casts and scales |weights| and re-arranges the layout.
+std::vector<float> PreprocessWeights(rtc::ArrayView<const int8_t> weights,
+                                     int output_size) {
+  if (output_size == 1) {
+    return GetScaledParams(weights);
+  }
+  // Transpose, scale and cast.
+  const int input_size = rtc::CheckedDivExact(
+      rtc::dchecked_cast<int>(weights.size()), output_size);
+  std::vector<float> w(weights.size());
+  for (int o = 0; o < output_size; ++o) {
+    for (int i = 0; i < input_size; ++i) {
+      w[o * input_size + i] = rnnoise::kWeightsScale *
+                              static_cast<float>(weights[i * output_size + o]);
+    }
+  }
+  return w;
+}
+
+rtc::FunctionView<float(float)> GetActivationFunction(
+    ActivationFunction activation_function) {
+  switch (activation_function) {
+    case ActivationFunction::kTansigApproximated:
+      return ::rnnoise::TansigApproximated;
+      break;
+    case ActivationFunction::kSigmoidApproximated:
+      return ::rnnoise::SigmoidApproximated;
+      break;
+  }
+}
+
+}  // namespace
+
+FullyConnectedLayer::FullyConnectedLayer(
+    const int input_size,
+    const int output_size,
+    const rtc::ArrayView<const int8_t> bias,
+    const rtc::ArrayView<const int8_t> weights,
+    ActivationFunction activation_function,
+    const AvailableCpuFeatures& cpu_features,
+    absl::string_view layer_name)
+    : input_size_(input_size),
+      output_size_(output_size),
+      bias_(GetScaledParams(bias)),
+      weights_(PreprocessWeights(weights, output_size)),
+      vector_math_(cpu_features),
+      activation_function_(GetActivationFunction(activation_function)) {
+  RTC_DCHECK_LE(output_size_, kFullyConnectedLayerMaxUnits)
+      << "Insufficient FC layer over-allocation (" << layer_name << ").";
+  RTC_DCHECK_EQ(output_size_, bias_.size())
+      << "Mismatching output size and bias terms array size (" << layer_name
+      << ").";
+  RTC_DCHECK_EQ(input_size_ * output_size_, weights_.size())
+      << "Mismatching input-output size and weight coefficients array size ("
+      << layer_name << ").";
+}
+
+FullyConnectedLayer::~FullyConnectedLayer() = default;
+
+void FullyConnectedLayer::ComputeOutput(rtc::ArrayView<const float> input) {
+  RTC_DCHECK_EQ(input.size(), input_size_);
+  rtc::ArrayView<const float> weights(weights_);
+  for (int o = 0; o < output_size_; ++o) {
+    output_[o] = activation_function_(
+        bias_[o] + vector_math_.DotProduct(
+                       input, weights.subview(o * input_size_, input_size_)));
+  }
+}
+
+}  // namespace rnn_vad
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_fc.h b/modules/audio_processing/agc2/rnn_vad/rnn_fc.h
new file mode 100644
index 0000000..d23957a
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_fc.h
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_RNN_FC_H_
+#define MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_RNN_FC_H_
+
+#include <array>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/function_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
+#include "modules/audio_processing/agc2/rnn_vad/vector_math.h"
+
+namespace webrtc {
+namespace rnn_vad {
+
+// Activation function for a neural network cell.
+enum class ActivationFunction { kTansigApproximated, kSigmoidApproximated };
+
+// Maximum number of units for an FC layer.
+constexpr int kFullyConnectedLayerMaxUnits = 24;
+
+// Fully-connected layer with a custom activation function which owns the output
+// buffer.
+class FullyConnectedLayer {
+ public:
+  // Ctor. `output_size` cannot be greater than `kFullyConnectedLayerMaxUnits`.
+  FullyConnectedLayer(int input_size,
+                      int output_size,
+                      rtc::ArrayView<const int8_t> bias,
+                      rtc::ArrayView<const int8_t> weights,
+                      ActivationFunction activation_function,
+                      const AvailableCpuFeatures& cpu_features,
+                      absl::string_view layer_name);
+  FullyConnectedLayer(const FullyConnectedLayer&) = delete;
+  FullyConnectedLayer& operator=(const FullyConnectedLayer&) = delete;
+  ~FullyConnectedLayer();
+
+  // Returns the size of the input vector.
+  int input_size() const { return input_size_; }
+  // Returns the pointer to the first element of the output buffer.
+  const float* data() const { return output_.data(); }
+  // Returns the size of the output buffer.
+  int size() const { return output_size_; }
+
+  // Computes the fully-connected layer output.
+  void ComputeOutput(rtc::ArrayView<const float> input);
+
+ private:
+  const int input_size_;
+  const int output_size_;
+  const std::vector<float> bias_;
+  const std::vector<float> weights_;
+  const VectorMath vector_math_;
+  rtc::FunctionView<float(float)> activation_function_;
+  // Over-allocated array with size equal to `output_size_`.
+  std::array<float, kFullyConnectedLayerMaxUnits> output_;
+};
+
+}  // namespace rnn_vad
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_RNN_FC_H_
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_fc_unittest.cc b/modules/audio_processing/agc2/rnn_vad/rnn_fc_unittest.cc
new file mode 100644
index 0000000..ff9bb18
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_fc_unittest.cc
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/agc2/rnn_vad/rnn_fc.h"
+
+#include <array>
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
+#include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
+#include "modules/audio_processing/test/performance_timer.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/system/arch.h"
+#include "test/gtest.h"
+#include "third_party/rnnoise/src/rnn_vad_weights.h"
+
+namespace webrtc {
+namespace rnn_vad {
+namespace {
+
+using ::rnnoise::kInputDenseBias;
+using ::rnnoise::kInputDenseWeights;
+using ::rnnoise::kInputLayerInputSize;
+using ::rnnoise::kInputLayerOutputSize;
+
+// Fully connected layer test data.
+constexpr std::array<float, 42> kFullyConnectedInputVector = {
+    -1.00131f,   -0.627069f, -7.81097f,  7.86285f,    -2.87145f,  3.32365f,
+    -0.653161f,  0.529839f,  -0.425307f, 0.25583f,    0.235094f,  0.230527f,
+    -0.144687f,  0.182785f,  0.57102f,   0.125039f,   0.479482f,  -0.0255439f,
+    -0.0073141f, -0.147346f, -0.217106f, -0.0846906f, -8.34943f,  3.09065f,
+    1.42628f,    -0.85235f,  -0.220207f, -0.811163f,  2.09032f,   -2.01425f,
+    -0.690268f,  -0.925327f, -0.541354f, 0.58455f,    -0.606726f, -0.0372358f,
+    0.565991f,   0.435854f,  0.420812f,  0.162198f,   -2.13f,     10.0089f};
+constexpr std::array<float, 24> kFullyConnectedExpectedOutput = {
+    -0.623293f, -0.988299f, 0.999378f,  0.967168f,  0.103087f,  -0.978545f,
+    -0.856347f, 0.346675f,  1.f,        -0.717442f, -0.544176f, 0.960363f,
+    0.983443f,  0.999991f,  -0.824335f, 0.984742f,  0.990208f,  0.938179f,
+    0.875092f,  0.999846f,  0.997707f,  -0.999382f, 0.973153f,  -0.966605f};
+
+class RnnFcParametrization
+    : public ::testing::TestWithParam<AvailableCpuFeatures> {};
+
+// Checks that the output of a fully connected layer is within tolerance given
+// test input data.
+TEST_P(RnnFcParametrization, CheckFullyConnectedLayerOutput) {
+  FullyConnectedLayer fc(kInputLayerInputSize, kInputLayerOutputSize,
+                         kInputDenseBias, kInputDenseWeights,
+                         ActivationFunction::kTansigApproximated,
+                         /*cpu_features=*/GetParam(),
+                         /*layer_name=*/"FC");
+  fc.ComputeOutput(kFullyConnectedInputVector);
+  ExpectNearAbsolute(kFullyConnectedExpectedOutput, fc, 1e-5f);
+}
+
+TEST_P(RnnFcParametrization, DISABLED_BenchmarkFullyConnectedLayer) {
+  const AvailableCpuFeatures cpu_features = GetParam();
+  FullyConnectedLayer fc(kInputLayerInputSize, kInputLayerOutputSize,
+                         kInputDenseBias, kInputDenseWeights,
+                         ActivationFunction::kTansigApproximated, cpu_features,
+                         /*layer_name=*/"FC");
+
+  constexpr int kNumTests = 10000;
+  ::webrtc::test::PerformanceTimer perf_timer(kNumTests);
+  for (int k = 0; k < kNumTests; ++k) {
+    perf_timer.StartTimer();
+    fc.ComputeOutput(kFullyConnectedInputVector);
+    perf_timer.StopTimer();
+  }
+  RTC_LOG(LS_INFO) << "CPU features: " << cpu_features.ToString() << " | "
+                   << (perf_timer.GetDurationAverage() / 1000) << " +/- "
+                   << (perf_timer.GetDurationStandardDeviation() / 1000)
+                   << " ms";
+}
+
+// Finds the relevant CPU features combinations to test.
+std::vector<AvailableCpuFeatures> GetCpuFeaturesToTest() {
+  std::vector<AvailableCpuFeatures> v;
+  v.push_back(NoAvailableCpuFeatures());
+  AvailableCpuFeatures available = GetAvailableCpuFeatures();
+  if (available.sse2) {
+    v.push_back({/*sse2=*/true, /*avx2=*/false, /*neon=*/false});
+  }
+  if (available.avx2) {
+    v.push_back({/*sse2=*/false, /*avx2=*/true, /*neon=*/false});
+  }
+  if (available.neon) {
+    v.push_back({/*sse2=*/false, /*avx2=*/false, /*neon=*/true});
+  }
+  return v;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    RnnVadTest,
+    RnnFcParametrization,
+    ::testing::ValuesIn(GetCpuFeaturesToTest()),
+    [](const ::testing::TestParamInfo<AvailableCpuFeatures>& info) {
+      return info.param.ToString();
+    });
+
+}  // namespace
+}  // namespace rnn_vad
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_gru.cc b/modules/audio_processing/agc2/rnn_vad/rnn_gru.cc
new file mode 100644
index 0000000..482016e
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_gru.cc
@@ -0,0 +1,198 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/agc2/rnn_vad/rnn_gru.h"
+
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "third_party/rnnoise/src/rnn_activations.h"
+#include "third_party/rnnoise/src/rnn_vad_weights.h"
+
+namespace webrtc {
+namespace rnn_vad {
+namespace {
+
+constexpr int kNumGruGates = 3;  // Update, reset, output.
+
+std::vector<float> PreprocessGruTensor(rtc::ArrayView<const int8_t> tensor_src,
+                                       int output_size) {
+  // Transpose, cast and scale.
+  // |n| is the size of the first dimension of the 3-dim tensor |weights|.
+  const int n = rtc::CheckedDivExact(rtc::dchecked_cast<int>(tensor_src.size()),
+                                     output_size * kNumGruGates);
+  const int stride_src = kNumGruGates * output_size;
+  const int stride_dst = n * output_size;
+  std::vector<float> tensor_dst(tensor_src.size());
+  for (int g = 0; g < kNumGruGates; ++g) {
+    for (int o = 0; o < output_size; ++o) {
+      for (int i = 0; i < n; ++i) {
+        tensor_dst[g * stride_dst + o * n + i] =
+            ::rnnoise::kWeightsScale *
+            static_cast<float>(
+                tensor_src[i * stride_src + g * output_size + o]);
+      }
+    }
+  }
+  return tensor_dst;
+}
+
+// Computes the output for the update or the reset gate.
+// Operation: `g = sigmoid(W^T∙i + R^T∙s + b)` where
+// - `g`: output gate vector
+// - `W`: weights matrix
+// - `i`: input vector
+// - `R`: recurrent weights matrix
+// - `s`: state gate vector
+// - `b`: bias vector
+void ComputeUpdateResetGate(int input_size,
+                            int output_size,
+                            const VectorMath& vector_math,
+                            rtc::ArrayView<const float> input,
+                            rtc::ArrayView<const float> state,
+                            rtc::ArrayView<const float> bias,
+                            rtc::ArrayView<const float> weights,
+                            rtc::ArrayView<const float> recurrent_weights,
+                            rtc::ArrayView<float> gate) {
+  RTC_DCHECK_EQ(input.size(), input_size);
+  RTC_DCHECK_EQ(state.size(), output_size);
+  RTC_DCHECK_EQ(bias.size(), output_size);
+  RTC_DCHECK_EQ(weights.size(), input_size * output_size);
+  RTC_DCHECK_EQ(recurrent_weights.size(), output_size * output_size);
+  RTC_DCHECK_GE(gate.size(), output_size);  // `gate` is over-allocated.
+  for (int o = 0; o < output_size; ++o) {
+    float x = bias[o];
+    x += vector_math.DotProduct(input,
+                                weights.subview(o * input_size, input_size));
+    x += vector_math.DotProduct(
+        state, recurrent_weights.subview(o * output_size, output_size));
+    gate[o] = ::rnnoise::SigmoidApproximated(x);
+  }
+}
+
+// Computes the output for the state gate.
+// Operation: `s' = u .* s + (1 - u) .* ReLU(W^T∙i + R^T∙(s .* r) + b)` where
+// - `s'`: output state gate vector
+// - `s`: previous state gate vector
+// - `u`: update gate vector
+// - `W`: weights matrix
+// - `i`: input vector
+// - `R`: recurrent weights matrix
+// - `r`: reset gate vector
+// - `b`: bias vector
+// - `.*` element-wise product
+void ComputeStateGate(int input_size,
+                      int output_size,
+                      const VectorMath& vector_math,
+                      rtc::ArrayView<const float> input,
+                      rtc::ArrayView<const float> update,
+                      rtc::ArrayView<const float> reset,
+                      rtc::ArrayView<const float> bias,
+                      rtc::ArrayView<const float> weights,
+                      rtc::ArrayView<const float> recurrent_weights,
+                      rtc::ArrayView<float> state) {
+  RTC_DCHECK_EQ(input.size(), input_size);
+  RTC_DCHECK_GE(update.size(), output_size);  // `update` is over-allocated.
+  RTC_DCHECK_GE(reset.size(), output_size);   // `reset` is over-allocated.
+  RTC_DCHECK_EQ(bias.size(), output_size);
+  RTC_DCHECK_EQ(weights.size(), input_size * output_size);
+  RTC_DCHECK_EQ(recurrent_weights.size(), output_size * output_size);
+  RTC_DCHECK_EQ(state.size(), output_size);
+  std::array<float, kGruLayerMaxUnits> reset_x_state;
+  for (int o = 0; o < output_size; ++o) {
+    reset_x_state[o] = state[o] * reset[o];
+  }
+  for (int o = 0; o < output_size; ++o) {
+    float x = bias[o];
+    x += vector_math.DotProduct(input,
+                                weights.subview(o * input_size, input_size));
+    x += vector_math.DotProduct(
+        {reset_x_state.data(), static_cast<size_t>(output_size)},
+        recurrent_weights.subview(o * output_size, output_size));
+    state[o] = update[o] * state[o] + (1.f - update[o]) * std::max(0.f, x);
+  }
+}
+
+}  // namespace
+
+GatedRecurrentLayer::GatedRecurrentLayer(
+    const int input_size,
+    const int output_size,
+    const rtc::ArrayView<const int8_t> bias,
+    const rtc::ArrayView<const int8_t> weights,
+    const rtc::ArrayView<const int8_t> recurrent_weights,
+    const AvailableCpuFeatures& cpu_features,
+    absl::string_view layer_name)
+    : input_size_(input_size),
+      output_size_(output_size),
+      bias_(PreprocessGruTensor(bias, output_size)),
+      weights_(PreprocessGruTensor(weights, output_size)),
+      recurrent_weights_(PreprocessGruTensor(recurrent_weights, output_size)),
+      vector_math_(cpu_features) {
+  RTC_DCHECK_LE(output_size_, kGruLayerMaxUnits)
+      << "Insufficient GRU layer over-allocation (" << layer_name << ").";
+  RTC_DCHECK_EQ(kNumGruGates * output_size_, bias_.size())
+      << "Mismatching output size and bias terms array size (" << layer_name
+      << ").";
+  RTC_DCHECK_EQ(kNumGruGates * input_size_ * output_size_, weights_.size())
+      << "Mismatching input-output size and weight coefficients array size ("
+      << layer_name << ").";
+  RTC_DCHECK_EQ(kNumGruGates * output_size_ * output_size_,
+                recurrent_weights_.size())
+      << "Mismatching input-output size and recurrent weight coefficients array"
+         " size ("
+      << layer_name << ").";
+  Reset();
+}
+
+GatedRecurrentLayer::~GatedRecurrentLayer() = default;
+
+void GatedRecurrentLayer::Reset() {
+  state_.fill(0.f);
+}
+
+void GatedRecurrentLayer::ComputeOutput(rtc::ArrayView<const float> input) {
+  RTC_DCHECK_EQ(input.size(), input_size_);
+
+  // The tensors below are organized as a sequence of flattened tensors for the
+  // `update`, `reset` and `state` gates.
+  rtc::ArrayView<const float> bias(bias_);
+  rtc::ArrayView<const float> weights(weights_);
+  rtc::ArrayView<const float> recurrent_weights(recurrent_weights_);
+  // Strides to access to the flattened tensors for a specific gate.
+  const int stride_weights = input_size_ * output_size_;
+  const int stride_recurrent_weights = output_size_ * output_size_;
+
+  rtc::ArrayView<float> state(state_.data(), output_size_);
+
+  // Update gate.
+  std::array<float, kGruLayerMaxUnits> update;
+  ComputeUpdateResetGate(
+      input_size_, output_size_, vector_math_, input, state,
+      bias.subview(0, output_size_), weights.subview(0, stride_weights),
+      recurrent_weights.subview(0, stride_recurrent_weights), update);
+  // Reset gate.
+  std::array<float, kGruLayerMaxUnits> reset;
+  ComputeUpdateResetGate(input_size_, output_size_, vector_math_, input, state,
+                         bias.subview(output_size_, output_size_),
+                         weights.subview(stride_weights, stride_weights),
+                         recurrent_weights.subview(stride_recurrent_weights,
+                                                   stride_recurrent_weights),
+                         reset);
+  // State gate.
+  ComputeStateGate(input_size_, output_size_, vector_math_, input, update,
+                   reset, bias.subview(2 * output_size_, output_size_),
+                   weights.subview(2 * stride_weights, stride_weights),
+                   recurrent_weights.subview(2 * stride_recurrent_weights,
+                                             stride_recurrent_weights),
+                   state);
+}
+
+}  // namespace rnn_vad
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_gru.h b/modules/audio_processing/agc2/rnn_vad/rnn_gru.h
new file mode 100644
index 0000000..3407dfc
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_gru.h
@@ -0,0 +1,70 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_RNN_GRU_H_
+#define MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_RNN_GRU_H_
+
+#include <array>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
+#include "modules/audio_processing/agc2/rnn_vad/vector_math.h"
+
+namespace webrtc {
+namespace rnn_vad {
+
+// Maximum number of units for a GRU layer.
+constexpr int kGruLayerMaxUnits = 24;
+
+// Recurrent layer with gated recurrent units (GRUs) with sigmoid and ReLU as
+// activation functions for the update/reset and output gates respectively.
+class GatedRecurrentLayer {
+ public:
+  // Ctor. `output_size` cannot be greater than `kGruLayerMaxUnits`.
+  GatedRecurrentLayer(int input_size,
+                      int output_size,
+                      rtc::ArrayView<const int8_t> bias,
+                      rtc::ArrayView<const int8_t> weights,
+                      rtc::ArrayView<const int8_t> recurrent_weights,
+                      const AvailableCpuFeatures& cpu_features,
+                      absl::string_view layer_name);
+  GatedRecurrentLayer(const GatedRecurrentLayer&) = delete;
+  GatedRecurrentLayer& operator=(const GatedRecurrentLayer&) = delete;
+  ~GatedRecurrentLayer();
+
+  // Returns the size of the input vector.
+  int input_size() const { return input_size_; }
+  // Returns the pointer to the first element of the output buffer.
+  const float* data() const { return state_.data(); }
+  // Returns the size of the output buffer.
+  int size() const { return output_size_; }
+
+  // Resets the GRU state.
+  void Reset();
+  // Computes the recurrent layer output and updates the status.
+  void ComputeOutput(rtc::ArrayView<const float> input);
+
+ private:
+  const int input_size_;
+  const int output_size_;
+  const std::vector<float> bias_;
+  const std::vector<float> weights_;
+  const std::vector<float> recurrent_weights_;
+  const VectorMath vector_math_;
+  // Over-allocated array with size equal to `output_size_`.
+  std::array<float, kGruLayerMaxUnits> state_;
+};
+
+}  // namespace rnn_vad
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_RNN_GRU_H_
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_gru_unittest.cc b/modules/audio_processing/agc2/rnn_vad/rnn_gru_unittest.cc
new file mode 100644
index 0000000..88ae728
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_gru_unittest.cc
@@ -0,0 +1,186 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/agc2/rnn_vad/rnn_gru.h"
+
+#include <array>
+#include <memory>
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
+#include "modules/audio_processing/test/performance_timer.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "test/gtest.h"
+#include "third_party/rnnoise/src/rnn_vad_weights.h"
+
+namespace webrtc {
+namespace rnn_vad {
+namespace {
+
+void TestGatedRecurrentLayer(
+    GatedRecurrentLayer& gru,
+    rtc::ArrayView<const float> input_sequence,
+    rtc::ArrayView<const float> expected_output_sequence) {
+  const int input_sequence_length = rtc::CheckedDivExact(
+      rtc::dchecked_cast<int>(input_sequence.size()), gru.input_size());
+  const int output_sequence_length = rtc::CheckedDivExact(
+      rtc::dchecked_cast<int>(expected_output_sequence.size()), gru.size());
+  ASSERT_EQ(input_sequence_length, output_sequence_length)
+      << "The test data length is invalid.";
+  // Feed the GRU layer and check the output at every step.
+  gru.Reset();
+  for (int i = 0; i < input_sequence_length; ++i) {
+    SCOPED_TRACE(i);
+    gru.ComputeOutput(
+        input_sequence.subview(i * gru.input_size(), gru.input_size()));
+    const auto expected_output =
+        expected_output_sequence.subview(i * gru.size(), gru.size());
+    ExpectNearAbsolute(expected_output, gru, 3e-6f);
+  }
+}
+
+// Gated recurrent units layer test data.
+constexpr int kGruInputSize = 5;
+constexpr int kGruOutputSize = 4;
+constexpr std::array<int8_t, 12> kGruBias = {96,   -99, -81, -114, 49,  119,
+                                             -118, 68,  -76, 91,   121, 125};
+constexpr std::array<int8_t, 60> kGruWeights = {
+    // Input 0.
+    124, 9, 1, 116,        // Update.
+    -66, -21, -118, -110,  // Reset.
+    104, 75, -23, -51,     // Output.
+    // Input 1.
+    -72, -111, 47, 93,   // Update.
+    77, -98, 41, -8,     // Reset.
+    40, -23, -43, -107,  // Output.
+    // Input 2.
+    9, -73, 30, -32,      // Update.
+    -2, 64, -26, 91,      // Reset.
+    -48, -24, -28, -104,  // Output.
+    // Input 3.
+    74, -46, 116, 15,    // Update.
+    32, 52, -126, -38,   // Reset.
+    -121, 12, -16, 110,  // Output.
+    // Input 4.
+    -95, 66, -103, -35,  // Update.
+    -38, 3, -126, -61,   // Reset.
+    28, 98, -117, -43    // Output.
+};
+constexpr std::array<int8_t, 48> kGruRecurrentWeights = {
+    // Output 0.
+    -3, 87, 50, 51,     // Update.
+    -22, 27, -39, 62,   // Reset.
+    31, -83, -52, -48,  // Output.
+    // Output 1.
+    -6, 83, -19, 104,  // Update.
+    105, 48, 23, 68,   // Reset.
+    23, 40, 7, -120,   // Output.
+    // Output 2.
+    64, -62, 117, 85,     // Update.
+    51, -43, 54, -105,    // Reset.
+    120, 56, -128, -107,  // Output.
+    // Output 3.
+    39, 50, -17, -47,   // Update.
+    -117, 14, 108, 12,  // Reset.
+    -7, -72, 103, -87,  // Output.
+};
+constexpr std::array<float, 20> kGruInputSequence = {
+    0.89395463f, 0.93224651f, 0.55788344f, 0.32341808f, 0.93355054f,
+    0.13475326f, 0.97370994f, 0.14253306f, 0.93710381f, 0.76093364f,
+    0.65780413f, 0.41657975f, 0.49403164f, 0.46843281f, 0.75138855f,
+    0.24517593f, 0.47657707f, 0.57064998f, 0.435184f,   0.19319285f};
+constexpr std::array<float, 16> kGruExpectedOutputSequence = {
+    0.0239123f,  0.5773077f,  0.f,         0.f,
+    0.01282811f, 0.64330572f, 0.f,         0.04863098f,
+    0.00781069f, 0.75267816f, 0.f,         0.02579715f,
+    0.00471378f, 0.59162533f, 0.11087593f, 0.01334511f};
+
+class RnnGruParametrization
+    : public ::testing::TestWithParam<AvailableCpuFeatures> {};
+
+// Checks that the output of a GRU layer is within tolerance given test input
+// data.
+TEST_P(RnnGruParametrization, CheckGatedRecurrentLayer) {
+  GatedRecurrentLayer gru(kGruInputSize, kGruOutputSize, kGruBias, kGruWeights,
+                          kGruRecurrentWeights,
+                          /*cpu_features=*/GetParam(),
+                          /*layer_name=*/"GRU");
+  TestGatedRecurrentLayer(gru, kGruInputSequence, kGruExpectedOutputSequence);
+}
+
+TEST_P(RnnGruParametrization, DISABLED_BenchmarkGatedRecurrentLayer) {
+  // Prefetch test data.
+  std::unique_ptr<FileReader> reader = CreateGruInputReader();
+  std::vector<float> gru_input_sequence(reader->size());
+  reader->ReadChunk(gru_input_sequence);
+
+  using ::rnnoise::kHiddenGruBias;
+  using ::rnnoise::kHiddenGruRecurrentWeights;
+  using ::rnnoise::kHiddenGruWeights;
+  using ::rnnoise::kHiddenLayerOutputSize;
+  using ::rnnoise::kInputLayerOutputSize;
+
+  GatedRecurrentLayer gru(kInputLayerOutputSize, kHiddenLayerOutputSize,
+                          kHiddenGruBias, kHiddenGruWeights,
+                          kHiddenGruRecurrentWeights,
+                          /*cpu_features=*/GetParam(),
+                          /*layer_name=*/"GRU");
+
+  rtc::ArrayView<const float> input_sequence(gru_input_sequence);
+  ASSERT_EQ(input_sequence.size() % kInputLayerOutputSize,
+            static_cast<size_t>(0));
+  const int input_sequence_length =
+      input_sequence.size() / kInputLayerOutputSize;
+
+  constexpr int kNumTests = 100;
+  ::webrtc::test::PerformanceTimer perf_timer(kNumTests);
+  for (int k = 0; k < kNumTests; ++k) {
+    perf_timer.StartTimer();
+    for (int i = 0; i < input_sequence_length; ++i) {
+      gru.ComputeOutput(
+          input_sequence.subview(i * gru.input_size(), gru.input_size()));
+    }
+    perf_timer.StopTimer();
+  }
+  RTC_LOG(LS_INFO) << (perf_timer.GetDurationAverage() / 1000) << " +/- "
+                   << (perf_timer.GetDurationStandardDeviation() / 1000)
+                   << " ms";
+}
+
+// Finds the relevant CPU features combinations to test.
+std::vector<AvailableCpuFeatures> GetCpuFeaturesToTest() {
+  std::vector<AvailableCpuFeatures> v;
+  v.push_back(NoAvailableCpuFeatures());
+  AvailableCpuFeatures available = GetAvailableCpuFeatures();
+  if (available.sse2) {
+    v.push_back({/*sse2=*/true, /*avx2=*/false, /*neon=*/false});
+  }
+  if (available.avx2) {
+    v.push_back({/*sse2=*/false, /*avx2=*/true, /*neon=*/false});
+  }
+  if (available.neon) {
+    v.push_back({/*sse2=*/false, /*avx2=*/false, /*neon=*/true});
+  }
+  return v;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    RnnVadTest,
+    RnnGruParametrization,
+    ::testing::ValuesIn(GetCpuFeaturesToTest()),
+    [](const ::testing::TestParamInfo<AvailableCpuFeatures>& info) {
+      return info.param.ToString();
+    });
+
+}  // namespace
+}  // namespace rnn_vad
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_unittest.cc b/modules/audio_processing/agc2/rnn_vad/rnn_unittest.cc
index a57a899..4c5409a 100644
--- a/modules/audio_processing/agc2/rnn_vad/rnn_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_unittest.cc
@@ -10,61 +10,16 @@
 
 #include "modules/audio_processing/agc2/rnn_vad/rnn.h"
 
-#include <array>
-#include <memory>
-#include <vector>
-
-#include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
-#include "modules/audio_processing/test/performance_timer.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/system/arch.h"
+#include "api/array_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
+#include "modules/audio_processing/agc2/rnn_vad/common.h"
 #include "test/gtest.h"
-#include "third_party/rnnoise/src/rnn_activations.h"
-#include "third_party/rnnoise/src/rnn_vad_weights.h"
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
-
 namespace {
 
-void TestFullyConnectedLayer(FullyConnectedLayer* fc,
-                             rtc::ArrayView<const float> input_vector,
-                             rtc::ArrayView<const float> expected_output) {
-  RTC_CHECK(fc);
-  fc->ComputeOutput(input_vector);
-  ExpectNearAbsolute(expected_output, fc->GetOutput(), 1e-5f);
-}
-
-void TestGatedRecurrentLayer(
-    GatedRecurrentLayer* gru,
-    rtc::ArrayView<const float> input_sequence,
-    rtc::ArrayView<const float> expected_output_sequence) {
-  RTC_CHECK(gru);
-  auto gru_output_view = gru->GetOutput();
-  const int input_sequence_length = rtc::CheckedDivExact(
-      rtc::dchecked_cast<int>(input_sequence.size()), gru->input_size());
-  const int output_sequence_length = rtc::CheckedDivExact(
-      rtc::dchecked_cast<int>(expected_output_sequence.size()),
-      gru->output_size());
-  ASSERT_EQ(input_sequence_length, output_sequence_length)
-      << "The test data length is invalid.";
-  // Feed the GRU layer and check the output at every step.
-  gru->Reset();
-  for (int i = 0; i < input_sequence_length; ++i) {
-    SCOPED_TRACE(i);
-    gru->ComputeOutput(
-        input_sequence.subview(i * gru->input_size(), gru->input_size()));
-    const auto expected_output = expected_output_sequence.subview(
-        i * gru->output_size(), gru->output_size());
-    ExpectNearAbsolute(expected_output, gru_output_view, 3e-6f);
-  }
-}
-
-// Fully connected layer test data.
-constexpr std::array<float, 42> kFullyConnectedInputVector = {
+constexpr std::array<float, kFeatureVectorSize> kFeatures = {
     -1.00131f,   -0.627069f, -7.81097f,  7.86285f,    -2.87145f,  3.32365f,
     -0.653161f,  0.529839f,  -0.425307f, 0.25583f,    0.235094f,  0.230527f,
     -0.144687f,  0.182785f,  0.57102f,   0.125039f,   0.479482f,  -0.0255439f,
@@ -72,203 +27,44 @@
     1.42628f,    -0.85235f,  -0.220207f, -0.811163f,  2.09032f,   -2.01425f,
     -0.690268f,  -0.925327f, -0.541354f, 0.58455f,    -0.606726f, -0.0372358f,
     0.565991f,   0.435854f,  0.420812f,  0.162198f,   -2.13f,     10.0089f};
-constexpr std::array<float, 24> kFullyConnectedExpectedOutput = {
-    -0.623293f, -0.988299f, 0.999378f,  0.967168f,  0.103087f,  -0.978545f,
-    -0.856347f, 0.346675f,  1.f,        -0.717442f, -0.544176f, 0.960363f,
-    0.983443f,  0.999991f,  -0.824335f, 0.984742f,  0.990208f,  0.938179f,
-    0.875092f,  0.999846f,  0.997707f,  -0.999382f, 0.973153f,  -0.966605f};
 
-// Gated recurrent units layer test data.
-constexpr int kGruInputSize = 5;
-constexpr int kGruOutputSize = 4;
-constexpr std::array<int8_t, 12> kGruBias = {96,   -99, -81, -114, 49,  119,
-                                             -118, 68,  -76, 91,   121, 125};
-constexpr std::array<int8_t, 60> kGruWeights = {
-    // Input 0.
-    124, 9, 1, 116,        // Update.
-    -66, -21, -118, -110,  // Reset.
-    104, 75, -23, -51,     // Output.
-    // Input 1.
-    -72, -111, 47, 93,   // Update.
-    77, -98, 41, -8,     // Reset.
-    40, -23, -43, -107,  // Output.
-    // Input 2.
-    9, -73, 30, -32,      // Update.
-    -2, 64, -26, 91,      // Reset.
-    -48, -24, -28, -104,  // Output.
-    // Input 3.
-    74, -46, 116, 15,    // Update.
-    32, 52, -126, -38,   // Reset.
-    -121, 12, -16, 110,  // Output.
-    // Input 4.
-    -95, 66, -103, -35,  // Update.
-    -38, 3, -126, -61,   // Reset.
-    28, 98, -117, -43    // Output.
-};
-constexpr std::array<int8_t, 48> kGruRecurrentWeights = {
-    // Output 0.
-    -3, 87, 50, 51,     // Update.
-    -22, 27, -39, 62,   // Reset.
-    31, -83, -52, -48,  // Output.
-    // Output 1.
-    -6, 83, -19, 104,  // Update.
-    105, 48, 23, 68,   // Reset.
-    23, 40, 7, -120,   // Output.
-    // Output 2.
-    64, -62, 117, 85,     // Update.
-    51, -43, 54, -105,    // Reset.
-    120, 56, -128, -107,  // Output.
-    // Output 3.
-    39, 50, -17, -47,   // Update.
-    -117, 14, 108, 12,  // Reset.
-    -7, -72, 103, -87,  // Output.
-};
-constexpr std::array<float, 20> kGruInputSequence = {
-    0.89395463f, 0.93224651f, 0.55788344f, 0.32341808f, 0.93355054f,
-    0.13475326f, 0.97370994f, 0.14253306f, 0.93710381f, 0.76093364f,
-    0.65780413f, 0.41657975f, 0.49403164f, 0.46843281f, 0.75138855f,
-    0.24517593f, 0.47657707f, 0.57064998f, 0.435184f,   0.19319285f};
-constexpr std::array<float, 16> kGruExpectedOutputSequence = {
-    0.0239123f,  0.5773077f,  0.f,         0.f,
-    0.01282811f, 0.64330572f, 0.f,         0.04863098f,
-    0.00781069f, 0.75267816f, 0.f,         0.02579715f,
-    0.00471378f, 0.59162533f, 0.11087593f, 0.01334511f};
-
-std::string GetOptimizationName(Optimization optimization) {
-  switch (optimization) {
-    case Optimization::kSse2:
-      return "SSE2";
-    case Optimization::kNeon:
-      return "NEON";
-    case Optimization::kNone:
-      return "none";
+void WarmUpRnnVad(RnnVad& rnn_vad) {
+  for (int i = 0; i < 10; ++i) {
+    rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/false);
   }
 }
 
-struct Result {
-  Optimization optimization;
-  double average_us;
-  double std_dev_us;
-};
+// Checks that the speech probability is zero with silence.
+TEST(RnnVadTest, CheckZeroProbabilityWithSilence) {
+  RnnVad rnn_vad(GetAvailableCpuFeatures());
+  WarmUpRnnVad(rnn_vad);
+  EXPECT_EQ(rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/true), 0.f);
+}
+
+// Checks that the same output is produced after reset given the same input
+// sequence.
+TEST(RnnVadTest, CheckRnnVadReset) {
+  RnnVad rnn_vad(GetAvailableCpuFeatures());
+  WarmUpRnnVad(rnn_vad);
+  float pre = rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/false);
+  rnn_vad.Reset();
+  WarmUpRnnVad(rnn_vad);
+  float post = rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/false);
+  EXPECT_EQ(pre, post);
+}
+
+// Checks that the same output is produced after silence is observed given the
+// same input sequence.
+TEST(RnnVadTest, CheckRnnVadSilence) {
+  RnnVad rnn_vad(GetAvailableCpuFeatures());
+  WarmUpRnnVad(rnn_vad);
+  float pre = rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/false);
+  rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/true);
+  WarmUpRnnVad(rnn_vad);
+  float post = rnn_vad.ComputeVadProbability(kFeatures, /*is_silence=*/false);
+  EXPECT_EQ(pre, post);
+}
 
 }  // namespace
-
-// Checks that the output of a fully connected layer is within tolerance given
-// test input data.
-TEST(RnnVadTest, CheckFullyConnectedLayerOutput) {
-  FullyConnectedLayer fc(rnnoise::kInputLayerInputSize,
-                         rnnoise::kInputLayerOutputSize,
-                         rnnoise::kInputDenseBias, rnnoise::kInputDenseWeights,
-                         rnnoise::TansigApproximated, Optimization::kNone);
-  TestFullyConnectedLayer(&fc, kFullyConnectedInputVector,
-                          kFullyConnectedExpectedOutput);
-}
-
-// Checks that the output of a GRU layer is within tolerance given test input
-// data.
-TEST(RnnVadTest, CheckGatedRecurrentLayer) {
-  GatedRecurrentLayer gru(kGruInputSize, kGruOutputSize, kGruBias, kGruWeights,
-                          kGruRecurrentWeights, Optimization::kNone);
-  TestGatedRecurrentLayer(&gru, kGruInputSequence, kGruExpectedOutputSequence);
-}
-
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-
-// Like CheckFullyConnectedLayerOutput, but testing the SSE2 implementation.
-TEST(RnnVadTest, CheckFullyConnectedLayerOutputSse2) {
-  if (!IsOptimizationAvailable(Optimization::kSse2)) {
-    return;
-  }
-
-  FullyConnectedLayer fc(rnnoise::kInputLayerInputSize,
-                         rnnoise::kInputLayerOutputSize,
-                         rnnoise::kInputDenseBias, rnnoise::kInputDenseWeights,
-                         rnnoise::TansigApproximated, Optimization::kSse2);
-  TestFullyConnectedLayer(&fc, kFullyConnectedInputVector,
-                          kFullyConnectedExpectedOutput);
-}
-
-// Like CheckGatedRecurrentLayer, but testing the SSE2 implementation.
-TEST(RnnVadTest, CheckGatedRecurrentLayerSse2) {
-  if (!IsOptimizationAvailable(Optimization::kSse2)) {
-    return;
-  }
-
-  GatedRecurrentLayer gru(kGruInputSize, kGruOutputSize, kGruBias, kGruWeights,
-                          kGruRecurrentWeights, Optimization::kSse2);
-  TestGatedRecurrentLayer(&gru, kGruInputSequence, kGruExpectedOutputSequence);
-}
-
-#endif  // WEBRTC_ARCH_X86_FAMILY
-
-TEST(RnnVadTest, DISABLED_BenchmarkFullyConnectedLayer) {
-  std::vector<std::unique_ptr<FullyConnectedLayer>> implementations;
-  implementations.emplace_back(std::make_unique<FullyConnectedLayer>(
-      rnnoise::kInputLayerInputSize, rnnoise::kInputLayerOutputSize,
-      rnnoise::kInputDenseBias, rnnoise::kInputDenseWeights,
-      rnnoise::TansigApproximated, Optimization::kNone));
-  if (IsOptimizationAvailable(Optimization::kSse2)) {
-    implementations.emplace_back(std::make_unique<FullyConnectedLayer>(
-        rnnoise::kInputLayerInputSize, rnnoise::kInputLayerOutputSize,
-        rnnoise::kInputDenseBias, rnnoise::kInputDenseWeights,
-        rnnoise::TansigApproximated, Optimization::kSse2));
-  }
-
-  std::vector<Result> results;
-  constexpr int number_of_tests = 10000;
-  for (auto& fc : implementations) {
-    ::webrtc::test::PerformanceTimer perf_timer(number_of_tests);
-    for (int k = 0; k < number_of_tests; ++k) {
-      perf_timer.StartTimer();
-      fc->ComputeOutput(kFullyConnectedInputVector);
-      perf_timer.StopTimer();
-    }
-    results.push_back({fc->optimization(), perf_timer.GetDurationAverage(),
-                       perf_timer.GetDurationStandardDeviation()});
-  }
-
-  for (const auto& result : results) {
-    RTC_LOG(LS_INFO) << GetOptimizationName(result.optimization) << ": "
-                     << (result.average_us / 1e3) << " +/- "
-                     << (result.std_dev_us / 1e3) << " ms";
-  }
-}
-
-TEST(RnnVadTest, DISABLED_BenchmarkGatedRecurrentLayer) {
-  std::vector<std::unique_ptr<GatedRecurrentLayer>> implementations;
-  implementations.emplace_back(std::make_unique<GatedRecurrentLayer>(
-      kGruInputSize, kGruOutputSize, kGruBias, kGruWeights,
-      kGruRecurrentWeights, Optimization::kNone));
-
-  rtc::ArrayView<const float> input_sequence(kGruInputSequence);
-  static_assert(kGruInputSequence.size() % kGruInputSize == 0, "");
-  constexpr int input_sequence_length =
-      kGruInputSequence.size() / kGruInputSize;
-
-  std::vector<Result> results;
-  constexpr int number_of_tests = 10000;
-  for (auto& gru : implementations) {
-    ::webrtc::test::PerformanceTimer perf_timer(number_of_tests);
-    gru->Reset();
-    for (int k = 0; k < number_of_tests; ++k) {
-      perf_timer.StartTimer();
-      for (int i = 0; i < input_sequence_length; ++i) {
-        gru->ComputeOutput(
-            input_sequence.subview(i * gru->input_size(), gru->input_size()));
-      }
-      perf_timer.StopTimer();
-    }
-    results.push_back({gru->optimization(), perf_timer.GetDurationAverage(),
-                       perf_timer.GetDurationStandardDeviation()});
-  }
-
-  for (const auto& result : results) {
-    RTC_LOG(LS_INFO) << GetOptimizationName(result.optimization) << ": "
-                     << (result.average_us / 1e3) << " +/- "
-                     << (result.std_dev_us / 1e3) << " ms";
-  }
-}
-
-}  // namespace test
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_vad_tool.cc b/modules/audio_processing/agc2/rnn_vad/rnn_vad_tool.cc
index 8b12b60..a0e1242 100644
--- a/modules/audio_processing/agc2/rnn_vad/rnn_vad_tool.cc
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_vad_tool.cc
@@ -16,6 +16,7 @@
 #include "absl/flags/parse.h"
 #include "common_audio/resampler/push_sinc_resampler.h"
 #include "common_audio/wav_file.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
 #include "modules/audio_processing/agc2/rnn_vad/features_extraction.h"
 #include "modules/audio_processing/agc2/rnn_vad/rnn.h"
@@ -63,9 +64,10 @@
   samples_10ms.resize(frame_size_10ms);
   std::array<float, kFrameSize10ms24kHz> samples_10ms_24kHz;
   PushSincResampler resampler(frame_size_10ms, kFrameSize10ms24kHz);
-  FeaturesExtractor features_extractor;
+  const AvailableCpuFeatures cpu_features = GetAvailableCpuFeatures();
+  FeaturesExtractor features_extractor(cpu_features);
   std::array<float, kFeatureVectorSize> feature_vector;
-  RnnBasedVad rnn_vad;
+  RnnVad rnn_vad(cpu_features);
 
   // Compute VAD probabilities.
   while (true) {
diff --git a/modules/audio_processing/agc2/rnn_vad/rnn_vad_unittest.cc b/modules/audio_processing/agc2/rnn_vad/rnn_vad_unittest.cc
index 0916bf5..989b235 100644
--- a/modules/audio_processing/agc2/rnn_vad/rnn_vad_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/rnn_vad_unittest.cc
@@ -9,10 +9,12 @@
  */
 
 #include <array>
+#include <memory>
 #include <string>
 #include <vector>
 
 #include "common_audio/resampler/push_sinc_resampler.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/agc2/rnn_vad/features_extraction.h"
 #include "modules/audio_processing/agc2/rnn_vad/rnn.h"
 #include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
@@ -25,7 +27,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 constexpr int kFrameSize10ms48kHz = 480;
@@ -48,8 +49,6 @@
 // constant below to true in order to write new expected output binary files.
 constexpr bool kWriteComputedOutputToFile = false;
 
-}  // namespace
-
 // Avoids that one forgets to set |kWriteComputedOutputToFile| back to false
 // when the expected output files are re-exported.
 TEST(RnnVadTest, CheckWriteComputedOutputIsFalse) {
@@ -57,21 +56,24 @@
       << "Cannot land if kWriteComputedOutput is true.";
 }
 
+class RnnVadProbabilityParametrization
+    : public ::testing::TestWithParam<AvailableCpuFeatures> {};
+
 // Checks that the computed VAD probability for a test input sequence sampled at
 // 48 kHz is within tolerance.
-TEST(RnnVadTest, RnnVadProbabilityWithinTolerance) {
+TEST_P(RnnVadProbabilityParametrization, RnnVadProbabilityWithinTolerance) {
   // Init resampler, feature extractor and RNN.
   PushSincResampler decimator(kFrameSize10ms48kHz, kFrameSize10ms24kHz);
-  FeaturesExtractor features_extractor;
-  RnnBasedVad rnn_vad;
+  const AvailableCpuFeatures cpu_features = GetParam();
+  FeaturesExtractor features_extractor(cpu_features);
+  RnnVad rnn_vad(cpu_features);
 
   // Init input samples and expected output readers.
-  auto samples_reader = CreatePcmSamplesReader(kFrameSize10ms48kHz);
-  auto expected_vad_prob_reader = CreateVadProbsReader();
+  std::unique_ptr<FileReader> samples_reader = CreatePcmSamplesReader();
+  std::unique_ptr<FileReader> expected_vad_prob_reader = CreateVadProbsReader();
 
-  // Input length.
-  const int num_frames = samples_reader.second;
-  ASSERT_GE(expected_vad_prob_reader.second, num_frames);
+  // Input length. The last incomplete frame is ignored.
+  const int num_frames = samples_reader->size() / kFrameSize10ms48kHz;
 
   // Init buffers.
   std::vector<float> samples_48k(kFrameSize10ms48kHz);
@@ -81,12 +83,12 @@
   std::vector<float> expected_vad_prob(num_frames);
 
   // Read expected output.
-  ASSERT_TRUE(expected_vad_prob_reader.first->ReadChunk(expected_vad_prob));
+  ASSERT_TRUE(expected_vad_prob_reader->ReadChunk(expected_vad_prob));
 
   // Compute VAD probabilities on the downsampled input.
   float cumulative_error = 0.f;
   for (int i = 0; i < num_frames; ++i) {
-    samples_reader.first->ReadChunk(samples_48k);
+    ASSERT_TRUE(samples_reader->ReadChunk(samples_48k));
     decimator.Resample(samples_48k.data(), samples_48k.size(),
                        samples_24k.data(), samples_24k.size());
     bool is_silence = features_extractor.CheckSilenceComputeFeatures(
@@ -101,7 +103,7 @@
   EXPECT_LT(cumulative_error / num_frames, 1e-4f);
 
   if (kWriteComputedOutputToFile) {
-    BinaryFileWriter<float> vad_prob_writer("new_vad_prob.dat");
+    FileWriter vad_prob_writer("new_vad_prob.dat");
     vad_prob_writer.WriteChunk(computed_vad_prob);
   }
 }
@@ -111,25 +113,27 @@
 // follows:
 // - on desktop: run the this unit test adding "--logs";
 // - on android: run the this unit test adding "--logcat-output-file".
-TEST(RnnVadTest, DISABLED_RnnVadPerformance) {
+TEST_P(RnnVadProbabilityParametrization, DISABLED_RnnVadPerformance) {
   // PCM samples reader and buffers.
-  auto samples_reader = CreatePcmSamplesReader(kFrameSize10ms48kHz);
-  const int num_frames = samples_reader.second;
+  std::unique_ptr<FileReader> samples_reader = CreatePcmSamplesReader();
+  // The last incomplete frame is ignored.
+  const int num_frames = samples_reader->size() / kFrameSize10ms48kHz;
   std::array<float, kFrameSize10ms48kHz> samples;
   // Pre-fetch and decimate samples.
   PushSincResampler decimator(kFrameSize10ms48kHz, kFrameSize10ms24kHz);
   std::vector<float> prefetched_decimated_samples;
   prefetched_decimated_samples.resize(num_frames * kFrameSize10ms24kHz);
   for (int i = 0; i < num_frames; ++i) {
-    samples_reader.first->ReadChunk(samples);
+    ASSERT_TRUE(samples_reader->ReadChunk(samples));
     decimator.Resample(samples.data(), samples.size(),
                        &prefetched_decimated_samples[i * kFrameSize10ms24kHz],
                        kFrameSize10ms24kHz);
   }
   // Initialize.
-  FeaturesExtractor features_extractor;
+  const AvailableCpuFeatures cpu_features = GetParam();
+  FeaturesExtractor features_extractor(cpu_features);
   std::array<float, kFeatureVectorSize> feature_vector;
-  RnnBasedVad rnn_vad;
+  RnnVad rnn_vad(cpu_features);
   constexpr int number_of_tests = 100;
   ::webrtc::test::PerformanceTimer perf_timer(number_of_tests);
   for (int k = 0; k < number_of_tests; ++k) {
@@ -145,13 +149,37 @@
       rnn_vad.ComputeVadProbability(feature_vector, is_silence);
     }
     perf_timer.StopTimer();
-    samples_reader.first->SeekBeginning();
   }
   DumpPerfStats(num_frames * kFrameSize10ms24kHz, kSampleRate24kHz,
                 perf_timer.GetDurationAverage(),
                 perf_timer.GetDurationStandardDeviation());
 }
 
-}  // namespace test
+// Finds the relevant CPU features combinations to test.
+std::vector<AvailableCpuFeatures> GetCpuFeaturesToTest() {
+  std::vector<AvailableCpuFeatures> v;
+  v.push_back(NoAvailableCpuFeatures());
+  AvailableCpuFeatures available = GetAvailableCpuFeatures();
+  if (available.avx2 && available.sse2) {
+    v.push_back({/*sse2=*/true, /*avx2=*/true, /*neon=*/false});
+  }
+  if (available.sse2) {
+    v.push_back({/*sse2=*/true, /*avx2=*/false, /*neon=*/false});
+  }
+  if (available.neon) {
+    v.push_back({/*sse2=*/false, /*avx2=*/false, /*neon=*/true});
+  }
+  return v;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    RnnVadTest,
+    RnnVadProbabilityParametrization,
+    ::testing::ValuesIn(GetCpuFeaturesToTest()),
+    [](const ::testing::TestParamInfo<AvailableCpuFeatures>& info) {
+      return info.param.ToString();
+    });
+
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/sequence_buffer_unittest.cc b/modules/audio_processing/agc2/rnn_vad/sequence_buffer_unittest.cc
index 125f1b8..f577571 100644
--- a/modules/audio_processing/agc2/rnn_vad/sequence_buffer_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/sequence_buffer_unittest.cc
@@ -17,7 +17,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 template <typename T, int S, int N>
@@ -60,8 +59,6 @@
   }
 }
 
-}  // namespace
-
 TEST(RnnVadTest, SequenceBufferGetters) {
   constexpr int buffer_size = 8;
   constexpr int chunk_size = 8;
@@ -100,6 +97,6 @@
   TestSequenceBufferPushOp<float, 23, 7>();   // Non-integer ratio.
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/spectral_features_internal_unittest.cc b/modules/audio_processing/agc2/rnn_vad/spectral_features_internal_unittest.cc
index 461047d..11a44a5 100644
--- a/modules/audio_processing/agc2/rnn_vad/spectral_features_internal_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/spectral_features_internal_unittest.cc
@@ -26,7 +26,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 // Generates the values for the array named |kOpusBandWeights24kHz20ms| in the
@@ -49,8 +48,6 @@
   return weights;
 }
 
-}  // namespace
-
 // Checks that the values returned by GetOpusScaleNumBins24kHz20ms() match the
 // Opus scale frequency boundaries.
 TEST(RnnVadTest, TestOpusScaleBoundaries) {
@@ -158,6 +155,6 @@
   }
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/spectral_features_unittest.cc b/modules/audio_processing/agc2/rnn_vad/spectral_features_unittest.cc
index fa376f2..9f41e96 100644
--- a/modules/audio_processing/agc2/rnn_vad/spectral_features_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/spectral_features_unittest.cc
@@ -21,7 +21,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 constexpr int kTestFeatureVectorSize = kNumBands + 3 * kNumLowerBands + 1;
@@ -66,8 +65,6 @@
 
 constexpr float kInitialFeatureVal = -9999.f;
 
-}  // namespace
-
 // Checks that silence is detected when the input signal is 0 and that the
 // feature vector is written only if the input signal is not tagged as silence.
 TEST(RnnVadTest, SpectralFeaturesWithAndWithoutSilence) {
@@ -159,6 +156,6 @@
                   feature_vector_last[kNumBands + 3 * kNumLowerBands]);
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/symmetric_matrix_buffer_unittest.cc b/modules/audio_processing/agc2/rnn_vad/symmetric_matrix_buffer_unittest.cc
index c1da8d1..6f61c87 100644
--- a/modules/audio_processing/agc2/rnn_vad/symmetric_matrix_buffer_unittest.cc
+++ b/modules/audio_processing/agc2/rnn_vad/symmetric_matrix_buffer_unittest.cc
@@ -15,7 +15,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
 template <typename T, int S>
@@ -44,8 +43,6 @@
   return false;
 }
 
-}  // namespace
-
 // Test that shows how to combine RingBuffer and SymmetricMatrixBuffer to
 // efficiently compute pair-wise scores. This test verifies that the evolution
 // of a SymmetricMatrixBuffer instance follows that of RingBuffer.
@@ -105,6 +102,6 @@
   }
 }
 
-}  // namespace test
+}  // namespace
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/test_utils.cc b/modules/audio_processing/agc2/rnn_vad/test_utils.cc
index 24bbf13..b8ca9c3 100644
--- a/modules/audio_processing/agc2/rnn_vad/test_utils.cc
+++ b/modules/audio_processing/agc2/rnn_vad/test_utils.cc
@@ -11,22 +11,58 @@
 #include "modules/audio_processing/agc2/rnn_vad/test_utils.h"
 
 #include <algorithm>
+#include <fstream>
 #include <memory>
+#include <type_traits>
+#include <vector>
 
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_compare.h"
-#include "rtc_base/system/arch.h"
-#include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gtest.h"
 #include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 namespace {
 
-using ReaderPairType =
-    std::pair<std::unique_ptr<BinaryFileReader<float>>, const int>;
+// File reader for binary files that contain a sequence of values with
+// arithmetic type `T`. The values of type `T` that are read are cast to float.
+template <typename T>
+class FloatFileReader : public FileReader {
+ public:
+  static_assert(std::is_arithmetic<T>::value, "");
+  FloatFileReader(const std::string& filename)
+      : is_(filename, std::ios::binary | std::ios::ate),
+        size_(is_.tellg() / sizeof(T)) {
+    RTC_CHECK(is_);
+    SeekBeginning();
+  }
+  FloatFileReader(const FloatFileReader&) = delete;
+  FloatFileReader& operator=(const FloatFileReader&) = delete;
+  ~FloatFileReader() = default;
+
+  int size() const override { return size_; }
+  bool ReadChunk(rtc::ArrayView<float> dst) override {
+    const std::streamsize bytes_to_read = dst.size() * sizeof(T);
+    if (std::is_same<T, float>::value) {
+      is_.read(reinterpret_cast<char*>(dst.data()), bytes_to_read);
+    } else {
+      buffer_.resize(dst.size());
+      is_.read(reinterpret_cast<char*>(buffer_.data()), bytes_to_read);
+      std::transform(buffer_.begin(), buffer_.end(), dst.begin(),
+                     [](const T& v) -> float { return static_cast<float>(v); });
+    }
+    return is_.gcount() == bytes_to_read;
+  }
+  bool ReadValue(float& dst) override { return ReadChunk({&dst, 1}); }
+  void SeekForward(int hop) override { is_.seekg(hop * sizeof(T), is_.cur); }
+  void SeekBeginning() override { is_.seekg(0, is_.beg); }
+
+ private:
+  std::ifstream is_;
+  const int size_;
+  std::vector<T> buffer_;
+};
 
 }  // namespace
 
@@ -51,85 +87,55 @@
   }
 }
 
-std::pair<std::unique_ptr<BinaryFileReader<int16_t, float>>, const int>
-CreatePcmSamplesReader(const int frame_length) {
-  auto ptr = std::make_unique<BinaryFileReader<int16_t, float>>(
-      test::ResourcePath("audio_processing/agc2/rnn_vad/samples", "pcm"),
-      frame_length);
-  // The last incomplete frame is ignored.
-  return {std::move(ptr), ptr->data_length() / frame_length};
+std::unique_ptr<FileReader> CreatePcmSamplesReader() {
+  return std::make_unique<FloatFileReader<int16_t>>(
+      /*filename=*/test::ResourcePath("audio_processing/agc2/rnn_vad/samples",
+                                      "pcm"));
 }
 
-ReaderPairType CreatePitchBuffer24kHzReader() {
-  constexpr int cols = 864;
-  auto ptr = std::make_unique<BinaryFileReader<float>>(
-      ResourcePath("audio_processing/agc2/rnn_vad/pitch_buf_24k", "dat"), cols);
-  return {std::move(ptr), rtc::CheckedDivExact(ptr->data_length(), cols)};
+ChunksFileReader CreatePitchBuffer24kHzReader() {
+  auto reader = std::make_unique<FloatFileReader<float>>(
+      /*filename=*/test::ResourcePath(
+          "audio_processing/agc2/rnn_vad/pitch_buf_24k", "dat"));
+  const int num_chunks = rtc::CheckedDivExact(reader->size(), kBufSize24kHz);
+  return {/*chunk_size=*/kBufSize24kHz, num_chunks, std::move(reader)};
 }
 
-ReaderPairType CreateLpResidualAndPitchPeriodGainReader() {
-  constexpr int num_lp_residual_coeffs = 864;
-  auto ptr = std::make_unique<BinaryFileReader<float>>(
-      ResourcePath("audio_processing/agc2/rnn_vad/pitch_lp_res", "dat"),
-      num_lp_residual_coeffs);
-  return {std::move(ptr),
-          rtc::CheckedDivExact(ptr->data_length(), 2 + num_lp_residual_coeffs)};
+ChunksFileReader CreateLpResidualAndPitchInfoReader() {
+  constexpr int kPitchInfoSize = 2;  // Pitch period and strength.
+  constexpr int kChunkSize = kBufSize24kHz + kPitchInfoSize;
+  auto reader = std::make_unique<FloatFileReader<float>>(
+      /*filename=*/test::ResourcePath(
+          "audio_processing/agc2/rnn_vad/pitch_lp_res", "dat"));
+  const int num_chunks = rtc::CheckedDivExact(reader->size(), kChunkSize);
+  return {kChunkSize, num_chunks, std::move(reader)};
 }
 
-ReaderPairType CreateVadProbsReader() {
-  auto ptr = std::make_unique<BinaryFileReader<float>>(
-      test::ResourcePath("audio_processing/agc2/rnn_vad/vad_prob", "dat"));
-  return {std::move(ptr), ptr->data_length()};
+std::unique_ptr<FileReader> CreateGruInputReader() {
+  return std::make_unique<FloatFileReader<float>>(
+      /*filename=*/test::ResourcePath("audio_processing/agc2/rnn_vad/gru_in",
+                                      "dat"));
+}
+
+std::unique_ptr<FileReader> CreateVadProbsReader() {
+  return std::make_unique<FloatFileReader<float>>(
+      /*filename=*/test::ResourcePath("audio_processing/agc2/rnn_vad/vad_prob",
+                                      "dat"));
 }
 
 PitchTestData::PitchTestData() {
-  BinaryFileReader<float> test_data_reader(
-      ResourcePath("audio_processing/agc2/rnn_vad/pitch_search_int", "dat"),
-      1396);
-  test_data_reader.ReadChunk(test_data_);
+  FloatFileReader<float> reader(
+      /*filename=*/ResourcePath(
+          "audio_processing/agc2/rnn_vad/pitch_search_int", "dat"));
+  reader.ReadChunk(pitch_buffer_24k_);
+  reader.ReadChunk(square_energies_24k_);
+  reader.ReadChunk(auto_correlation_12k_);
   // Reverse the order of the squared energy values.
   // Required after the WebRTC CL 191703 which switched to forward computation.
-  std::reverse(test_data_.begin() + kBufSize24kHz,
-               test_data_.begin() + kBufSize24kHz + kNumPitchBufSquareEnergies);
+  std::reverse(square_energies_24k_.begin(), square_energies_24k_.end());
 }
 
 PitchTestData::~PitchTestData() = default;
 
-rtc::ArrayView<const float, kBufSize24kHz> PitchTestData::GetPitchBufView()
-    const {
-  return {test_data_.data(), kBufSize24kHz};
-}
-
-rtc::ArrayView<const float, kNumPitchBufSquareEnergies>
-PitchTestData::GetPitchBufSquareEnergiesView() const {
-  return {test_data_.data() + kBufSize24kHz, kNumPitchBufSquareEnergies};
-}
-
-rtc::ArrayView<const float, kNumPitchBufAutoCorrCoeffs>
-PitchTestData::GetPitchBufAutoCorrCoeffsView() const {
-  return {test_data_.data() + kBufSize24kHz + kNumPitchBufSquareEnergies,
-          kNumPitchBufAutoCorrCoeffs};
-}
-
-bool IsOptimizationAvailable(Optimization optimization) {
-  switch (optimization) {
-    case Optimization::kSse2:
-#if defined(WEBRTC_ARCH_X86_FAMILY)
-      return GetCPUInfo(kSSE2) != 0;
-#else
-      return false;
-#endif
-    case Optimization::kNeon:
-#if defined(WEBRTC_HAS_NEON)
-      return true;
-#else
-      return false;
-#endif
-    case Optimization::kNone:
-      return true;
-  }
-}
-
-}  // namespace test
 }  // namespace rnn_vad
 }  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/test_utils.h b/modules/audio_processing/agc2/rnn_vad/test_utils.h
index 23e642b..e366e18 100644
--- a/modules/audio_processing/agc2/rnn_vad/test_utils.h
+++ b/modules/audio_processing/agc2/rnn_vad/test_utils.h
@@ -11,15 +11,10 @@
 #ifndef MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_TEST_UTILS_H_
 #define MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_TEST_UTILS_H_
 
-#include <algorithm>
 #include <array>
 #include <fstream>
-#include <limits>
 #include <memory>
 #include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
 
 #include "api/array_view.h"
 #include "modules/audio_processing/agc2/rnn_vad/common.h"
@@ -28,7 +23,6 @@
 
 namespace webrtc {
 namespace rnn_vad {
-namespace test {
 
 constexpr float kFloatMin = std::numeric_limits<float>::min();
 
@@ -43,98 +37,51 @@
                         rtc::ArrayView<const float> computed,
                         float tolerance);
 
-// Reader for binary files consisting of an arbitrary long sequence of elements
-// having type T. It is possible to read and cast to another type D at once.
-template <typename T, typename D = T>
-class BinaryFileReader {
+// File reader interface.
+class FileReader {
  public:
-  BinaryFileReader(const std::string& file_path, int chunk_size = 0)
-      : is_(file_path, std::ios::binary | std::ios::ate),
-        data_length_(is_.tellg() / sizeof(T)),
-        chunk_size_(chunk_size) {
-    RTC_CHECK(is_);
-    SeekBeginning();
-    buf_.resize(chunk_size_);
-  }
-  BinaryFileReader(const BinaryFileReader&) = delete;
-  BinaryFileReader& operator=(const BinaryFileReader&) = delete;
-  ~BinaryFileReader() = default;
-  int data_length() const { return data_length_; }
-  bool ReadValue(D* dst) {
-    if (std::is_same<T, D>::value) {
-      is_.read(reinterpret_cast<char*>(dst), sizeof(T));
-    } else {
-      T v;
-      is_.read(reinterpret_cast<char*>(&v), sizeof(T));
-      *dst = static_cast<D>(v);
-    }
-    return is_.gcount() == sizeof(T);
-  }
-  // If |chunk_size| was specified in the ctor, it will check that the size of
-  // |dst| equals |chunk_size|.
-  bool ReadChunk(rtc::ArrayView<D> dst) {
-    RTC_DCHECK((chunk_size_ == 0) || rtc::SafeEq(chunk_size_, dst.size()));
-    const std::streamsize bytes_to_read = dst.size() * sizeof(T);
-    if (std::is_same<T, D>::value) {
-      is_.read(reinterpret_cast<char*>(dst.data()), bytes_to_read);
-    } else {
-      is_.read(reinterpret_cast<char*>(buf_.data()), bytes_to_read);
-      std::transform(buf_.begin(), buf_.end(), dst.begin(),
-                     [](const T& v) -> D { return static_cast<D>(v); });
-    }
-    return is_.gcount() == bytes_to_read;
-  }
-  void SeekForward(int items) { is_.seekg(items * sizeof(T), is_.cur); }
-  void SeekBeginning() { is_.seekg(0, is_.beg); }
-
- private:
-  std::ifstream is_;
-  const int data_length_;
-  const int chunk_size_;
-  std::vector<T> buf_;
+  virtual ~FileReader() = default;
+  // Number of values in the file.
+  virtual int size() const = 0;
+  // Reads `dst.size()` float values into `dst`, advances the internal file
+  // position according to the number of read bytes and returns true if the
+  // values are correctly read. If the number of remaining bytes in the file is
+  // not sufficient to read `dst.size()` float values, `dst` is partially
+  // modified and false is returned.
+  virtual bool ReadChunk(rtc::ArrayView<float> dst) = 0;
+  // Reads a single float value, advances the internal file position according
+  // to the number of read bytes and returns true if the value is correctly
+  // read. If the number of remaining bytes in the file is not sufficient to
+  // read one float, `dst` is not modified and false is returned.
+  virtual bool ReadValue(float& dst) = 0;
+  // Advances the internal file position by `hop` float values.
+  virtual void SeekForward(int hop) = 0;
+  // Resets the internal file position to BOF.
+  virtual void SeekBeginning() = 0;
 };
 
-// Writer for binary files.
-template <typename T>
-class BinaryFileWriter {
- public:
-  explicit BinaryFileWriter(const std::string& file_path)
-      : os_(file_path, std::ios::binary) {}
-  BinaryFileWriter(const BinaryFileWriter&) = delete;
-  BinaryFileWriter& operator=(const BinaryFileWriter&) = delete;
-  ~BinaryFileWriter() = default;
-  static_assert(std::is_arithmetic<T>::value, "");
-  void WriteChunk(rtc::ArrayView<const T> value) {
-    const std::streamsize bytes_to_write = value.size() * sizeof(T);
-    os_.write(reinterpret_cast<const char*>(value.data()), bytes_to_write);
-  }
-
- private:
-  std::ofstream os_;
+// File reader for files that contain `num_chunks` chunks with size equal to
+// `chunk_size`.
+struct ChunksFileReader {
+  const int chunk_size;
+  const int num_chunks;
+  std::unique_ptr<FileReader> reader;
 };
 
-// Factories for resource file readers.
-// The functions below return a pair where the first item is a reader unique
-// pointer and the second the number of chunks that can be read from the file.
-// Creates a reader for the PCM samples that casts from S16 to float and reads
-// chunks with length |frame_length|.
-std::pair<std::unique_ptr<BinaryFileReader<int16_t, float>>, const int>
-CreatePcmSamplesReader(const int frame_length);
-// Creates a reader for the pitch buffer content at 24 kHz.
-std::pair<std::unique_ptr<BinaryFileReader<float>>, const int>
-CreatePitchBuffer24kHzReader();
-// Creates a reader for the the LP residual coefficients and the pitch period
-// and gain values.
-std::pair<std::unique_ptr<BinaryFileReader<float>>, const int>
-CreateLpResidualAndPitchPeriodGainReader();
-// Creates a reader for the VAD probabilities.
-std::pair<std::unique_ptr<BinaryFileReader<float>>, const int>
-CreateVadProbsReader();
+// Creates a reader for the PCM S16 samples file.
+std::unique_ptr<FileReader> CreatePcmSamplesReader();
 
-constexpr int kNumPitchBufAutoCorrCoeffs = 147;
-constexpr int kNumPitchBufSquareEnergies = 385;
-constexpr int kPitchTestDataSize =
-    kBufSize24kHz + kNumPitchBufSquareEnergies + kNumPitchBufAutoCorrCoeffs;
+// Creates a reader for the 24 kHz pitch buffer test data.
+ChunksFileReader CreatePitchBuffer24kHzReader();
+
+// Creates a reader for the LP residual and pitch information test data.
+ChunksFileReader CreateLpResidualAndPitchInfoReader();
+
+// Creates a reader for the sequence of GRU input vectors.
+std::unique_ptr<FileReader> CreateGruInputReader();
+
+// Creates a reader for the VAD probabilities test data.
+std::unique_ptr<FileReader> CreateVadProbsReader();
 
 // Class to retrieve a test pitch buffer content and the expected output for the
 // analysis steps.
@@ -142,20 +89,40 @@
  public:
   PitchTestData();
   ~PitchTestData();
-  rtc::ArrayView<const float, kBufSize24kHz> GetPitchBufView() const;
-  rtc::ArrayView<const float, kNumPitchBufSquareEnergies>
-  GetPitchBufSquareEnergiesView() const;
-  rtc::ArrayView<const float, kNumPitchBufAutoCorrCoeffs>
-  GetPitchBufAutoCorrCoeffsView() const;
+  rtc::ArrayView<const float, kBufSize24kHz> PitchBuffer24kHzView() const {
+    return pitch_buffer_24k_;
+  }
+  rtc::ArrayView<const float, kRefineNumLags24kHz> SquareEnergies24kHzView()
+      const {
+    return square_energies_24k_;
+  }
+  rtc::ArrayView<const float, kNumLags12kHz> AutoCorrelation12kHzView() const {
+    return auto_correlation_12k_;
+  }
 
  private:
-  std::array<float, kPitchTestDataSize> test_data_;
+  std::array<float, kBufSize24kHz> pitch_buffer_24k_;
+  std::array<float, kRefineNumLags24kHz> square_energies_24k_;
+  std::array<float, kNumLags12kHz> auto_correlation_12k_;
 };
 
-// Returns true if the given optimization is available.
-bool IsOptimizationAvailable(Optimization optimization);
+// Writer for binary files.
+class FileWriter {
+ public:
+  explicit FileWriter(const std::string& file_path)
+      : os_(file_path, std::ios::binary) {}
+  FileWriter(const FileWriter&) = delete;
+  FileWriter& operator=(const FileWriter&) = delete;
+  ~FileWriter() = default;
+  void WriteChunk(rtc::ArrayView<const float> value) {
+    const std::streamsize bytes_to_write = value.size() * sizeof(float);
+    os_.write(reinterpret_cast<const char*>(value.data()), bytes_to_write);
+  }
 
-}  // namespace test
+ private:
+  std::ofstream os_;
+};
+
 }  // namespace rnn_vad
 }  // namespace webrtc
 
diff --git a/modules/audio_processing/agc2/rnn_vad/vector_math.h b/modules/audio_processing/agc2/rnn_vad/vector_math.h
new file mode 100644
index 0000000..47f6811
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/vector_math.h
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_VECTOR_MATH_H_
+#define MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_VECTOR_MATH_H_
+
+// Defines WEBRTC_ARCH_X86_FAMILY, used below.
+#include "rtc_base/system/arch.h"
+
+#if defined(WEBRTC_HAS_NEON)
+#include <arm_neon.h>
+#endif
+#if defined(WEBRTC_ARCH_X86_FAMILY)
+#include <emmintrin.h>
+#endif
+
+#include <numeric>
+
+#include "api/array_view.h"
+#include "modules/audio_processing/agc2/cpu_features.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/system/arch.h"
+
+namespace webrtc {
+namespace rnn_vad {
+
+// Provides optimizations for mathematical operations having vectors as
+// operand(s).
+class VectorMath {
+ public:
+  explicit VectorMath(AvailableCpuFeatures cpu_features)
+      : cpu_features_(cpu_features) {}
+
+  // Computes the dot product between two equally sized vectors.
+  float DotProduct(rtc::ArrayView<const float> x,
+                   rtc::ArrayView<const float> y) const {
+    RTC_DCHECK_EQ(x.size(), y.size());
+#if defined(WEBRTC_ARCH_X86_FAMILY)
+    if (cpu_features_.avx2) {
+      return DotProductAvx2(x, y);
+    } else if (cpu_features_.sse2) {
+      __m128 accumulator = _mm_setzero_ps();
+      constexpr int kBlockSizeLog2 = 2;
+      constexpr int kBlockSize = 1 << kBlockSizeLog2;
+      const int incomplete_block_index = (x.size() >> kBlockSizeLog2)
+                                         << kBlockSizeLog2;
+      for (int i = 0; i < incomplete_block_index; i += kBlockSize) {
+        RTC_DCHECK_LE(i + kBlockSize, x.size());
+        const __m128 x_i = _mm_loadu_ps(&x[i]);
+        const __m128 y_i = _mm_loadu_ps(&y[i]);
+        // Multiply-add.
+        const __m128 z_j = _mm_mul_ps(x_i, y_i);
+        accumulator = _mm_add_ps(accumulator, z_j);
+      }
+      // Reduce `accumulator` by addition.
+      __m128 high = _mm_movehl_ps(accumulator, accumulator);
+      accumulator = _mm_add_ps(accumulator, high);
+      high = _mm_shuffle_ps(accumulator, accumulator, 1);
+      accumulator = _mm_add_ps(accumulator, high);
+      float dot_product = _mm_cvtss_f32(accumulator);
+      // Add the result for the last block if incomplete.
+      for (int i = incomplete_block_index;
+           i < rtc::dchecked_cast<int>(x.size()); ++i) {
+        dot_product += x[i] * y[i];
+      }
+      return dot_product;
+    }
+#elif defined(WEBRTC_HAS_NEON) && defined(WEBRTC_ARCH_ARM64)
+    if (cpu_features_.neon) {
+      float32x4_t accumulator = vdupq_n_f32(0.f);
+      constexpr int kBlockSizeLog2 = 2;
+      constexpr int kBlockSize = 1 << kBlockSizeLog2;
+      const int incomplete_block_index = (x.size() >> kBlockSizeLog2)
+                                         << kBlockSizeLog2;
+      for (int i = 0; i < incomplete_block_index; i += kBlockSize) {
+        RTC_DCHECK_LE(i + kBlockSize, x.size());
+        const float32x4_t x_i = vld1q_f32(&x[i]);
+        const float32x4_t y_i = vld1q_f32(&y[i]);
+        accumulator = vfmaq_f32(accumulator, x_i, y_i);
+      }
+      // Reduce `accumulator` by addition.
+      const float32x2_t tmp =
+          vpadd_f32(vget_low_f32(accumulator), vget_high_f32(accumulator));
+      float dot_product = vget_lane_f32(vpadd_f32(tmp, vrev64_f32(tmp)), 0);
+      // Add the result for the last block if incomplete.
+      for (int i = incomplete_block_index;
+           i < rtc::dchecked_cast<int>(x.size()); ++i) {
+        dot_product += x[i] * y[i];
+      }
+      return dot_product;
+    }
+#endif
+    return std::inner_product(x.begin(), x.end(), y.begin(), 0.f);
+  }
+
+ private:
+  float DotProductAvx2(rtc::ArrayView<const float> x,
+                       rtc::ArrayView<const float> y) const;
+
+  const AvailableCpuFeatures cpu_features_;
+};
+
+}  // namespace rnn_vad
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_VECTOR_MATH_H_
diff --git a/modules/audio_processing/agc2/rnn_vad/vector_math_avx2.cc b/modules/audio_processing/agc2/rnn_vad/vector_math_avx2.cc
new file mode 100644
index 0000000..e4d246d
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/vector_math_avx2.cc
@@ -0,0 +1,55 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/agc2/rnn_vad/vector_math.h"
+
+#include <immintrin.h>
+
+#include "api/array_view.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+namespace rnn_vad {
+
+float VectorMath::DotProductAvx2(rtc::ArrayView<const float> x,
+                                 rtc::ArrayView<const float> y) const {
+  RTC_DCHECK(cpu_features_.avx2);
+  RTC_DCHECK_EQ(x.size(), y.size());
+  __m256 accumulator = _mm256_setzero_ps();
+  constexpr int kBlockSizeLog2 = 3;
+  constexpr int kBlockSize = 1 << kBlockSizeLog2;
+  const int incomplete_block_index = (x.size() >> kBlockSizeLog2)
+                                     << kBlockSizeLog2;
+  for (int i = 0; i < incomplete_block_index; i += kBlockSize) {
+    RTC_DCHECK_LE(i + kBlockSize, x.size());
+    const __m256 x_i = _mm256_loadu_ps(&x[i]);
+    const __m256 y_i = _mm256_loadu_ps(&y[i]);
+    accumulator = _mm256_fmadd_ps(x_i, y_i, accumulator);
+  }
+  // Reduce `accumulator` by addition.
+  __m128 high = _mm256_extractf128_ps(accumulator, 1);
+  __m128 low = _mm256_extractf128_ps(accumulator, 0);
+  low = _mm_add_ps(high, low);
+  high = _mm_movehl_ps(high, low);
+  low = _mm_add_ps(high, low);
+  high = _mm_shuffle_ps(low, low, 1);
+  low = _mm_add_ss(high, low);
+  float dot_product = _mm_cvtss_f32(low);
+  // Add the result for the last block if incomplete.
+  for (int i = incomplete_block_index; i < rtc::dchecked_cast<int>(x.size());
+       ++i) {
+    dot_product += x[i] * y[i];
+  }
+  return dot_product;
+}
+
+}  // namespace rnn_vad
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/rnn_vad/vector_math_unittest.cc b/modules/audio_processing/agc2/rnn_vad/vector_math_unittest.cc
new file mode 100644
index 0000000..45fd65d
--- /dev/null
+++ b/modules/audio_processing/agc2/rnn_vad/vector_math_unittest.cc
@@ -0,0 +1,71 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/agc2/rnn_vad/vector_math.h"
+
+#include <vector>
+
+#include "modules/audio_processing/agc2/cpu_features.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace rnn_vad {
+namespace {
+
+constexpr int kSizeOfX = 19;
+constexpr float kX[kSizeOfX] = {
+    0.31593041f, 0.9350786f,   -0.25252445f, -0.86956251f, -0.9673632f,
+    0.54571901f, -0.72504495f, -0.79509912f, -0.25525012f, -0.73340473f,
+    0.15747377f, -0.04370565f, 0.76135145f,  -0.57239645f, 0.68616848f,
+    0.3740298f,  0.34710799f,  -0.92207423f, 0.10738454f};
+constexpr int kSizeOfXSubSpan = 16;
+static_assert(kSizeOfXSubSpan < kSizeOfX, "");
+constexpr float kEnergyOfX = 7.315563958160327f;
+constexpr float kEnergyOfXSubspan = 6.333327669592963f;
+
+class VectorMathParametrization
+    : public ::testing::TestWithParam<AvailableCpuFeatures> {};
+
+TEST_P(VectorMathParametrization, TestDotProduct) {
+  VectorMath vector_math(/*cpu_features=*/GetParam());
+  EXPECT_FLOAT_EQ(vector_math.DotProduct(kX, kX), kEnergyOfX);
+  EXPECT_FLOAT_EQ(
+      vector_math.DotProduct({kX, kSizeOfXSubSpan}, {kX, kSizeOfXSubSpan}),
+      kEnergyOfXSubspan);
+}
+
+// Finds the relevant CPU features combinations to test.
+std::vector<AvailableCpuFeatures> GetCpuFeaturesToTest() {
+  std::vector<AvailableCpuFeatures> v;
+  v.push_back({/*sse2=*/false, /*avx2=*/false, /*neon=*/false});
+  AvailableCpuFeatures available = GetAvailableCpuFeatures();
+  if (available.avx2) {
+    v.push_back({/*sse2=*/false, /*avx2=*/true, /*neon=*/false});
+  }
+  if (available.sse2) {
+    v.push_back({/*sse2=*/true, /*avx2=*/false, /*neon=*/false});
+  }
+  if (available.neon) {
+    v.push_back({/*sse2=*/false, /*avx2=*/false, /*neon=*/true});
+  }
+  return v;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    RnnVadTest,
+    VectorMathParametrization,
+    ::testing::ValuesIn(GetCpuFeaturesToTest()),
+    [](const ::testing::TestParamInfo<AvailableCpuFeatures>& info) {
+      return info.param.ToString();
+    });
+
+}  // namespace
+}  // namespace rnn_vad
+}  // namespace webrtc
diff --git a/modules/audio_processing/agc2/vad_with_level.cc b/modules/audio_processing/agc2/vad_with_level.cc
index 3dbb557..b54ae56 100644
--- a/modules/audio_processing/agc2/vad_with_level.cc
+++ b/modules/audio_processing/agc2/vad_with_level.cc
@@ -32,7 +32,8 @@
 // Computes the speech probability on the first channel.
 class Vad : public VoiceActivityDetector {
  public:
-  Vad() = default;
+  explicit Vad(const AvailableCpuFeatures& cpu_features)
+      : features_extractor_(cpu_features), rnn_vad_(cpu_features) {}
   Vad(const Vad&) = delete;
   Vad& operator=(const Vad&) = delete;
   ~Vad() = default;
@@ -59,7 +60,7 @@
  private:
   PushResampler<float> resampler_;
   rnn_vad::FeaturesExtractor features_extractor_;
-  rnn_vad::RnnBasedVad rnn_vad_;
+  rnn_vad::RnnVad rnn_vad_;
 };
 
 // Returns an updated version of `p_old` by using instant decay and the given
@@ -80,10 +81,12 @@
 
 VadLevelAnalyzer::VadLevelAnalyzer()
     : VadLevelAnalyzer(kDefaultSmoothedVadProbabilityAttack,
-                       std::make_unique<Vad>()) {}
+                       GetAvailableCpuFeatures()) {}
 
-VadLevelAnalyzer::VadLevelAnalyzer(float vad_probability_attack)
-    : VadLevelAnalyzer(vad_probability_attack, std::make_unique<Vad>()) {}
+VadLevelAnalyzer::VadLevelAnalyzer(float vad_probability_attack,
+                                   const AvailableCpuFeatures& cpu_features)
+    : VadLevelAnalyzer(vad_probability_attack,
+                       std::make_unique<Vad>(cpu_features)) {}
 
 VadLevelAnalyzer::VadLevelAnalyzer(float vad_probability_attack,
                                    std::unique_ptr<VoiceActivityDetector> vad)
diff --git a/modules/audio_processing/agc2/vad_with_level.h b/modules/audio_processing/agc2/vad_with_level.h
index ce72cdc..2a67882 100644
--- a/modules/audio_processing/agc2/vad_with_level.h
+++ b/modules/audio_processing/agc2/vad_with_level.h
@@ -13,6 +13,7 @@
 
 #include <memory>
 
+#include "modules/audio_processing/agc2/cpu_features.h"
 #include "modules/audio_processing/include/audio_frame_view.h"
 
 namespace webrtc {
@@ -36,7 +37,8 @@
 
   // Ctor. Uses the default VAD.
   VadLevelAnalyzer();
-  explicit VadLevelAnalyzer(float vad_probability_attack);
+  VadLevelAnalyzer(float vad_probability_attack,
+                   const AvailableCpuFeatures& cpu_features);
   // Ctor. Uses a custom `vad`.
   VadLevelAnalyzer(float vad_probability_attack,
                    std::unique_ptr<VoiceActivityDetector> vad);
diff --git a/modules/audio_processing/audio_processing_impl.cc b/modules/audio_processing/audio_processing_impl.cc
index 56d7073..37112f0 100644
--- a/modules/audio_processing/audio_processing_impl.cc
+++ b/modules/audio_processing/audio_processing_impl.cc
@@ -1476,8 +1476,8 @@
       rtc::ArrayView<const float> channel_view =
           rtc::ArrayView<const float>(linear_aec_buffer->channels_const()[ch],
                                       linear_aec_buffer->num_frames());
-      std::copy(channel_view.begin(), channel_view.end(),
-                linear_output[ch].begin());
+      FloatS16ToFloat(channel_view.data(), channel_view.size(),
+                      linear_output[ch].data());
     }
     return true;
   }
diff --git a/modules/audio_processing/gain_controller2.cc b/modules/audio_processing/gain_controller2.cc
index 6561beb..4477065 100644
--- a/modules/audio_processing/gain_controller2.cc
+++ b/modules/audio_processing/gain_controller2.cc
@@ -16,6 +16,7 @@
 #include "modules/audio_processing/logging/apm_data_dumper.h"
 #include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
@@ -27,7 +28,8 @@
           new ApmDataDumper(rtc::AtomicOps::Increment(&instance_count_))),
       gain_applier_(/*hard_clip_samples=*/false,
                     /*initial_gain_factor=*/0.f),
-      limiter_(static_cast<size_t>(48000), data_dumper_.get(), "Agc2") {
+      limiter_(static_cast<size_t>(48000), data_dumper_.get(), "Agc2"),
+      calls_since_last_limiter_log_(0) {
   if (config_.adaptive_digital.enabled) {
     adaptive_agc_.reset(new AdaptiveAgc(data_dumper_.get()));
   }
@@ -43,6 +45,7 @@
   limiter_.SetSampleRate(sample_rate_hz);
   data_dumper_->InitiateNewSetOfRecordings();
   data_dumper_->DumpRaw("sample_rate_hz", sample_rate_hz);
+  calls_since_last_limiter_log_ = 0;
 }
 
 void GainController2::Process(AudioBuffer* audio) {
@@ -54,6 +57,18 @@
     adaptive_agc_->Process(float_frame, limiter_.LastAudioLevel());
   }
   limiter_.Process(float_frame);
+
+  // Log limiter stats every 30 seconds.
+  ++calls_since_last_limiter_log_;
+  if (calls_since_last_limiter_log_ == 3000) {
+    calls_since_last_limiter_log_ = 0;
+    InterpolatedGainCurve::Stats stats = limiter_.GetGainCurveStats();
+    RTC_LOG(LS_INFO) << "AGC2 limiter stats"
+                     << " | identity: " << stats.look_ups_identity_region
+                     << " | knee: " << stats.look_ups_knee_region
+                     << " | limiter: " << stats.look_ups_limiter_region
+                     << " | saturation: " << stats.look_ups_saturation_region;
+  }
 }
 
 void GainController2::NotifyAnalogLevel(int level) {
diff --git a/modules/audio_processing/gain_controller2.h b/modules/audio_processing/gain_controller2.h
index da27fdc..31665bd 100644
--- a/modules/audio_processing/gain_controller2.h
+++ b/modules/audio_processing/gain_controller2.h
@@ -46,6 +46,7 @@
   GainApplier gain_applier_;
   std::unique_ptr<AdaptiveAgc> adaptive_agc_;
   Limiter limiter_;
+  int calls_since_last_limiter_log_;
   int analog_level_ = -1;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(GainController2);
diff --git a/modules/audio_processing/include/audio_processing.cc b/modules/audio_processing/include/audio_processing.cc
index 04336b6..3bc0075 100644
--- a/modules/audio_processing/include/audio_processing.cc
+++ b/modules/audio_processing/include/audio_processing.cc
@@ -123,12 +123,12 @@
   char buf[2048];
   rtc::SimpleStringBuilder builder(buf);
   builder << "AudioProcessing::Config{ "
-             "pipeline: {"
+             "pipeline: { "
              "maximum_internal_processing_rate: "
           << pipeline.maximum_internal_processing_rate
           << ", multi_channel_render: " << pipeline.multi_channel_render
           << ", multi_channel_capture: " << pipeline.multi_channel_capture
-          << "}, pre_amplifier: { enabled: " << pre_amplifier.enabled
+          << " }, pre_amplifier: { enabled: " << pre_amplifier.enabled
           << ", fixed_gain_factor: " << pre_amplifier.fixed_gain_factor
           << " }, high_pass_filter: { enabled: " << high_pass_filter.enabled
           << " }, echo_canceller: { enabled: " << echo_canceller.enabled
@@ -151,9 +151,11 @@
           << " }, gain_controller2: { enabled: " << gain_controller2.enabled
           << ", fixed_digital: { gain_db: "
           << gain_controller2.fixed_digital.gain_db
-          << "}, adaptive_digital: { enabled: "
+          << " }, adaptive_digital: { enabled: "
           << gain_controller2.adaptive_digital.enabled
-          << ", level_estimator: { type: "
+          << ", level_estimator: { vad_probability_attack: "
+          << gain_controller2.adaptive_digital.vad_probability_attack
+          << ", type: "
           << GainController2LevelEstimatorToString(
                  gain_controller2.adaptive_digital.level_estimator)
           << ", adjacent_speech_frames_threshold: "
@@ -163,17 +165,17 @@
           << gain_controller2.adaptive_digital.initial_saturation_margin_db
           << ", extra_saturation_margin_db: "
           << gain_controller2.adaptive_digital.extra_saturation_margin_db
-          << "}, gain_applier: { adjacent_speech_frames_threshold: "
+          << " }, gain_applier: { adjacent_speech_frames_threshold: "
           << gain_controller2.adaptive_digital
                  .gain_applier_adjacent_speech_frames_threshold
           << ", max_gain_change_db_per_second: "
           << gain_controller2.adaptive_digital.max_gain_change_db_per_second
           << ", max_output_noise_level_dbfs: "
           << gain_controller2.adaptive_digital.max_output_noise_level_dbfs
-          << " } }, residual_echo_detector: { enabled: "
+          << " }}}, residual_echo_detector: { enabled: "
           << residual_echo_detector.enabled
           << " }, level_estimation: { enabled: " << level_estimation.enabled
-          << " }}}";
+          << " }}";
   return builder.str();
 }
 
diff --git a/modules/audio_processing/include/audio_processing.h b/modules/audio_processing/include/audio_processing.h
index e85ac0c..942e0c0 100644
--- a/modules/audio_processing/include/audio_processing.h
+++ b/modules/audio_processing/include/audio_processing.h
@@ -187,7 +187,7 @@
 // analog_level = apm->recommended_stream_analog_level();
 // has_voice = apm->stream_has_voice();
 //
-// // Repeate render and capture processing for the duration of the call...
+// // Repeat render and capture processing for the duration of the call...
 // // Start a new call...
 // apm->Initialize();
 //
@@ -350,10 +350,10 @@
 
       enum LevelEstimator { kRms, kPeak };
       bool enabled = false;
-      struct {
+      struct FixedDigital {
         float gain_db = 0.f;
       } fixed_digital;
-      struct {
+      struct AdaptiveDigital {
         bool enabled = false;
         float vad_probability_attack = 1.f;
         LevelEstimator level_estimator = kRms;
@@ -365,6 +365,9 @@
         int gain_applier_adjacent_speech_frames_threshold = 1;
         float max_gain_change_db_per_second = 3.f;
         float max_output_noise_level_dbfs = -50.f;
+        bool sse2_allowed = true;
+        bool avx2_allowed = true;
+        bool neon_allowed = true;
       } adaptive_digital;
     } gain_controller2;
 
@@ -713,7 +716,7 @@
   static constexpr int kMaxNativeSampleRateHz =
       kNativeSampleRatesHz[kNumNativeSampleRates - 1];
 
-  static const int kChunkSizeMs = 10;
+  static constexpr int kChunkSizeMs = 10;
 };
 
 class RTC_EXPORT AudioProcessingBuilder {
diff --git a/modules/audio_processing/include/mock_audio_processing.h b/modules/audio_processing/include/mock_audio_processing.h
index 2055f7e..db9ab97 100644
--- a/modules/audio_processing/include/mock_audio_processing.h
+++ b/modules/audio_processing/include/mock_audio_processing.h
@@ -67,7 +67,7 @@
   MOCK_METHOD(bool, ActiveProcessing, (), (const, override));
 };
 
-class MockAudioProcessing : public ::testing::NiceMock<AudioProcessing> {
+class MockAudioProcessing : public AudioProcessing {
  public:
   MockAudioProcessing() {}
 
diff --git a/modules/audio_processing/module.mk b/modules/audio_processing/module.mk
index 483fe9a..51312e1 100644
--- a/modules/audio_processing/module.mk
+++ b/modules/audio_processing/module.mk
@@ -103,7 +103,6 @@
 	modules/audio_processing/agc2/vad_with_level.o \
 	modules/audio_processing/agc2/vector_float_frame.o \
 	modules/audio_processing/agc2/rnn_vad/auto_correlation.o \
-	modules/audio_processing/agc2/rnn_vad/common.o \
 	modules/audio_processing/agc2/rnn_vad/features_extraction.o \
 	modules/audio_processing/agc2/rnn_vad/lp_residual.o \
 	modules/audio_processing/agc2/rnn_vad/pitch_search.o \
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index 9761790..e10d846 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -298,6 +298,7 @@
     "../../rtc_base/experiments:field_trial_parser",
     "../../rtc_base/synchronization:mutex",
     "../../rtc_base/synchronization:sequence_checker",
+    "../../rtc_base/system:no_unique_address",
     "../../rtc_base/task_utils:pending_task_safety_flag",
     "../../rtc_base/task_utils:repeating_task",
     "../../rtc_base/task_utils:to_queued_task",
@@ -318,6 +319,11 @@
   ]
 }
 
+rtc_source_set("rtp_rtcp_legacy") {
+  # TODO(bugs.webrtc.org/11581): The files "source/rtp_rtcp_impl.cc"
+  # and "source/rtp_rtcp_impl.h" should be moved to this target.
+}
+
 rtc_library("rtcp_transceiver") {
   visibility = [ "*" ]
   public = [
@@ -522,6 +528,7 @@
       ":rtcp_transceiver",
       ":rtp_rtcp",
       ":rtp_rtcp_format",
+      ":rtp_rtcp_legacy",
       "../../api:array_view",
       "../../api:libjingle_peerconnection_api",
       "../../api:mock_frame_encryptor",
diff --git a/modules/rtp_rtcp/include/flexfec_receiver.h b/modules/rtp_rtcp/include/flexfec_receiver.h
index 6df984f..f9bac9c 100644
--- a/modules/rtp_rtcp/include/flexfec_receiver.h
+++ b/modules/rtp_rtcp/include/flexfec_receiver.h
@@ -20,6 +20,7 @@
 #include "modules/rtp_rtcp/source/forward_error_correction.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -69,7 +70,7 @@
   int64_t last_recovered_packet_ms_ RTC_GUARDED_BY(sequence_checker_);
   FecPacketCounter packet_counter_ RTC_GUARDED_BY(sequence_checker_);
 
-  SequenceChecker sequence_checker_;
+  RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_;
 };
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
index 70b073c..77289c9 100644
--- a/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
+++ b/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h
@@ -149,8 +149,6 @@
               GetLatestReportBlockData,
               (),
               (const, override));
-  MOCK_METHOD(void, SetRtcpXrRrtrStatus, (bool enable), (override));
-  MOCK_METHOD(bool, RtcpXrRrtrStatus, (), (const, override));
   MOCK_METHOD(void,
               SetRemb,
               (int64_t bitrate, std::vector<uint32_t> ssrcs),
@@ -168,7 +166,6 @@
               SetStorePacketsStatus,
               (bool enable, uint16_t number_to_store),
               (override));
-  MOCK_METHOD(bool, StorePackets, (), (const, override));
   MOCK_METHOD(void,
               SendCombinedRtcpPacket,
               (std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets),
diff --git a/modules/rtp_rtcp/source/fec_test_helper.cc b/modules/rtp_rtcp/source/fec_test_helper.cc
index f8579b4..ff736fd 100644
--- a/modules/rtp_rtcp/source/fec_test_helper.cc
+++ b/modules/rtp_rtcp/source/fec_test_helper.cc
@@ -57,7 +57,7 @@
     media_packet->data.SetSize(
         random_->Rand(min_packet_size_, max_packet_size_));
 
-    uint8_t* data = media_packet->data.data();
+    uint8_t* data = media_packet->data.MutableData();
     // Generate random values for the first 2 bytes
     data[0] = random_->Rand<uint8_t>();
     data[1] = random_->Rand<uint8_t>();
@@ -88,7 +88,7 @@
   // Last packet, set marker bit.
   ForwardErrorCorrection::Packet* media_packet = media_packets.back().get();
   RTC_DCHECK(media_packet);
-  media_packet->data[1] |= 0x80;
+  media_packet->data.MutableData()[1] |= 0x80;
 
   next_seq_num_ = seq_num;
 
@@ -122,7 +122,7 @@
   std::unique_ptr<AugmentedPacket> packet(new AugmentedPacket());
 
   packet->data.SetSize(length + kRtpHeaderSize);
-  uint8_t* data = packet->data.data();
+  uint8_t* data = packet->data.MutableData();
   for (size_t i = 0; i < length; ++i)
     data[i + kRtpHeaderSize] = offset + i;
   packet->data.SetSize(length + kRtpHeaderSize);
@@ -132,7 +132,7 @@
   packet->header.sequenceNumber = seq_num_;
   packet->header.timestamp = timestamp_;
   packet->header.ssrc = ssrc_;
-  WriteRtpHeader(packet->header, packet->data.data());
+  WriteRtpHeader(packet->header, data);
   ++seq_num_;
   --num_packets_;
 
@@ -171,8 +171,8 @@
   std::unique_ptr<AugmentedPacket> packet_with_rtp_header(
       new AugmentedPacket());
   packet_with_rtp_header->data.SetSize(kRtpHeaderSize + packet.data.size());
-  WriteRtpHeader(header, packet_with_rtp_header->data.data());
-  memcpy(packet_with_rtp_header->data.data() + kRtpHeaderSize,
+  WriteRtpHeader(header, packet_with_rtp_header->data.MutableData());
+  memcpy(packet_with_rtp_header->data.MutableData() + kRtpHeaderSize,
          packet.data.cdata(), packet.data.size());
 
   return packet_with_rtp_header;
diff --git a/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc b/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc
index ab0dcb6..8b4162f 100644
--- a/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc
+++ b/modules/rtp_rtcp/source/flexfec_header_reader_writer.cc
@@ -85,7 +85,7 @@
     RTC_LOG(LS_WARNING) << "Discarding truncated FlexFEC packet.";
     return false;
   }
-  uint8_t* const data = fec_packet->pkt->data.data();
+  uint8_t* const data = fec_packet->pkt->data.MutableData();
   bool r_bit = (data[0] & 0x80) != 0;
   if (r_bit) {
     RTC_LOG(LS_INFO)
@@ -249,7 +249,7 @@
     const uint8_t* packet_mask,
     size_t packet_mask_size,
     ForwardErrorCorrection::Packet* fec_packet) const {
-  uint8_t* data = fec_packet->data.data();
+  uint8_t* data = fec_packet->data.MutableData();
   data[0] &= 0x7f;  // Clear R bit.
   data[0] &= 0xbf;  // Clear F bit.
   ByteWriter<uint8_t>::WriteBigEndian(&data[8], kSsrcCount);
@@ -260,8 +260,7 @@
   //
   // We treat the mask parts as unsigned integers with host order endianness
   // in order to simplify the bit shifting between bytes.
-  uint8_t* const written_packet_mask =
-      fec_packet->data.data() + kPacketMaskOffset;
+  uint8_t* const written_packet_mask = data + kPacketMaskOffset;
   if (packet_mask_size == kUlpfecPacketMaskSizeLBitSet) {
     // The packet mask is 48 bits long.
     uint16_t tmp_mask_part0 =
diff --git a/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc b/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc
index 1d86dd0..4a24e90 100644
--- a/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc
+++ b/modules/rtp_rtcp/source/flexfec_header_reader_writer_unittest.cc
@@ -78,8 +78,9 @@
   FlexfecHeaderWriter writer;
   rtc::scoped_refptr<Packet> written_packet(new Packet());
   written_packet->data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet->data.MutableData();
   for (size_t i = 0; i < written_packet->data.size(); ++i) {
-    written_packet->data[i] = i;  // Actual content doesn't matter.
+    data[i] = i;  // Actual content doesn't matter.
   }
   writer.FinalizeFecHeader(kMediaSsrc, kMediaStartSeqNum, packet_mask,
                            packet_mask_size, written_packet.get());
@@ -328,8 +329,9 @@
   constexpr uint8_t kUlpfecPacketMask[] = {0x11, 0x02};
   Packet written_packet;
   written_packet.data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet.data.MutableData();
   for (size_t i = 0; i < written_packet.data.size(); ++i) {
-    written_packet.data[i] = i;
+    data[i] = i;
   }
 
   FlexfecHeaderWriter writer;
@@ -346,8 +348,9 @@
   constexpr uint8_t kUlpfecPacketMask[] = {0x91, 0x02, 0x08, 0x44, 0x00, 0x84};
   Packet written_packet;
   written_packet.data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet.data.MutableData();
   for (size_t i = 0; i < written_packet.data.size(); ++i) {
-    written_packet.data[i] = i;
+    data[i] = i;
   }
 
   FlexfecHeaderWriter writer;
@@ -368,8 +371,9 @@
   constexpr uint8_t kUlpfecPacketMask[] = {0x22, 0x22, 0x44, 0x44, 0x44, 0x41};
   Packet written_packet;
   written_packet.data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet.data.MutableData();
   for (size_t i = 0; i < written_packet.data.size(); ++i) {
-    written_packet.data[i] = i;
+    data[i] = i;
   }
 
   FlexfecHeaderWriter writer;
diff --git a/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc b/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc
index 199d786..b9391ee 100644
--- a/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc
@@ -165,10 +165,10 @@
   PacketizeFrame(kNumMediaPackets, 0, &media_packets);
   auto& media_packet = media_packets.front();
   // Corrupt the SSRC.
-  media_packet->data[8] = 0;
-  media_packet->data[9] = 1;
-  media_packet->data[10] = 2;
-  media_packet->data[11] = 3;
+  media_packet->data.MutableData()[8] = 0;
+  media_packet->data.MutableData()[9] = 1;
+  media_packet->data.MutableData()[10] = 2;
+  media_packet->data.MutableData()[11] = 3;
 
   EXPECT_FALSE(receiver_.AddReceivedPacket(ParsePacket(*media_packet)));
 }
@@ -183,10 +183,10 @@
   const auto& media_packet = media_packets.front();
   auto fec_packet = packet_generator_.BuildFlexfecPacket(*fec_packets.front());
   // Corrupt the SSRC.
-  fec_packet->data[8] = 4;
-  fec_packet->data[9] = 5;
-  fec_packet->data[10] = 6;
-  fec_packet->data[11] = 7;
+  fec_packet->data.MutableData()[8] = 4;
+  fec_packet->data.MutableData()[9] = 5;
+  fec_packet->data.MutableData()[10] = 6;
+  fec_packet->data.MutableData()[11] = 7;
 
   std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet =
       receiver_.AddReceivedPacket(ParsePacket(*media_packet));
diff --git a/modules/rtp_rtcp/source/forward_error_correction.cc b/modules/rtp_rtcp/source/forward_error_correction.cc
index 1812fbf..56eabc8 100644
--- a/modules/rtp_rtcp/source/forward_error_correction.cc
+++ b/modules/rtp_rtcp/source/forward_error_correction.cc
@@ -151,7 +151,7 @@
   }
   for (int i = 0; i < num_fec_packets; ++i) {
     generated_fec_packets_[i].data.EnsureCapacity(IP_PACKET_SIZE);
-    memset(generated_fec_packets_[i].data.data(), 0, IP_PACKET_SIZE);
+    memset(generated_fec_packets_[i].data.MutableData(), 0, IP_PACKET_SIZE);
     // Use this as a marker for untouched packets.
     generated_fec_packets_[i].data.SetSize(0);
     fec_packets->push_back(&generated_fec_packets_[i]);
@@ -231,7 +231,7 @@
           fec_packet->data.SetSize(fec_packet_length);
         }
         if (first_protected_packet) {
-          uint8_t* data = fec_packet->data.data();
+          uint8_t* data = fec_packet->data.MutableData();
           // Write P, X, CC, M, and PT recovery fields.
           // Note that bits 0, 1, and 16 are overwritten in FinalizeFecHeaders.
           memcpy(&data[0], &media_packet_data[0], 2);
@@ -567,11 +567,11 @@
   // Copy bytes corresponding to minimum RTP header size.
   // Note that the sequence number and SSRC fields will be overwritten
   // at the end of packet recovery.
-  memcpy(recovered_packet->pkt->data.data(), fec_packet.pkt->data.cdata(),
-         kRtpHeaderSize);
+  memcpy(recovered_packet->pkt->data.MutableData(),
+         fec_packet.pkt->data.cdata(), kRtpHeaderSize);
   // Copy remaining FEC payload.
   if (fec_packet.protection_length > 0) {
-    memcpy(recovered_packet->pkt->data.data() + kRtpHeaderSize,
+    memcpy(recovered_packet->pkt->data.MutableData() + kRtpHeaderSize,
            fec_packet.pkt->data.cdata() + fec_packet.fec_header_size,
            fec_packet.protection_length);
   }
@@ -581,7 +581,7 @@
 bool ForwardErrorCorrection::FinishPacketRecovery(
     const ReceivedFecPacket& fec_packet,
     RecoveredPacket* recovered_packet) {
-  uint8_t* data = recovered_packet->pkt->data.data();
+  uint8_t* data = recovered_packet->pkt->data.MutableData();
   // Set the RTP version to 2.
   data[0] |= 0x80;  // Set the 1st bit.
   data[0] &= 0xbf;  // Clear the 2nd bit.
@@ -603,7 +603,7 @@
 }
 
 void ForwardErrorCorrection::XorHeaders(const Packet& src, Packet* dst) {
-  uint8_t* dst_data = dst->data.data();
+  uint8_t* dst_data = dst->data.MutableData();
   const uint8_t* src_data = src.data.cdata();
   // XOR the first 2 bytes of the header: V, P, X, CC, M, PT fields.
   dst_data[0] ^= src_data[0];
@@ -635,7 +635,7 @@
   if (dst_offset + payload_length > dst->data.size()) {
     dst->data.SetSize(dst_offset + payload_length);
   }
-  uint8_t* dst_data = dst->data.data();
+  uint8_t* dst_data = dst->data.MutableData();
   const uint8_t* src_data = src.data.cdata();
   for (size_t i = 0; i < payload_length; ++i) {
     dst_data[dst_offset + i] ^= src_data[kRtpHeaderSize + i];
@@ -731,11 +731,11 @@
   RTC_DCHECK_LE(recovered_packets->size(), max_media_packets);
 }
 
-uint16_t ForwardErrorCorrection::ParseSequenceNumber(uint8_t* packet) {
+uint16_t ForwardErrorCorrection::ParseSequenceNumber(const uint8_t* packet) {
   return (packet[2] << 8) + packet[3];
 }
 
-uint32_t ForwardErrorCorrection::ParseSsrc(uint8_t* packet) {
+uint32_t ForwardErrorCorrection::ParseSsrc(const uint8_t* packet) {
   return (packet[8] << 24) + (packet[9] << 16) + (packet[10] << 8) + packet[11];
 }
 
diff --git a/modules/rtp_rtcp/source/forward_error_correction.h b/modules/rtp_rtcp/source/forward_error_correction.h
index 566ce74..0c54ad9 100644
--- a/modules/rtp_rtcp/source/forward_error_correction.h
+++ b/modules/rtp_rtcp/source/forward_error_correction.h
@@ -235,8 +235,8 @@
 
   // TODO(brandtr): Remove these functions when the Packet classes
   // have been refactored.
-  static uint16_t ParseSequenceNumber(uint8_t* packet);
-  static uint32_t ParseSsrc(uint8_t* packet);
+  static uint16_t ParseSequenceNumber(const uint8_t* packet);
+  static uint32_t ParseSsrc(const uint8_t* packet);
 
  protected:
   ForwardErrorCorrection(std::unique_ptr<FecHeaderReader> fec_header_reader,
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index 1db5eeb..a9ec2a1 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -174,7 +174,7 @@
       // TODO(bugs.webrtc.org/10774): Remove fallback.
       remote_ssrc_(0),
       remote_sender_rtp_time_(0),
-      xr_rrtr_status_(false),
+      xr_rrtr_status_(config.non_sender_rtt_measurement),
       xr_rr_rtt_ms_(0),
       oldest_tmmbr_info_ms_(0),
       stats_callback_(config.rtcp_statistics_callback),
@@ -256,11 +256,6 @@
   return 0;
 }
 
-void RTCPReceiver::SetRtcpXrRrtrStatus(bool enable) {
-  MutexLock lock(&rtcp_receiver_lock_);
-  xr_rrtr_status_ = enable;
-}
-
 bool RTCPReceiver::GetAndResetXrRrRtt(int64_t* rtt_ms) {
   RTC_DCHECK(rtt_ms);
   MutexLock lock(&rtcp_receiver_lock_);
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.h b/modules/rtp_rtcp/source/rtcp_receiver.h
index f97fe61..d735653 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.h
+++ b/modules/rtp_rtcp/source/rtcp_receiver.h
@@ -86,7 +86,6 @@
               int64_t* min_rtt_ms,
               int64_t* max_rtt_ms) const;
 
-  void SetRtcpXrRrtrStatus(bool enable);
   bool GetAndResetXrRrRtt(int64_t* rtt_ms);
 
   // Called once per second on the worker thread to do rtt calculations.
@@ -252,7 +251,7 @@
       received_rrtrs_ssrc_it_ RTC_GUARDED_BY(rtcp_receiver_lock_);
 
   // Estimated rtt, zero when there is no valid estimate.
-  bool xr_rrtr_status_ RTC_GUARDED_BY(rtcp_receiver_lock_);
+  const bool xr_rrtr_status_;
   int64_t xr_rr_rtt_ms_;
 
   int64_t oldest_tmmbr_info_ms_ RTC_GUARDED_BY(rtcp_receiver_lock_);
diff --git a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index 0506aed..1a1d94a 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -838,11 +838,11 @@
 
 TEST(RtcpReceiverTest, ExtendedReportsDlrrPacketNotToUsIgnored) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
-  receiver.SetRemoteSSRC(kSenderSsrc);
-
+  auto config = DefaultConfiguration(&mocks);
   // Allow calculate rtt using dlrr/rrtr, simulating media receiver side.
-  receiver.SetRtcpXrRrtrStatus(true);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
+  receiver.SetRemoteSSRC(kSenderSsrc);
 
   rtcp::ExtendedReports xr;
   xr.SetSenderSsrc(kSenderSsrc);
@@ -856,12 +856,13 @@
 
 TEST(RtcpReceiverTest, InjectExtendedReportsDlrrPacketWithSubBlock) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
   const uint32_t kLastRR = 0x12345;
   const uint32_t kDelay = 0x23456;
-  receiver.SetRtcpXrRrtrStatus(true);
   int64_t rtt_ms = 0;
   EXPECT_FALSE(receiver.GetAndResetXrRrRtt(&rtt_ms));
 
@@ -880,12 +881,13 @@
 
 TEST(RtcpReceiverTest, InjectExtendedReportsDlrrPacketWithMultipleSubBlocks) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
   const uint32_t kLastRR = 0x12345;
   const uint32_t kDelay = 0x56789;
-  receiver.SetRtcpXrRrtrStatus(true);
 
   rtcp::ExtendedReports xr;
   xr.SetSenderSsrc(kSenderSsrc);
@@ -905,11 +907,11 @@
 
 TEST(RtcpReceiverTest, InjectExtendedReportsPacketWithMultipleReportBlocks) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
-  receiver.SetRtcpXrRrtrStatus(true);
-
   rtcp::Rrtr rrtr;
   rtcp::ExtendedReports xr;
   xr.SetSenderSsrc(kSenderSsrc);
@@ -927,11 +929,11 @@
 
 TEST(RtcpReceiverTest, InjectExtendedReportsPacketWithUnknownReportBlock) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
-  receiver.SetRtcpXrRrtrStatus(true);
-
   rtcp::Rrtr rrtr;
   rtcp::ExtendedReports xr;
   xr.SetSenderSsrc(kSenderSsrc);
@@ -955,25 +957,26 @@
 
 TEST(RtcpReceiverTest, TestExtendedReportsRrRttInitiallyFalse) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
-  receiver.SetRtcpXrRrtrStatus(true);
-
   int64_t rtt_ms;
   EXPECT_FALSE(receiver.GetAndResetXrRrRtt(&rtt_ms));
 }
 
 TEST(RtcpReceiverTest, RttCalculatedAfterExtendedReportsDlrr) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
   Random rand(0x0123456789abcdef);
   const int64_t kRttMs = rand.Rand(1, 9 * 3600 * 1000);
   const uint32_t kDelayNtp = rand.Rand(0, 0x7fffffff);
   const int64_t kDelayMs = CompactNtpRttToMs(kDelayNtp);
-  receiver.SetRtcpXrRrtrStatus(true);
   NtpTime now = TimeMicrosToNtp(mocks.clock.TimeInMicroseconds());
   uint32_t sent_ntp = CompactNtp(now);
   mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs);
@@ -991,7 +994,9 @@
 
 TEST(RtcpReceiverTest, XrDlrrCalculatesNegativeRttAsOne) {
   ReceiverMocks mocks;
-  RTCPReceiver receiver(DefaultConfiguration(&mocks), &mocks.rtp_rtcp_impl);
+  auto config = DefaultConfiguration(&mocks);
+  config.non_sender_rtt_measurement = true;
+  RTCPReceiver receiver(config, &mocks.rtp_rtcp_impl);
   receiver.SetRemoteSSRC(kSenderSsrc);
 
   Random rand(0x0123456789abcdef);
@@ -1001,7 +1006,6 @@
   NtpTime now = TimeMicrosToNtp(mocks.clock.TimeInMicroseconds());
   uint32_t sent_ntp = CompactNtp(now);
   mocks.clock.AdvanceTimeMilliseconds(kRttMs + kDelayMs);
-  receiver.SetRtcpXrRrtrStatus(true);
 
   rtcp::ExtendedReports xr;
   xr.SetSenderSsrc(kSenderSsrc);
diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc
index 61e6085..79f5aa6 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -173,7 +173,8 @@
       packet_oh_send_(0),
       max_packet_size_(IP_PACKET_SIZE - 28),  // IPv4 + UDP by default.
 
-      xr_send_receiver_reference_time_enabled_(false),
+      xr_send_receiver_reference_time_enabled_(
+          config.non_sender_rtt_measurement),
       packet_type_counter_observer_(config.rtcp_packet_type_counter_observer),
       send_video_bitrate_allocation_(false),
       last_payload_type_(-1) {
@@ -434,14 +435,7 @@
     now += RTCP_SEND_BEFORE_KEY_FRAME_MS;
   }
 
-  if (now >= next_time_to_send_rtcp_) {
-    return true;
-  } else if (now < 0x0000ffff &&
-             next_time_to_send_rtcp_ > 0xffff0000) {  // 65 sec margin
-    // wrap
-    return true;
-  }
-  return false;
+  return now >= next_time_to_send_rtcp_;
 }
 
 std::unique_ptr<rtcp::RtcpPacket> RTCPSender::BuildSR(const RtcpContext& ctx) {
@@ -896,16 +890,6 @@
   csrcs_ = csrcs;
 }
 
-void RTCPSender::SendRtcpXrReceiverReferenceTime(bool enable) {
-  MutexLock lock(&mutex_rtcp_sender_);
-  xr_send_receiver_reference_time_enabled_ = enable;
-}
-
-bool RTCPSender::RtcpXrReceiverReferenceTime() const {
-  MutexLock lock(&mutex_rtcp_sender_);
-  return xr_send_receiver_reference_time_enabled_;
-}
-
 void RTCPSender::SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set) {
   MutexLock lock(&mutex_rtcp_sender_);
   tmmbn_to_send_ = std::move(bounding_set);
diff --git a/modules/rtp_rtcp/source/rtcp_sender.h b/modules/rtp_rtcp/source/rtcp_sender.h
index 22b2bb7..cc9091d 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.h
+++ b/modules/rtp_rtcp/source/rtcp_sender.h
@@ -20,7 +20,6 @@
 #include "absl/types/optional.h"
 #include "api/call/transport.h"
 #include "api/video/video_bitrate_allocation.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
 #include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
 #include "modules/rtp_rtcp/include/receive_statistics.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@@ -143,12 +142,6 @@
   void SetTmmbn(std::vector<rtcp::TmmbItem> bounding_set)
       RTC_LOCKS_EXCLUDED(mutex_rtcp_sender_);
 
-  void SendRtcpXrReceiverReferenceTime(bool enable)
-      RTC_LOCKS_EXCLUDED(mutex_rtcp_sender_);
-
-  bool RtcpXrReceiverReferenceTime() const
-      RTC_LOCKS_EXCLUDED(mutex_rtcp_sender_);
-
   void SetCsrcs(const std::vector<uint32_t>& csrcs)
       RTC_LOCKS_EXCLUDED(mutex_rtcp_sender_);
 
@@ -268,8 +261,7 @@
   size_t max_packet_size_ RTC_GUARDED_BY(mutex_rtcp_sender_);
 
   // True if sending of XR Receiver reference time report is enabled.
-  bool xr_send_receiver_reference_time_enabled_
-      RTC_GUARDED_BY(mutex_rtcp_sender_);
+  const bool xr_send_receiver_reference_time_enabled_;
 
   RtcpPacketTypeCounterObserver* const packet_type_counter_observer_;
   RtcpPacketTypeCounter packet_type_counter_ RTC_GUARDED_BY(mutex_rtcp_sender_);
diff --git a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
index 4b6d4a3..4c8038f 100644
--- a/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender_unittest.cc
@@ -68,6 +68,21 @@
 static const uint32_t kRemoteSsrc = 0x22222222;
 static const uint32_t kStartRtpTimestamp = 0x34567;
 static const uint32_t kRtpTimestamp = 0x45678;
+
+std::unique_ptr<RTCPSender> CreateRtcpSender(
+    const RtpRtcpInterface::Configuration& config,
+    bool init_timestamps = true) {
+  auto rtcp_sender = std::make_unique<RTCPSender>(config);
+  rtcp_sender->SetRemoteSSRC(kRemoteSsrc);
+  if (init_timestamps) {
+    rtcp_sender->SetTimestampOffset(kStartRtpTimestamp);
+    rtcp_sender->SetLastRtpTime(kRtpTimestamp,
+                                config.clock->TimeInMilliseconds(),
+                                /*payload_type=*/0);
+  }
+  return rtcp_sender;
+}
+
 }  // namespace
 
 class RtcpSenderTest : public ::testing::Test {
@@ -78,11 +93,6 @@
         retransmission_rate_limiter_(&clock_, 1000) {
     RtpRtcpInterface::Configuration configuration = GetDefaultConfig();
     rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl2(configuration));
-    rtcp_sender_.reset(new RTCPSender(configuration));
-    rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
-    rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
-    rtcp_sender_->SetLastRtpTime(kRtpTimestamp, clock_.TimeInMilliseconds(),
-                                 /*payload_type=*/0);
   }
 
   RtpRtcpInterface::Configuration GetDefaultConfig() {
@@ -116,37 +126,40 @@
   TestTransport test_transport_;
   std::unique_ptr<ReceiveStatistics> receive_statistics_;
   std::unique_ptr<ModuleRtpRtcpImpl2> rtp_rtcp_impl_;
-  std::unique_ptr<RTCPSender> rtcp_sender_;
   RateLimiter retransmission_rate_limiter_;
 };
 
 TEST_F(RtcpSenderTest, SetRtcpStatus) {
-  EXPECT_EQ(RtcpMode::kOff, rtcp_sender_->Status());
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(RtcpMode::kReducedSize, rtcp_sender_->Status());
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  EXPECT_EQ(RtcpMode::kOff, rtcp_sender->Status());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(RtcpMode::kReducedSize, rtcp_sender->Status());
 }
 
 TEST_F(RtcpSenderTest, SetSendingStatus) {
-  EXPECT_FALSE(rtcp_sender_->Sending());
-  EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), true));
-  EXPECT_TRUE(rtcp_sender_->Sending());
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  EXPECT_FALSE(rtcp_sender->Sending());
+  EXPECT_EQ(0, rtcp_sender->SetSendingStatus(feedback_state(), true));
+  EXPECT_TRUE(rtcp_sender->Sending());
 }
 
 TEST_F(RtcpSenderTest, NoPacketSentIfOff) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kOff);
-  EXPECT_EQ(-1, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kOff);
+  EXPECT_EQ(-1, rtcp_sender->SendRTCP(feedback_state(), kRtcpSr));
 }
 
 TEST_F(RtcpSenderTest, SendSr) {
   const uint32_t kPacketCount = 0x12345;
   const uint32_t kOctetCount = 0x23456;
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
   RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
-  rtcp_sender_->SetSendingStatus(feedback_state, true);
+  rtcp_sender->SetSendingStatus(feedback_state, true);
   feedback_state.packets_sent = kPacketCount;
   feedback_state.media_bytes_sent = kOctetCount;
   NtpTime ntp = TimeMicrosToNtp(clock_.TimeInMicroseconds());
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpSr));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state, kRtcpSr));
   EXPECT_EQ(1, parser()->sender_report()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->sender_report()->sender_ssrc());
   EXPECT_EQ(ntp, parser()->sender_report()->ntp());
@@ -162,15 +175,16 @@
   const uint32_t kOctetCount = 0x23456;
   const int kTimeBetweenSRsUs = 10043;  // Not exact value in milliseconds.
   const int kExtraPackets = 30;
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
   // Make sure clock is not exactly at some milliseconds point.
   clock_.AdvanceTimeMicroseconds(kTimeBetweenSRsUs);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
   RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
-  rtcp_sender_->SetSendingStatus(feedback_state, true);
+  rtcp_sender->SetSendingStatus(feedback_state, true);
   feedback_state.packets_sent = kPacketCount;
   feedback_state.media_bytes_sent = kOctetCount;
 
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpSr));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state, kRtcpSr));
   EXPECT_EQ(1, parser()->sender_report()->num_packets());
   NtpTime ntp1 = parser()->sender_report()->ntp();
   uint32_t rtp1 = parser()->sender_report()->rtp_timestamp();
@@ -178,7 +192,7 @@
   // Send more SRs to ensure slope is always exact for different offsets
   for (int packets = 1; packets <= kExtraPackets; ++packets) {
     clock_.AdvanceTimeMicroseconds(kTimeBetweenSRsUs);
-    EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpSr));
+    EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state, kRtcpSr));
     EXPECT_EQ(packets + 1, parser()->sender_report()->num_packets());
 
     NtpTime ntp2 = parser()->sender_report()->ntp();
@@ -197,18 +211,17 @@
   config.outgoing_transport = &test_transport_;
   config.rtcp_report_interval_ms = 1000;
   config.local_media_ssrc = kSenderSsrc;
-  rtcp_sender_.reset(new RTCPSender(config));
-  rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  rtcp_sender_->SetSendingStatus(feedback_state(), true);
+  auto rtcp_sender = CreateRtcpSender(config, /*init_timestamps=*/false);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  rtcp_sender->SetSendingStatus(feedback_state(), true);
 
   // Sender Report shouldn't be send as an SR nor as a Report.
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpSr);
   EXPECT_EQ(0, parser()->sender_report()->num_packets());
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpReport);
   EXPECT_EQ(0, parser()->sender_report()->num_packets());
   // Other packets (e.g. Pli) are allowed, even if useless.
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpPli));
   EXPECT_EQ(1, parser()->pli()->num_packets());
 }
 
@@ -219,20 +232,20 @@
   config.outgoing_transport = &test_transport_;
   config.rtcp_report_interval_ms = 1000;
   config.local_media_ssrc = kSenderSsrc;
-  rtcp_sender_.reset(new RTCPSender(config));
-  rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  rtcp_sender_->SetSendingStatus(feedback_state(), true);
+  auto rtcp_sender = CreateRtcpSender(config, /*init_timestamps=*/false);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  rtcp_sender->SetSendingStatus(feedback_state(), true);
 
   // In compound mode no packets are allowed (e.g. Pli) because compound mode
   // should start with Sender Report.
-  EXPECT_EQ(-1, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
+  EXPECT_EQ(-1, rtcp_sender->SendRTCP(feedback_state(), kRtcpPli));
   EXPECT_EQ(0, parser()->pli()->num_packets());
 }
 
 TEST_F(RtcpSenderTest, SendRr) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpRr));
   EXPECT_EQ(1, parser()->receiver_report()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->receiver_report()->sender_ssrc());
   EXPECT_EQ(0U, parser()->receiver_report()->report_blocks().size());
@@ -240,9 +253,10 @@
 
 TEST_F(RtcpSenderTest, SendRrWithOneReportBlock) {
   const uint16_t kSeqNum = 11111;
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
   InsertIncomingPacket(kRemoteSsrc, kSeqNum);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr));
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpRr));
   EXPECT_EQ(1, parser()->receiver_report()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->receiver_report()->sender_ssrc());
   ASSERT_EQ(1U, parser()->receiver_report()->report_blocks().size());
@@ -255,10 +269,11 @@
 
 TEST_F(RtcpSenderTest, SendRrWithTwoReportBlocks) {
   const uint16_t kSeqNum = 11111;
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
   InsertIncomingPacket(kRemoteSsrc, kSeqNum);
   InsertIncomingPacket(kRemoteSsrc + 1, kSeqNum + 1);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr));
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpRr));
   EXPECT_EQ(1, parser()->receiver_report()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->receiver_report()->sender_ssrc());
   EXPECT_EQ(2U, parser()->receiver_report()->report_blocks().size());
@@ -269,9 +284,10 @@
 }
 
 TEST_F(RtcpSenderTest, SendSdes) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SetCNAME("alice@host"));
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSdes));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SetCNAME("alice@host"));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpSdes));
   EXPECT_EQ(1, parser()->sdes()->num_packets());
   EXPECT_EQ(1U, parser()->sdes()->chunks().size());
   EXPECT_EQ(kSenderSsrc, parser()->sdes()->chunks()[0].ssrc);
@@ -279,68 +295,75 @@
 }
 
 TEST_F(RtcpSenderTest, SendSdesWithMaxChunks) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SetCNAME("alice@host"));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SetCNAME("alice@host"));
   const char cname[] = "smith@host";
   for (size_t i = 0; i < 30; ++i) {
     const uint32_t csrc = 0x1234 + i;
-    EXPECT_EQ(0, rtcp_sender_->AddMixedCNAME(csrc, cname));
+    EXPECT_EQ(0, rtcp_sender->AddMixedCNAME(csrc, cname));
   }
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSdes));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpSdes));
   EXPECT_EQ(1, parser()->sdes()->num_packets());
   EXPECT_EQ(31U, parser()->sdes()->chunks().size());
 }
 
 TEST_F(RtcpSenderTest, SdesIncludedInCompoundPacket) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SetCNAME("alice@host"));
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SetCNAME("alice@host"));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(1, parser()->receiver_report()->num_packets());
   EXPECT_EQ(1, parser()->sdes()->num_packets());
   EXPECT_EQ(1U, parser()->sdes()->chunks().size());
 }
 
 TEST_F(RtcpSenderTest, SendBye) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpBye));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpBye));
   EXPECT_EQ(1, parser()->bye()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->bye()->sender_ssrc());
 }
 
 TEST_F(RtcpSenderTest, StopSendingTriggersBye) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), true));
-  EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), false));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SetSendingStatus(feedback_state(), true));
+  EXPECT_EQ(0, rtcp_sender->SetSendingStatus(feedback_state(), false));
   EXPECT_EQ(1, parser()->bye()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->bye()->sender_ssrc());
 }
 
 TEST_F(RtcpSenderTest, SendFir) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpFir));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpFir));
   EXPECT_EQ(1, parser()->fir()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->fir()->sender_ssrc());
   EXPECT_EQ(1U, parser()->fir()->requests().size());
   EXPECT_EQ(kRemoteSsrc, parser()->fir()->requests()[0].ssrc);
   uint8_t seq = parser()->fir()->requests()[0].seq_nr;
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpFir));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpFir));
   EXPECT_EQ(2, parser()->fir()->num_packets());
   EXPECT_EQ(seq + 1, parser()->fir()->requests()[0].seq_nr);
 }
 
 TEST_F(RtcpSenderTest, SendPli) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpPli));
   EXPECT_EQ(1, parser()->pli()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->pli()->sender_ssrc());
   EXPECT_EQ(kRemoteSsrc, parser()->pli()->media_ssrc());
 }
 
 TEST_F(RtcpSenderTest, SendNack) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
   const uint16_t kList[] = {0, 1, 16};
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpNack,
-                                      ABSL_ARRAYSIZE(kList), kList));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpNack,
+                                     ABSL_ARRAYSIZE(kList), kList));
   EXPECT_EQ(1, parser()->nack()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->nack()->sender_ssrc());
   EXPECT_EQ(kRemoteSsrc, parser()->nack()->media_ssrc());
@@ -348,14 +371,15 @@
 }
 
 TEST_F(RtcpSenderTest, SendLossNotificationBufferingNotAllowed) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
   constexpr uint16_t kLastDecoded = 0x1234;
   constexpr uint16_t kLastReceived = 0x4321;
   constexpr bool kDecodabilityFlag = true;
   constexpr bool kBufferingAllowed = false;
-  EXPECT_EQ(rtcp_sender_->SendLossNotification(feedback_state(), kLastDecoded,
-                                               kLastReceived, kDecodabilityFlag,
-                                               kBufferingAllowed),
+  EXPECT_EQ(rtcp_sender->SendLossNotification(feedback_state(), kLastDecoded,
+                                              kLastReceived, kDecodabilityFlag,
+                                              kBufferingAllowed),
             0);
   EXPECT_EQ(parser()->processed_rtcp_packets(), 1u);
   EXPECT_EQ(parser()->loss_notification()->num_packets(), 1);
@@ -364,14 +388,15 @@
 }
 
 TEST_F(RtcpSenderTest, SendLossNotificationBufferingAllowed) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
   constexpr uint16_t kLastDecoded = 0x1234;
   constexpr uint16_t kLastReceived = 0x4321;
   constexpr bool kDecodabilityFlag = true;
   constexpr bool kBufferingAllowed = true;
-  EXPECT_EQ(rtcp_sender_->SendLossNotification(feedback_state(), kLastDecoded,
-                                               kLastReceived, kDecodabilityFlag,
-                                               kBufferingAllowed),
+  EXPECT_EQ(rtcp_sender->SendLossNotification(feedback_state(), kLastDecoded,
+                                              kLastReceived, kDecodabilityFlag,
+                                              kBufferingAllowed),
             0);
 
   // No RTCP messages sent yet.
@@ -379,8 +404,8 @@
 
   // Sending another messages triggers sending the LNTF messages as well.
   const uint16_t kList[] = {0, 1, 16};
-  EXPECT_EQ(rtcp_sender_->SendRTCP(feedback_state(), kRtcpNack,
-                                   ABSL_ARRAYSIZE(kList), kList),
+  EXPECT_EQ(rtcp_sender->SendRTCP(feedback_state(), kRtcpNack,
+                                  ABSL_ARRAYSIZE(kList), kList),
             0);
 
   // Exactly one packet was produced, and it contained both the buffered LNTF
@@ -395,9 +420,10 @@
 }
 
 TEST_F(RtcpSenderTest, RembNotIncludedBeforeSet) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
 
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpRr);
 
   ASSERT_EQ(1, parser()->receiver_report()->num_packets());
   EXPECT_EQ(0, parser()->remb()->num_packets());
@@ -406,15 +432,16 @@
 TEST_F(RtcpSenderTest, RembNotIncludedAfterUnset) {
   const int64_t kBitrate = 261011;
   const std::vector<uint32_t> kSsrcs = {kRemoteSsrc, kRemoteSsrc + 1};
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  rtcp_sender_->SetRemb(kBitrate, kSsrcs);
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  rtcp_sender->SetRemb(kBitrate, kSsrcs);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpRr);
   ASSERT_EQ(1, parser()->receiver_report()->num_packets());
   EXPECT_EQ(1, parser()->remb()->num_packets());
 
   // Turn off REMB. rtcp_sender no longer should send it.
-  rtcp_sender_->UnsetRemb();
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpRr);
+  rtcp_sender->UnsetRemb();
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpRr);
   ASSERT_EQ(2, parser()->receiver_report()->num_packets());
   EXPECT_EQ(1, parser()->remb()->num_packets());
 }
@@ -422,10 +449,11 @@
 TEST_F(RtcpSenderTest, SendRemb) {
   const int64_t kBitrate = 261011;
   const std::vector<uint32_t> kSsrcs = {kRemoteSsrc, kRemoteSsrc + 1};
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  rtcp_sender_->SetRemb(kBitrate, kSsrcs);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  rtcp_sender->SetRemb(kBitrate, kSsrcs);
 
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpRemb);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpRemb);
 
   EXPECT_EQ(1, parser()->remb()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->remb()->sender_ssrc());
@@ -437,25 +465,27 @@
 TEST_F(RtcpSenderTest, RembIncludedInEachCompoundPacketAfterSet) {
   const int kBitrate = 261011;
   const std::vector<uint32_t> kSsrcs = {kRemoteSsrc, kRemoteSsrc + 1};
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  rtcp_sender_->SetRemb(kBitrate, kSsrcs);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  rtcp_sender->SetRemb(kBitrate, kSsrcs);
 
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpReport);
   EXPECT_EQ(1, parser()->remb()->num_packets());
   // REMB should be included in each compound packet.
-  rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport);
+  rtcp_sender->SendRTCP(feedback_state(), kRtcpReport);
   EXPECT_EQ(2, parser()->remb()->num_packets());
 }
 
 TEST_F(RtcpSenderTest, SendXrWithDlrr) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
   RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
   rtcp::ReceiveTimeInfo last_xr_rr;
   last_xr_rr.ssrc = 0x11111111;
   last_xr_rr.last_rr = 0x22222222;
   last_xr_rr.delay_since_last_rr = 0x33333333;
   feedback_state.last_xr_rtis.push_back(last_xr_rr);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpReport));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state, kRtcpReport));
   EXPECT_EQ(1, parser()->xr()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->xr()->sender_ssrc());
   ASSERT_THAT(parser()->xr()->dlrr().sub_blocks(), SizeIs(1));
@@ -467,7 +497,8 @@
 
 TEST_F(RtcpSenderTest, SendXrWithMultipleDlrrSubBlocks) {
   const size_t kNumReceivers = 2;
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
   RTCPSender::FeedbackState feedback_state = rtp_rtcp_impl_->GetFeedbackState();
   for (size_t i = 0; i < kNumReceivers; ++i) {
     rtcp::ReceiveTimeInfo last_xr_rr;
@@ -477,7 +508,7 @@
     feedback_state.last_xr_rtis.push_back(last_xr_rr);
   }
 
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state, kRtcpReport));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state, kRtcpReport));
   EXPECT_EQ(1, parser()->xr()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->xr()->sender_ssrc());
   ASSERT_THAT(parser()->xr()->dlrr().sub_blocks(), SizeIs(kNumReceivers));
@@ -492,11 +523,13 @@
 }
 
 TEST_F(RtcpSenderTest, SendXrWithRrtr) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), false));
-  rtcp_sender_->SendRtcpXrReceiverReferenceTime(true);
+  RtpRtcpInterface::Configuration config = GetDefaultConfig();
+  config.non_sender_rtt_measurement = true;
+  auto rtcp_sender = CreateRtcpSender(config);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SetSendingStatus(feedback_state(), false));
   NtpTime ntp = TimeMicrosToNtp(clock_.TimeInMicroseconds());
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(1, parser()->xr()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->xr()->sender_ssrc());
   EXPECT_FALSE(parser()->xr()->dlrr());
@@ -505,18 +538,22 @@
 }
 
 TEST_F(RtcpSenderTest, TestNoXrRrtrSentIfSending) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), true));
-  rtcp_sender_->SendRtcpXrReceiverReferenceTime(true);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  RtpRtcpInterface::Configuration config = GetDefaultConfig();
+  config.non_sender_rtt_measurement = true;
+  auto rtcp_sender = CreateRtcpSender(config);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SetSendingStatus(feedback_state(), true));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(0, parser()->xr()->num_packets());
 }
 
 TEST_F(RtcpSenderTest, TestNoXrRrtrSentIfNotEnabled) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SetSendingStatus(feedback_state(), false));
-  rtcp_sender_->SendRtcpXrReceiverReferenceTime(false);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  RtpRtcpInterface::Configuration config = GetDefaultConfig();
+  config.non_sender_rtt_measurement = false;
+  auto rtcp_sender = CreateRtcpSender(config);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SetSendingStatus(feedback_state(), false));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(0, parser()->xr()->num_packets());
 }
 
@@ -528,11 +565,9 @@
   config.outgoing_transport = &test_transport_;
   config.rtcp_packet_type_counter_observer = &observer;
   config.rtcp_report_interval_ms = 1000;
-  rtcp_sender_.reset(new RTCPSender(config));
-
-  rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
+  auto rtcp_sender = CreateRtcpSender(config);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpPli));
   EXPECT_EQ(1, parser()->pli()->num_packets());
   EXPECT_EQ(kRemoteSsrc, observer.ssrc_);
   EXPECT_EQ(1U, observer.counter_.pli_packets);
@@ -542,9 +577,10 @@
 
 TEST_F(RtcpSenderTest, SendTmmbr) {
   const unsigned int kBitrateBps = 312000;
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  rtcp_sender_->SetTargetBitrate(kBitrateBps);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpTmmbr));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  rtcp_sender->SetTargetBitrate(kBitrateBps);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpTmmbr));
   EXPECT_EQ(1, parser()->tmmbr()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->tmmbr()->sender_ssrc());
   EXPECT_EQ(1U, parser()->tmmbr()->requests().size());
@@ -554,34 +590,36 @@
 
 TEST_F(RtcpSenderTest, TmmbrIncludedInCompoundPacketIfEnabled) {
   const unsigned int kBitrateBps = 312000;
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_FALSE(rtcp_sender_->TMMBR());
-  rtcp_sender_->SetTMMBRStatus(true);
-  EXPECT_TRUE(rtcp_sender_->TMMBR());
-  rtcp_sender_->SetTargetBitrate(kBitrateBps);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_FALSE(rtcp_sender->TMMBR());
+  rtcp_sender->SetTMMBRStatus(true);
+  EXPECT_TRUE(rtcp_sender->TMMBR());
+  rtcp_sender->SetTargetBitrate(kBitrateBps);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(1, parser()->tmmbr()->num_packets());
   EXPECT_EQ(1U, parser()->tmmbr()->requests().size());
   // TMMBR should be included in each compound packet.
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(2, parser()->tmmbr()->num_packets());
 
-  rtcp_sender_->SetTMMBRStatus(false);
-  EXPECT_FALSE(rtcp_sender_->TMMBR());
+  rtcp_sender->SetTMMBRStatus(false);
+  EXPECT_FALSE(rtcp_sender->TMMBR());
 }
 
 TEST_F(RtcpSenderTest, SendTmmbn) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  rtcp_sender_->SetSendingStatus(feedback_state(), true);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  rtcp_sender->SetSendingStatus(feedback_state(), true);
   std::vector<rtcp::TmmbItem> bounding_set;
   const uint32_t kBitrateBps = 32768000;
   const uint32_t kPacketOh = 40;
   const uint32_t kSourceSsrc = 12345;
   const rtcp::TmmbItem tmmbn(kSourceSsrc, kBitrateBps, kPacketOh);
   bounding_set.push_back(tmmbn);
-  rtcp_sender_->SetTmmbn(bounding_set);
+  rtcp_sender->SetTmmbn(bounding_set);
 
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpSr));
   EXPECT_EQ(1, parser()->sender_report()->num_packets());
   EXPECT_EQ(1, parser()->tmmbn()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->tmmbn()->sender_ssrc());
@@ -598,11 +636,12 @@
 // See http://code.google.com/p/webrtc/issues/detail?id=468 for one
 // situation where this caused confusion.
 TEST_F(RtcpSenderTest, SendsTmmbnIfSetAndEmpty) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  rtcp_sender_->SetSendingStatus(feedback_state(), true);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  rtcp_sender->SetSendingStatus(feedback_state(), true);
   std::vector<rtcp::TmmbItem> bounding_set;
-  rtcp_sender_->SetTmmbn(bounding_set);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpSr));
+  rtcp_sender->SetTmmbn(bounding_set);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpSr));
   EXPECT_EQ(1, parser()->sender_report()->num_packets());
   EXPECT_EQ(1, parser()->tmmbn()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->tmmbn()->sender_ssrc());
@@ -611,20 +650,21 @@
 
 TEST_F(RtcpSenderTest, SendCompoundPliRemb) {
   const int kBitrate = 261011;
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
   std::vector<uint32_t> ssrcs;
   ssrcs.push_back(kRemoteSsrc);
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  rtcp_sender_->SetRemb(kBitrate, ssrcs);
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  rtcp_sender->SetRemb(kBitrate, ssrcs);
   std::set<RTCPPacketType> packet_types;
   packet_types.insert(kRtcpRemb);
   packet_types.insert(kRtcpPli);
-  EXPECT_EQ(0, rtcp_sender_->SendCompoundRTCP(feedback_state(), packet_types));
+  EXPECT_EQ(0, rtcp_sender->SendCompoundRTCP(feedback_state(), packet_types));
   EXPECT_EQ(1, parser()->remb()->num_packets());
   EXPECT_EQ(1, parser()->pli()->num_packets());
 }
 
 // This test is written to verify that BYE is always the last packet
-// type in a RTCP compoud packet.  The rtcp_sender_ is recreated with
+// type in a RTCP compoud packet.  The rtcp_sender is recreated with
 // mock_transport, which is used to check for whether BYE at the end
 // of a RTCP compound packet.
 TEST_F(RtcpSenderTest, ByeMustBeLast) {
@@ -649,28 +689,28 @@
         return true;
       }));
 
-  // Re-configure rtcp_sender_ with mock_transport_
+  // Re-configure rtcp_sender with mock_transport_
   RtpRtcpInterface::Configuration config;
   config.clock = &clock_;
   config.receive_statistics = receive_statistics_.get();
   config.outgoing_transport = &mock_transport;
   config.rtcp_report_interval_ms = 1000;
   config.local_media_ssrc = kSenderSsrc;
-  rtcp_sender_.reset(new RTCPSender(config));
+  auto rtcp_sender = CreateRtcpSender(config);
 
-  rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
-  rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
-  rtcp_sender_->SetLastRtpTime(kRtpTimestamp, clock_.TimeInMilliseconds(),
-                               /*payload_type=*/0);
+  rtcp_sender->SetTimestampOffset(kStartRtpTimestamp);
+  rtcp_sender->SetLastRtpTime(kRtpTimestamp, clock_.TimeInMilliseconds(),
+                              /*payload_type=*/0);
 
   // Set up REMB info to be included with BYE.
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  rtcp_sender_->SetRemb(1234, {});
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpBye));
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  rtcp_sender->SetRemb(1234, {});
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpBye));
 }
 
 TEST_F(RtcpSenderTest, SendXrWithTargetBitrate) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
   const size_t kNumSpatialLayers = 2;
   const size_t kNumTemporalLayers = 2;
   VideoBitrateAllocation allocation;
@@ -679,9 +719,9 @@
     for (size_t tl = 0; tl < kNumTemporalLayers; ++tl)
       allocation.SetBitrate(sl, tl, start_bitrate_bps + (tl * 20000));
   }
-  rtcp_sender_->SetVideoBitrateAllocation(allocation);
+  rtcp_sender->SetVideoBitrateAllocation(allocation);
 
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   EXPECT_EQ(1, parser()->xr()->num_packets());
   EXPECT_EQ(kSenderSsrc, parser()->xr()->sender_ssrc());
   const absl::optional<rtcp::TargetBitrate>& target_bitrate =
@@ -706,48 +746,50 @@
 
 TEST_F(RtcpSenderTest, SendImmediateXrWithTargetBitrate) {
   // Initialize. Send a first report right away.
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   clock_.AdvanceTimeMilliseconds(5);
 
   // Video bitrate allocation generated, save until next time we send a report.
   VideoBitrateAllocation allocation;
   allocation.SetBitrate(0, 0, 100000);
-  rtcp_sender_->SetVideoBitrateAllocation(allocation);
+  rtcp_sender->SetVideoBitrateAllocation(allocation);
   // First seen instance will be sent immediately.
-  EXPECT_TRUE(rtcp_sender_->TimeToSendRTCPReport(false));
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  EXPECT_TRUE(rtcp_sender->TimeToSendRTCPReport(false));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   clock_.AdvanceTimeMilliseconds(5);
 
   // Update bitrate of existing layer, does not quality for immediate sending.
   allocation.SetBitrate(0, 0, 150000);
-  rtcp_sender_->SetVideoBitrateAllocation(allocation);
-  EXPECT_FALSE(rtcp_sender_->TimeToSendRTCPReport(false));
+  rtcp_sender->SetVideoBitrateAllocation(allocation);
+  EXPECT_FALSE(rtcp_sender->TimeToSendRTCPReport(false));
 
   // A new spatial layer enabled, signal this as soon as possible.
   allocation.SetBitrate(1, 0, 200000);
-  rtcp_sender_->SetVideoBitrateAllocation(allocation);
-  EXPECT_TRUE(rtcp_sender_->TimeToSendRTCPReport(false));
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  rtcp_sender->SetVideoBitrateAllocation(allocation);
+  EXPECT_TRUE(rtcp_sender->TimeToSendRTCPReport(false));
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   clock_.AdvanceTimeMilliseconds(5);
 
   // Explicitly disable top layer. The same set of layers now has a bitrate
   // defined, but the explicit 0 indicates shutdown. Signal immediately.
   allocation.SetBitrate(1, 0, 0);
-  EXPECT_FALSE(rtcp_sender_->TimeToSendRTCPReport(false));
-  rtcp_sender_->SetVideoBitrateAllocation(allocation);
-  EXPECT_TRUE(rtcp_sender_->TimeToSendRTCPReport(false));
+  EXPECT_FALSE(rtcp_sender->TimeToSendRTCPReport(false));
+  rtcp_sender->SetVideoBitrateAllocation(allocation);
+  EXPECT_TRUE(rtcp_sender->TimeToSendRTCPReport(false));
 }
 
 TEST_F(RtcpSenderTest, SendTargetBitrateExplicitZeroOnStreamRemoval) {
   // Set up and send a bitrate allocation with two layers.
 
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kCompound);
   VideoBitrateAllocation allocation;
   allocation.SetBitrate(0, 0, 100000);
   allocation.SetBitrate(1, 0, 200000);
-  rtcp_sender_->SetVideoBitrateAllocation(allocation);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  rtcp_sender->SetVideoBitrateAllocation(allocation);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   absl::optional<rtcp::TargetBitrate> target_bitrate =
       parser()->xr()->target_bitrate();
   ASSERT_TRUE(target_bitrate);
@@ -762,8 +804,8 @@
   // Create a new allocation, where the second stream is no longer available.
   VideoBitrateAllocation new_allocation;
   new_allocation.SetBitrate(0, 0, 150000);
-  rtcp_sender_->SetVideoBitrateAllocation(new_allocation);
-  EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpReport));
+  rtcp_sender->SetVideoBitrateAllocation(new_allocation);
+  EXPECT_EQ(0, rtcp_sender->SendRTCP(feedback_state(), kRtcpReport));
   target_bitrate = parser()->xr()->target_bitrate();
   ASSERT_TRUE(target_bitrate);
   bitrates = target_bitrate->GetTargetBitrates();
@@ -777,15 +819,17 @@
 }
 
 TEST_F(RtcpSenderTest, DoesntSchedulesInitialReportWhenSsrcSetOnConstruction) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
-  rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
+  rtcp_sender->SetRemoteSSRC(kRemoteSsrc);
   // New report should not have been scheduled yet.
   clock_.AdvanceTimeMilliseconds(100);
-  EXPECT_FALSE(rtcp_sender_->TimeToSendRTCPReport(false));
+  EXPECT_FALSE(rtcp_sender->TimeToSendRTCPReport(false));
 }
 
 TEST_F(RtcpSenderTest, SendsCombinedRtcpPacket) {
-  rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
+  auto rtcp_sender = CreateRtcpSender(GetDefaultConfig());
+  rtcp_sender->SetRTCPStatus(RtcpMode::kReducedSize);
 
   std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets;
   auto transport_feedback = std::make_unique<rtcp::TransportFeedback>();
@@ -793,7 +837,7 @@
   packets.push_back(std::move(transport_feedback));
   auto remote_estimate = std::make_unique<rtcp::RemoteEstimate>();
   packets.push_back(std::move(remote_estimate));
-  rtcp_sender_->SendCombinedRtcpPacket(std::move(packets));
+  rtcp_sender->SendCombinedRtcpPacket(std::move(packets));
 
   EXPECT_EQ(parser()->transport_feedback()->num_packets(), 1);
   EXPECT_EQ(parser()->transport_feedback()->sender_ssrc(), kSenderSsrc);
diff --git a/modules/rtp_rtcp/source/rtp_fec_unittest.cc b/modules/rtp_rtcp/source/rtp_fec_unittest.cc
index eb559f2..a90e61a 100644
--- a/modules/rtp_rtcp/source/rtp_fec_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_fec_unittest.cc
@@ -127,7 +127,7 @@
         // For media packets, the sequence number is obtained from the
         // RTP header as written by MediaPacketGenerator::ConstructMediaPackets.
         received_packet->seq_num =
-            ByteReader<uint16_t>::ReadBigEndian(&packet->data[2]);
+            ByteReader<uint16_t>::ReadBigEndian(packet->data.data() + 2);
       } else {
         received_packet->ssrc = ForwardErrorCorrectionType::kFecSsrc;
         // For FEC packets, we simulate the sequence numbers differently
@@ -222,10 +222,10 @@
       this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
 
   // Create |kMaxMediaPackets - 1| sequence number difference.
-  ByteWriter<uint16_t>::WriteBigEndian(&this->media_packets_.front()->data[2],
-                                       1);
-  ByteWriter<uint16_t>::WriteBigEndian(&this->media_packets_.back()->data[2],
-                                       kMaxMediaPackets);
+  ByteWriter<uint16_t>::WriteBigEndian(
+      this->media_packets_.front()->data.MutableData() + 2, 1);
+  ByteWriter<uint16_t>::WriteBigEndian(
+      this->media_packets_.back()->data.MutableData() + 2, kMaxMediaPackets);
 
   EXPECT_EQ(
       0, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
@@ -245,10 +245,11 @@
       this->media_packet_generator_.ConstructMediaPackets(kNumMediaPackets);
 
   // Create |kMaxMediaPackets| sequence number difference.
-  ByteWriter<uint16_t>::WriteBigEndian(&this->media_packets_.front()->data[2],
-                                       1);
-  ByteWriter<uint16_t>::WriteBigEndian(&this->media_packets_.back()->data[2],
-                                       kMaxMediaPackets + 1);
+  ByteWriter<uint16_t>::WriteBigEndian(
+      this->media_packets_.front()->data.MutableData() + 2, 1);
+  ByteWriter<uint16_t>::WriteBigEndian(
+      this->media_packets_.back()->data.MutableData() + 2,
+      kMaxMediaPackets + 1);
 
   EXPECT_EQ(
       -1, this->fec_.EncodeFec(this->media_packets_, kProtectionFactor,
@@ -526,9 +527,9 @@
   // Overwrite the sequence numbers generated by ConstructMediaPackets,
   // to make sure that we do have a wrap.
   auto it = this->generated_fec_packets_.begin();
-  ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data[2], 65535);
+  ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data.MutableData()[2], 65535);
   ++it;
-  ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data[2], 0);
+  ByteWriter<uint16_t>::WriteBigEndian(&(*it)->data.MutableData()[2], 0);
 
   // Lose the last two media packets (seq# 65533, 65534).
   memset(this->media_loss_mask_, 0, sizeof(this->media_loss_mask_));
diff --git a/modules/rtp_rtcp/source/rtp_format.cc b/modules/rtp_rtcp/source/rtp_format.cc
index 7703a6b..7550b70 100644
--- a/modules/rtp_rtcp/source/rtp_format.cc
+++ b/modules/rtp_rtcp/source/rtp_format.cc
@@ -54,8 +54,9 @@
       return std::make_unique<RtpPacketizerVp9>(payload, limits, vp9);
     }
     case kVideoCodecAV1:
-      return std::make_unique<RtpPacketizerAv1>(payload, limits,
-                                                rtp_video_header.frame_type);
+      return std::make_unique<RtpPacketizerAv1>(
+          payload, limits, rtp_video_header.frame_type,
+          rtp_video_header.is_last_frame_in_picture);
     default: {
       return std::make_unique<RtpPacketizerGeneric>(payload, limits,
                                                     rtp_video_header);
diff --git a/modules/rtp_rtcp/source/rtp_format_h264.cc b/modules/rtp_rtcp/source/rtp_format_h264.cc
index 6c3966c..86f4858 100644
--- a/modules/rtp_rtcp/source/rtp_format_h264.cc
+++ b/modules/rtp_rtcp/source/rtp_format_h264.cc
@@ -177,7 +177,7 @@
       return fragment_size;
     }
     if (fragment_index == input_fragments_.size() - 1) {
-      // Last fragment, so StrapA might be the last packet.
+      // Last fragment, so STAP-A might be the last packet.
       return fragment_size + limits_.last_packet_reduction_len;
     }
     return fragment_size;
diff --git a/modules/rtp_rtcp/source/rtp_packet.h b/modules/rtp_rtcp/source/rtp_packet.h
index b3e67be..aa854f3 100644
--- a/modules/rtp_rtcp/source/rtp_packet.h
+++ b/modules/rtp_rtcp/source/rtp_packet.h
@@ -30,6 +30,8 @@
   // packet creating and used if available in Parse function.
   // Adding and getting extensions will fail until |extensions| is
   // provided via constructor or IdentifyExtensions function.
+  // |*extensions| is only accessed during construction; the pointer is not
+  // stored.
   RtpPacket();
   explicit RtpPacket(const ExtensionManager* extensions);
   RtpPacket(const RtpPacket&);
@@ -178,8 +180,10 @@
 
   uint16_t SetExtensionLengthMaybeAddZeroPadding(size_t extensions_offset);
 
-  uint8_t* WriteAt(size_t offset) { return buffer_.data() + offset; }
-  void WriteAt(size_t offset, uint8_t byte) { buffer_.data()[offset] = byte; }
+  uint8_t* WriteAt(size_t offset) { return buffer_.MutableData() + offset; }
+  void WriteAt(size_t offset, uint8_t byte) {
+    buffer_.MutableData()[offset] = byte;
+  }
   const uint8_t* ReadAt(size_t offset) const { return buffer_.data() + offset; }
 
   // Header.
diff --git a/modules/rtp_rtcp/source/rtp_packet_received.h b/modules/rtp_rtcp/source/rtp_packet_received.h
index f5d3176..6727b67 100644
--- a/modules/rtp_rtcp/source/rtp_packet_received.h
+++ b/modules/rtp_rtcp/source/rtp_packet_received.h
@@ -17,7 +17,6 @@
 #include "api/array_view.h"
 #include "api/rtp_headers.h"
 #include "modules/rtp_rtcp/source/rtp_packet.h"
-#include "system_wrappers/include/ntp_time.h"
 
 namespace webrtc {
 // Class to hold rtp packet with metadata for receiver side.
@@ -42,10 +41,6 @@
   int64_t arrival_time_ms() const { return arrival_time_ms_; }
   void set_arrival_time_ms(int64_t time) { arrival_time_ms_ = time; }
 
-  // Estimated from Timestamp() using rtcp Sender Reports.
-  NtpTime capture_ntp_time() const { return capture_time_; }
-  void set_capture_ntp_time(NtpTime time) { capture_time_ = time; }
-
   // Flag if packet was recovered via RTX or FEC.
   bool recovered() const { return recovered_; }
   void set_recovered(bool value) { recovered_ = value; }
@@ -65,7 +60,6 @@
   }
 
  private:
-  NtpTime capture_time_;
   int64_t arrival_time_ms_ = 0;
   int payload_type_frequency_ = 0;
   bool recovered_ = false;
diff --git a/modules/rtp_rtcp/source/rtp_packetizer_av1.cc b/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
index 909b128..4408bee 100644
--- a/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
+++ b/modules/rtp_rtcp/source/rtp_packetizer_av1.cc
@@ -88,10 +88,12 @@
 
 RtpPacketizerAv1::RtpPacketizerAv1(rtc::ArrayView<const uint8_t> payload,
                                    RtpPacketizer::PayloadSizeLimits limits,
-                                   VideoFrameType frame_type)
+                                   VideoFrameType frame_type,
+                                   bool is_last_frame_in_picture)
     : frame_type_(frame_type),
       obus_(ParseObus(payload)),
-      packets_(Packetize(obus_, limits)) {}
+      packets_(Packetize(obus_, limits)),
+      is_last_frame_in_picture_(is_last_frame_in_picture) {}
 
 std::vector<RtpPacketizerAv1::Obu> RtpPacketizerAv1::ParseObus(
     rtc::ArrayView<const uint8_t> payload) {
@@ -414,11 +416,8 @@
                 kAggregationHeaderSize + next_packet.packet_size);
 
   ++packet_index_;
-  if (packet_index_ == packets_.size()) {
-    // TODO(danilchap): To support spatial scalability pass and use information
-    // if this frame is the last in the temporal unit.
-    packet->SetMarker(true);
-  }
+  bool is_last_packet_in_frame = packet_index_ == packets_.size();
+  packet->SetMarker(is_last_packet_in_frame && is_last_frame_in_picture_);
   return true;
 }
 
diff --git a/modules/rtp_rtcp/source/rtp_packetizer_av1.h b/modules/rtp_rtcp/source/rtp_packetizer_av1.h
index 79fa6e0..520e746 100644
--- a/modules/rtp_rtcp/source/rtp_packetizer_av1.h
+++ b/modules/rtp_rtcp/source/rtp_packetizer_av1.h
@@ -26,7 +26,8 @@
  public:
   RtpPacketizerAv1(rtc::ArrayView<const uint8_t> payload,
                    PayloadSizeLimits limits,
-                   VideoFrameType frame_type);
+                   VideoFrameType frame_type,
+                   bool is_last_frame_in_picture);
   ~RtpPacketizerAv1() override = default;
 
   size_t NumPackets() const override { return packets_.size() - packet_index_; }
@@ -63,6 +64,7 @@
   const VideoFrameType frame_type_;
   const std::vector<Obu> obus_;
   const std::vector<Packet> packets_;
+  const bool is_last_frame_in_picture_;
   size_t packet_index_ = 0;
 };
 
diff --git a/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc b/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc
index 0529e98..84d2b35 100644
--- a/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_packetizer_av1_unittest.cc
@@ -88,9 +88,11 @@
 std::vector<RtpPayload> Packetize(
     rtc::ArrayView<const uint8_t> payload,
     RtpPacketizer::PayloadSizeLimits limits,
-    VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta) {
+    VideoFrameType frame_type = VideoFrameType::kVideoFrameDelta,
+    bool is_last_frame_in_picture = true) {
   // Run code under test.
-  RtpPacketizerAv1 packetizer(payload, limits, frame_type);
+  RtpPacketizerAv1 packetizer(payload, limits, frame_type,
+                              is_last_frame_in_picture);
   // Convert result into structure that is easier to run expectation against.
   std::vector<RtpPayload> result(packetizer.NumPackets());
   for (RtpPayload& rtp_payload : result) {
@@ -332,6 +334,34 @@
   EXPECT_THAT(ReassembleFrame(payloads), ElementsAreArray(kFrame));
 }
 
+TEST(RtpPacketizerAv1Test, SetMarkerBitForLastPacketInEndOfPictureFrame) {
+  auto kFrame = BuildAv1Frame(
+      {Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
+
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 100;
+  auto payloads = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta,
+                            /*is_last_frame_in_picture=*/true);
+  ASSERT_THAT(payloads, SizeIs(3u));
+  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
+  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
+  EXPECT_TRUE(payloads[2].rtp_packet.Marker());
+}
+
+TEST(RtpPacketizerAv1Test, DoesntSetMarkerBitForPacketsNotInEndOfPictureFrame) {
+  auto kFrame = BuildAv1Frame(
+      {Obu(kObuTypeFrame).WithPayload(std::vector<uint8_t>(200, 27))});
+
+  RtpPacketizer::PayloadSizeLimits limits;
+  limits.max_payload_len = 100;
+  auto payloads = Packetize(kFrame, limits, VideoFrameType::kVideoFrameDelta,
+                            /*is_last_frame_in_picture=*/false);
+  ASSERT_THAT(payloads, SizeIs(3u));
+  EXPECT_FALSE(payloads[0].rtp_packet.Marker());
+  EXPECT_FALSE(payloads[1].rtp_packet.Marker());
+  EXPECT_FALSE(payloads[2].rtp_packet.Marker());
+}
+
 TEST(RtpPacketizerAv1Test, SplitTwoObusIntoTwoPackets) {
   // 2nd OBU is too large to fit into one packet, so its head would be in the
   // same packet as the 1st OBU.
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index b2268c7..69a64fe 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -536,15 +536,6 @@
   return -1;
 }
 
-void ModuleRtpRtcpImpl::SetRtcpXrRrtrStatus(bool enable) {
-  rtcp_receiver_.SetRtcpXrRrtrStatus(enable);
-  rtcp_sender_.SendRtcpXrReceiverReferenceTime(enable);
-}
-
-bool ModuleRtpRtcpImpl::RtcpXrRrtrStatus() const {
-  return rtcp_sender_.RtcpXrReceiverReferenceTime();
-}
-
 // TODO(asapersson): Replace this method with the one below.
 int32_t ModuleRtpRtcpImpl::DataCountersRTP(size_t* bytes_sent,
                                            uint32_t* packets_sent) const {
@@ -817,15 +808,4 @@
   return rtp_sender_ ? &rtp_sender_->packet_generator : nullptr;
 }
 
-DataRate ModuleRtpRtcpImpl::SendRate() const {
-  RTC_DCHECK(rtp_sender_);
-  return rtp_sender_->packet_sender.GetSendRates().Sum();
-}
-
-DataRate ModuleRtpRtcpImpl::NackOverheadRate() const {
-  RTC_DCHECK(rtp_sender_);
-  return rtp_sender_->packet_sender
-      .GetSendRates()[RtpPacketMediaType::kRetransmission];
-}
-
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index 7f7df17..e30f1cc 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -238,8 +238,6 @@
   // requests.
   void SetStorePacketsStatus(bool enable, uint16_t number_to_store) override;
 
-  bool StorePackets() const override;
-
   void SendCombinedRtcpPacket(
       std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets) override;
 
@@ -249,11 +247,6 @@
                                          const uint8_t* data,
                                          uint16_t length) override;
 
-  // (XR) Receiver reference time report.
-  void SetRtcpXrRrtrStatus(bool enable) override;
-
-  bool RtcpXrRrtrStatus() const override;
-
   // Video part.
   int32_t SendLossNotification(uint16_t last_decoded_seq_num,
                                uint16_t last_received_seq_num,
@@ -300,10 +293,6 @@
 
   Clock* clock() const { return clock_; }
 
-  // TODO(sprang): Remove when usage is gone.
-  DataRate SendRate() const;
-  DataRate NackOverheadRate() const;
-
  private:
   FRIEND_TEST_ALL_PREFIXES(RtpRtcpImplTest, Rtt);
   FRIEND_TEST_ALL_PREFIXES(RtpRtcpImplTest, RttForReceiverOnly);
@@ -326,6 +315,12 @@
 
   bool TimeToSendFullNackList(int64_t now) const;
 
+  // Returns true if the module is configured to store packets.
+  bool StorePackets() const;
+
+  // Returns current Receiver Reference Time Report (RTTR) status.
+  bool RtcpXrRrtrStatus() const;
+
   std::unique_ptr<RtpSenderContext> rtp_sender_;
 
   RTCPSender rtcp_sender_;
@@ -348,7 +343,7 @@
 
   // The processed RTT from RtcpRttStats.
   mutable Mutex mutex_rtt_;
-  int64_t rtt_ms_;
+  int64_t rtt_ms_ RTC_GUARDED_BY(mutex_rtt_);
 };
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc
index 88ede3d..94dc297 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2.cc
@@ -479,15 +479,6 @@
   return rtcp_sender_.SendRTCP(GetFeedbackState(), packet_type);
 }
 
-void ModuleRtpRtcpImpl2::SetRtcpXrRrtrStatus(bool enable) {
-  rtcp_receiver_.SetRtcpXrRrtrStatus(enable);
-  rtcp_sender_.SendRtcpXrReceiverReferenceTime(enable);
-}
-
-bool ModuleRtpRtcpImpl2::RtcpXrRrtrStatus() const {
-  return rtcp_sender_.RtcpXrReceiverReferenceTime();
-}
-
 void ModuleRtpRtcpImpl2::GetSendStreamDataCounters(
     StreamDataCounters* rtp_counters,
     StreamDataCounters* rtx_counters) const {
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2.h b/modules/rtp_rtcp/source/rtp_rtcp_impl2.h
index 9eb7e3a..9431e75 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl2.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2.h
@@ -37,6 +37,7 @@
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/synchronization/mutex.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 #include "rtc_base/task_utils/pending_task_safety_flag.h"
 #include "rtc_base/task_utils/repeating_task.h"
 
@@ -230,16 +231,9 @@
   // requests.
   void SetStorePacketsStatus(bool enable, uint16_t number_to_store) override;
 
-  bool StorePackets() const override;
-
   void SendCombinedRtcpPacket(
       std::vector<std::unique_ptr<rtcp::RtcpPacket>> rtcp_packets) override;
 
-  // (XR) Receiver reference time report.
-  void SetRtcpXrRrtrStatus(bool enable) override;
-
-  bool RtcpXrRrtrStatus() const override;
-
   // Video part.
   int32_t SendLossNotification(uint16_t last_decoded_seq_num,
                                uint16_t last_received_seq_num,
@@ -291,8 +285,11 @@
   // check if we need to send RTCP report, send TMMBR updates and fire events.
   void PeriodicUpdate();
 
+  // Returns true if the module is configured to store packets.
+  bool StorePackets() const;
+
   TaskQueueBase* const worker_queue_;
-  SequenceChecker process_thread_checker_;
+  RTC_NO_UNIQUE_ADDRESS SequenceChecker process_thread_checker_;
 
   std::unique_ptr<RtpSenderContext> rtp_sender_;
 
@@ -316,7 +313,7 @@
 
   // The processed RTT from RtcpRttStats.
   mutable Mutex mutex_rtt_;
-  int64_t rtt_ms_;
+  int64_t rtt_ms_ RTC_GUARDED_BY(mutex_rtt_);
 };
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc
index 9925c54..3b66642 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl2_unittest.cc
@@ -160,6 +160,7 @@
     config.rtcp_report_interval_ms = rtcp_report_interval_ms_;
     config.local_media_ssrc = is_sender_ ? kSenderSsrc : kReceiverSsrc;
     config.need_rtp_packet_infos = true;
+    config.non_sender_rtt_measurement = true;
 
     impl_.reset(new ModuleRtpRtcpImpl2(config));
     impl_->SetRemoteSSRC(is_sender_ ? kReceiverSsrc : kSenderSsrc);
@@ -320,15 +321,7 @@
   EXPECT_NEAR(2 * kOneWayNetworkDelayMs, sender_.impl_->rtt_ms(), 1);
 }
 
-TEST_F(RtpRtcpImpl2Test, SetRtcpXrRrtrStatus) {
-  EXPECT_FALSE(receiver_.impl_->RtcpXrRrtrStatus());
-  receiver_.impl_->SetRtcpXrRrtrStatus(true);
-  EXPECT_TRUE(receiver_.impl_->RtcpXrRrtrStatus());
-}
-
 TEST_F(RtpRtcpImpl2Test, RttForReceiverOnly) {
-  receiver_.impl_->SetRtcpXrRrtrStatus(true);
-
   // Receiver module should send a Receiver time reference report (RTRR).
   EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport));
 
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 826e4cb..05c6ae1 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -155,6 +155,7 @@
     config.rtcp_report_interval_ms = rtcp_report_interval_ms_;
     config.local_media_ssrc = is_sender_ ? kSenderSsrc : kReceiverSsrc;
     config.need_rtp_packet_infos = true;
+    config.non_sender_rtt_measurement = true;
 
     impl_.reset(new ModuleRtpRtcpImpl(config));
     impl_->SetRemoteSSRC(is_sender_ ? kReceiverSsrc : kSenderSsrc);
@@ -308,15 +309,7 @@
   EXPECT_NEAR(2 * kOneWayNetworkDelayMs, sender_.impl_->rtt_ms(), 1);
 }
 
-TEST_F(RtpRtcpImplTest, SetRtcpXrRrtrStatus) {
-  EXPECT_FALSE(receiver_.impl_->RtcpXrRrtrStatus());
-  receiver_.impl_->SetRtcpXrRrtrStatus(true);
-  EXPECT_TRUE(receiver_.impl_->RtcpXrRrtrStatus());
-}
-
 TEST_F(RtpRtcpImplTest, RttForReceiverOnly) {
-  receiver_.impl_->SetRtcpXrRrtrStatus(true);
-
   // Receiver module should send a Receiver time reference report (RTRR).
   EXPECT_EQ(0, receiver_.impl_->SendRTCP(kRtcpReport));
 
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_interface.h b/modules/rtp_rtcp/source/rtp_rtcp_interface.h
index 3bd5d47..5bb3eb5 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_interface.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_interface.h
@@ -144,6 +144,10 @@
     // overhead.
     bool enable_rtx_padding_prioritization = true;
 
+    // Estimate RTT as non-sender as described in
+    // https://tools.ietf.org/html/rfc3611#section-4.4 and #section-4.5
+    bool non_sender_rtt_measurement = false;
+
    private:
     RTC_DISALLOW_COPY_AND_ASSIGN(Configuration);
   };
@@ -369,12 +373,6 @@
   // that pair.
   virtual std::vector<ReportBlockData> GetLatestReportBlockData() const = 0;
 
-  // (XR) Sets Receiver Reference Time Report (RTTR) status.
-  virtual void SetRtcpXrRrtrStatus(bool enable) = 0;
-
-  // Returns current Receiver Reference Time Report (RTTR) status.
-  virtual bool RtcpXrRrtrStatus() const = 0;
-
   // (REMB) Receiver Estimated Max Bitrate.
   // Schedules sending REMB on next and following sender/receiver reports.
   void SetRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) override = 0;
@@ -399,9 +397,6 @@
   // requests.
   virtual void SetStorePacketsStatus(bool enable, uint16_t numberToStore) = 0;
 
-  // Returns true if the module is configured to store packets.
-  virtual bool StorePackets() const = 0;
-
   virtual void SetVideoBitrateAllocation(
       const VideoBitrateAllocation& bitrate) = 0;
 
diff --git a/modules/rtp_rtcp/source/rtp_sender_egress.h b/modules/rtp_rtcp/source/rtp_sender_egress.h
index 8e36425..d7d71e2 100644
--- a/modules/rtp_rtcp/source/rtp_sender_egress.h
+++ b/modules/rtp_rtcp/source/rtp_sender_egress.h
@@ -30,6 +30,7 @@
 #include "rtc_base/rate_statistics.h"
 #include "rtc_base/synchronization/mutex.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 #include "rtc_base/task_utils/pending_task_safety_flag.h"
 #include "rtc_base/task_utils/repeating_task.h"
 #include "rtc_base/thread_annotations.h"
@@ -127,7 +128,7 @@
   void PeriodicUpdate();
 
   TaskQueueBase* const worker_queue_;
-  SequenceChecker pacer_checker_;
+  RTC_NO_UNIQUE_ADDRESS SequenceChecker pacer_checker_;
   const uint32_t ssrc_;
   const absl::optional<uint32_t> rtx_ssrc_;
   const absl::optional<uint32_t> flexfec_ssrc_;
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index 38f2d10..807d63d 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -77,6 +77,7 @@
 
 using ::testing::_;
 using ::testing::AllOf;
+using ::testing::AtLeast;
 using ::testing::Contains;
 using ::testing::Each;
 using ::testing::ElementsAreArray;
@@ -2818,6 +2819,53 @@
   EXPECT_GT(rtp_sender()->ReSendPacket(kSeqNum), 0);
 }
 
+TEST_P(RtpSenderTest, MarksPacketsWithKeyframeStatus) {
+  FieldTrialBasedConfig field_trials;
+  RTPSenderVideo::Config video_config;
+  video_config.clock = clock_;
+  video_config.rtp_sender = rtp_sender();
+  video_config.field_trials = &field_trials;
+  RTPSenderVideo rtp_sender_video(video_config);
+
+  const uint8_t kPayloadType = 127;
+  const absl::optional<VideoCodecType> kCodecType =
+      VideoCodecType::kVideoCodecGeneric;
+
+  const uint32_t kCaptureTimeMsToRtpTimestamp = 90;  // 90 kHz clock
+
+  {
+    EXPECT_CALL(mock_paced_sender_,
+                EnqueuePackets(Each(
+                    Pointee(Property(&RtpPacketToSend::is_key_frame, true)))))
+        .Times(AtLeast(1));
+    RTPVideoHeader video_header;
+    video_header.frame_type = VideoFrameType::kVideoFrameKey;
+    int64_t capture_time_ms = clock_->TimeInMilliseconds();
+    EXPECT_TRUE(rtp_sender_video.SendVideo(
+        kPayloadType, kCodecType,
+        capture_time_ms * kCaptureTimeMsToRtpTimestamp, capture_time_ms,
+        kPayloadData, video_header, kDefaultExpectedRetransmissionTimeMs));
+
+    time_controller_.AdvanceTime(TimeDelta::Millis(33));
+  }
+
+  {
+    EXPECT_CALL(mock_paced_sender_,
+                EnqueuePackets(Each(
+                    Pointee(Property(&RtpPacketToSend::is_key_frame, false)))))
+        .Times(AtLeast(1));
+    RTPVideoHeader video_header;
+    video_header.frame_type = VideoFrameType::kVideoFrameDelta;
+    int64_t capture_time_ms = clock_->TimeInMilliseconds();
+    EXPECT_TRUE(rtp_sender_video.SendVideo(
+        kPayloadType, kCodecType,
+        capture_time_ms * kCaptureTimeMsToRtpTimestamp, capture_time_ms,
+        kPayloadData, video_header, kDefaultExpectedRetransmissionTimeMs));
+
+    time_controller_.AdvanceTime(TimeDelta::Millis(33));
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(WithAndWithoutOverhead,
                          RtpSenderTest,
                          ::testing::Values(TestConfig{false},
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index 7a75973..934be82 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -153,7 +153,7 @@
               : (kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers)),
       last_rotation_(kVideoRotation_0),
       transmit_color_space_next_frame_(false),
-      send_allocation_(false),
+      send_allocation_(SendVideoLayersAllocation::kDontSend),
       current_playout_delay_{-1, -1},
       playout_delay_pending_(false),
       forced_playout_delay_(LoadVideoPlayoutDelayOverride(config.field_trials)),
@@ -293,8 +293,13 @@
 void RTPSenderVideo::SetVideoLayersAllocationInternal(
     VideoLayersAllocation allocation) {
   RTC_DCHECK_RUNS_SERIALIZED(&send_checker_);
+  if (!allocation_ || allocation.active_spatial_layers.size() >
+                          allocation_->active_spatial_layers.size()) {
+    send_allocation_ = SendVideoLayersAllocation::kSendWithResolution;
+  } else if (send_allocation_ == SendVideoLayersAllocation::kDontSend) {
+    send_allocation_ = SendVideoLayersAllocation::kSendWithoutResolution;
+  }
   allocation_ = std::move(allocation);
-  send_allocation_ = true;
 }
 
 void RTPSenderVideo::AddRtpHeaderExtensions(
@@ -433,16 +438,14 @@
     }
   }
 
-  if (first_packet && send_allocation_) {
-    if (video_header.frame_type == VideoFrameType::kVideoFrameKey) {
-      packet->SetExtension<RtpVideoLayersAllocationExtension>(
-          allocation_.value());
-    } else if (PacketWillLikelyBeRequestedForRestransmitionIfLost(
-                   video_header)) {
-      VideoLayersAllocation allocation = allocation_.value();
-      allocation.resolution_and_frame_rate_is_valid = false;
-      packet->SetExtension<RtpVideoLayersAllocationExtension>(allocation);
-    }
+  if (first_packet &&
+      send_allocation_ != SendVideoLayersAllocation::kDontSend &&
+      (video_header.frame_type == VideoFrameType::kVideoFrameKey ||
+       PacketWillLikelyBeRequestedForRestransmitionIfLost(video_header))) {
+    VideoLayersAllocation allocation = allocation_.value();
+    allocation.resolution_and_frame_rate_is_valid =
+        send_allocation_ == SendVideoLayersAllocation::kSendWithResolution;
+    packet->SetExtension<RtpVideoLayersAllocationExtension>(allocation);
   }
 }
 
@@ -481,7 +484,7 @@
     }
     if (allocation_) {
       // Send the bitrate allocation on every key frame.
-      send_allocation_ = true;
+      send_allocation_ = SendVideoLayersAllocation::kSendWithResolution;
     }
   }
 
@@ -649,6 +652,8 @@
       return false;
 
     packet->set_allow_retransmission(allow_retransmission);
+    packet->set_is_key_frame(video_header.frame_type ==
+                             VideoFrameType::kVideoFrameKey);
 
     // Put packetization finish timestamp into extension.
     if (packet->HasExtension<VideoTimingExtension>()) {
@@ -704,7 +709,7 @@
     // This frame will likely be delivered, no need to populate playout
     // delay extensions until it changes again.
     playout_delay_pending_ = false;
-    send_allocation_ = false;
+    send_allocation_ = SendVideoLayersAllocation::kDontSend;
   }
 
   TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.h b/modules/rtp_rtcp/source/rtp_sender_video.h
index 3f431df..6e46990 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -159,6 +159,12 @@
     int64_t last_frame_time_ms;
   };
 
+  enum class SendVideoLayersAllocation {
+    kSendWithResolution,
+    kSendWithoutResolution,
+    kDontSend
+  };
+
   void SetVideoStructureInternal(
       const FrameDependencyStructure* video_structure);
   void SetVideoLayersAllocationInternal(VideoLayersAllocation allocation);
@@ -202,7 +208,7 @@
   absl::optional<VideoLayersAllocation> allocation_
       RTC_GUARDED_BY(send_checker_);
   // Flag indicating if we should send |allocation_|.
-  bool send_allocation_ RTC_GUARDED_BY(send_checker_);
+  SendVideoLayersAllocation send_allocation_ RTC_GUARDED_BY(send_checker_);
 
   // Current target playout delay.
   VideoPlayoutDelay current_playout_delay_ RTC_GUARDED_BY(send_checker_);
diff --git a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
index e415bad..55bafdc 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video_unittest.cc
@@ -862,7 +862,7 @@
 }
 
 TEST_P(RtpSenderVideoTest,
-       VideoLayersAllocationWithoutResolutionSentOnDeltaFrames) {
+       VideoLayersAllocationWithoutResolutionSentOnDeltaWhenUpdated) {
   const size_t kFrameSize = 100;
   uint8_t kFrame[kFrameSize];
   rtp_module_->RegisterRtpHeaderExtension(
@@ -876,14 +876,28 @@
   allocation.resolution_and_frame_rate_is_valid = true;
   layer.target_bitrate_per_temporal_layer.push_back(
       DataRate::KilobitsPerSec(50));
-
   allocation.active_spatial_layers.push_back(layer);
   rtp_sender_video_->SetVideoLayersAllocation(allocation);
 
   RTPVideoHeader hdr;
+  hdr.frame_type = VideoFrameType::kVideoFrameKey;
+  rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
+                               kDefaultExpectedRetransmissionTimeMs);
+  EXPECT_TRUE(transport_.last_sent_packet()
+                  .HasExtension<RtpVideoLayersAllocationExtension>());
+
+  // No allocation sent on delta frame unless it has been updated.
   hdr.frame_type = VideoFrameType::kVideoFrameDelta;
   rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
                                kDefaultExpectedRetransmissionTimeMs);
+  EXPECT_FALSE(transport_.last_sent_packet()
+                   .HasExtension<RtpVideoLayersAllocationExtension>());
+
+  // Update the allocation.
+  rtp_sender_video_->SetVideoLayersAllocation(allocation);
+  rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
+                               kDefaultExpectedRetransmissionTimeMs);
+
   VideoLayersAllocation sent_allocation;
   EXPECT_TRUE(
       transport_.last_sent_packet()
@@ -895,6 +909,52 @@
               SizeIs(1));
 }
 
+TEST_P(RtpSenderVideoTest,
+       VideoLayersAllocationWithResolutionSentOnDeltaWhenSpatialLayerAdded) {
+  const size_t kFrameSize = 100;
+  uint8_t kFrame[kFrameSize];
+  rtp_module_->RegisterRtpHeaderExtension(
+      RtpVideoLayersAllocationExtension::kUri,
+      kVideoLayersAllocationExtensionId);
+
+  VideoLayersAllocation allocation;
+  allocation.resolution_and_frame_rate_is_valid = true;
+  VideoLayersAllocation::SpatialLayer layer;
+  layer.width = 360;
+  layer.height = 180;
+  layer.spatial_id = 0;
+  layer.target_bitrate_per_temporal_layer.push_back(
+      DataRate::KilobitsPerSec(50));
+  allocation.active_spatial_layers.push_back(layer);
+  rtp_sender_video_->SetVideoLayersAllocation(allocation);
+
+  RTPVideoHeader hdr;
+  hdr.frame_type = VideoFrameType::kVideoFrameKey;
+  rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
+                               kDefaultExpectedRetransmissionTimeMs);
+  ASSERT_TRUE(transport_.last_sent_packet()
+                  .HasExtension<RtpVideoLayersAllocationExtension>());
+
+  // Update the allocation.
+  layer.width = 640;
+  layer.height = 320;
+  layer.spatial_id = 1;
+  layer.target_bitrate_per_temporal_layer.push_back(
+      DataRate::KilobitsPerSec(100));
+  allocation.active_spatial_layers.push_back(layer);
+  rtp_sender_video_->SetVideoLayersAllocation(allocation);
+  hdr.frame_type = VideoFrameType::kVideoFrameDelta;
+  rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
+                               kDefaultExpectedRetransmissionTimeMs);
+
+  VideoLayersAllocation sent_allocation;
+  EXPECT_TRUE(
+      transport_.last_sent_packet()
+          .GetExtension<RtpVideoLayersAllocationExtension>(&sent_allocation));
+  EXPECT_THAT(sent_allocation.active_spatial_layers, SizeIs(2));
+  EXPECT_TRUE(sent_allocation.resolution_and_frame_rate_is_valid);
+}
+
 TEST_P(RtpSenderVideoTest, VideoLayersAllocationSentOnDeltaFramesOnlyOnUpdate) {
   const size_t kFrameSize = 100;
   uint8_t kFrame[kFrameSize];
@@ -904,6 +964,8 @@
 
   VideoLayersAllocation allocation;
   VideoLayersAllocation::SpatialLayer layer;
+  layer.width = 360;
+  layer.height = 180;
   layer.target_bitrate_per_temporal_layer.push_back(
       DataRate::KilobitsPerSec(50));
   allocation.active_spatial_layers.push_back(layer);
@@ -943,7 +1005,10 @@
       kVideoLayersAllocationExtensionId);
 
   VideoLayersAllocation allocation;
+  allocation.resolution_and_frame_rate_is_valid = true;
   VideoLayersAllocation::SpatialLayer layer;
+  layer.width = 360;
+  layer.height = 180;
   layer.target_bitrate_per_temporal_layer.push_back(
       DataRate::KilobitsPerSec(50));
   allocation.active_spatial_layers.push_back(layer);
@@ -957,18 +1022,15 @@
 
   rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
                                kDefaultExpectedRetransmissionTimeMs);
-  VideoLayersAllocation sent_allocation;
-  EXPECT_FALSE(
-      transport_.last_sent_packet()
-          .GetExtension<RtpVideoLayersAllocationExtension>(&sent_allocation));
+  EXPECT_FALSE(transport_.last_sent_packet()
+                   .HasExtension<RtpVideoLayersAllocationExtension>());
 
   // Send a delta frame on tl0.
   vp8_header.temporalIdx = 0;
   rtp_sender_video_->SendVideo(kPayload, kType, kTimestamp, 0, kFrame, hdr,
                                kDefaultExpectedRetransmissionTimeMs);
-  EXPECT_TRUE(
-      transport_.last_sent_packet()
-          .GetExtension<RtpVideoLayersAllocationExtension>(&sent_allocation));
+  EXPECT_TRUE(transport_.last_sent_packet()
+                  .HasExtension<RtpVideoLayersAllocationExtension>());
 }
 
 TEST_P(RtpSenderVideoTest, AbsoluteCaptureTime) {
diff --git a/modules/rtp_rtcp/source/rtp_video_header.h b/modules/rtp_rtcp/source/rtp_video_header.h
index ca34155..8a2fcba 100644
--- a/modules/rtp_rtcp/source/rtp_video_header.h
+++ b/modules/rtp_rtcp/source/rtp_video_header.h
@@ -70,6 +70,7 @@
   VideoContentType content_type = VideoContentType::UNSPECIFIED;
   bool is_first_packet_in_frame = false;
   bool is_last_packet_in_frame = false;
+  bool is_last_frame_in_picture = true;
   uint8_t simulcastIdx = 0;
   VideoCodecType codec = VideoCodecType::kVideoCodecGeneric;
 
diff --git a/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.cc b/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.cc
index dbaa36b..1587bc3 100644
--- a/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.cc
+++ b/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.cc
@@ -10,10 +10,13 @@
 
 #include "modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.h"
 
-#include <limits>
+#include <stddef.h>
+#include <stdint.h>
 
+#include "absl/algorithm/container.h"
 #include "api/video/video_layers_allocation.h"
-#include "rtc_base/bit_buffer.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "rtc_base/checks.h"
 
 namespace webrtc {
 
@@ -22,202 +25,348 @@
 
 namespace {
 
-// Counts the number of bits used in the binary representation of val.
-size_t CountBits(uint64_t val) {
-  size_t bit_count = 0;
-  while (val != 0) {
-    bit_count++;
-    val >>= 1;
+constexpr int kMaxNumRtpStreams = 4;
+
+// TODO(bugs.webrtc.org/12000): share Leb128 functions with av1 packetizer.
+// Returns minimum number of bytes required to store `value`.
+int Leb128Size(uint32_t value) {
+  int size = 0;
+  while (value >= 0x80) {
+    ++size;
+    value >>= 7;
   }
-  return bit_count;
+  return size + 1;
 }
 
-// Counts the number of bits used if `val`is encoded using unsigned exponential
-// Golomb encoding.
-// TODO(bugs.webrtc.org/12000): Move to bit_buffer.cc if Golomb encoding is used
-// in the final version.
-size_t SizeExponentialGolomb(uint32_t val) {
-  if (val == std::numeric_limits<uint32_t>::max()) {
-    return 0;
+// Returns number of bytes consumed.
+int WriteLeb128(uint32_t value, uint8_t* buffer) {
+  int size = 0;
+  while (value >= 0x80) {
+    buffer[size] = 0x80 | (value & 0x7F);
+    ++size;
+    value >>= 7;
   }
-  uint64_t val_to_encode = static_cast<uint64_t>(val) + 1;
-  return CountBits(val_to_encode) * 2 - 1;
+  buffer[size] = value;
+  ++size;
+  return size;
+}
+
+// Reads leb128 encoded value and advance read_at by number of bytes consumed.
+// Sets read_at to nullptr on error.
+uint64_t ReadLeb128(const uint8_t*& read_at, const uint8_t* end) {
+  uint64_t value = 0;
+  int fill_bits = 0;
+  while (read_at != end && fill_bits < 64 - 7) {
+    uint8_t leb128_byte = *read_at;
+    value |= uint64_t{leb128_byte & 0x7Fu} << fill_bits;
+    ++read_at;
+    fill_bits += 7;
+    if ((leb128_byte & 0x80) == 0) {
+      return value;
+    }
+  }
+  // Failed to find terminator leb128 byte.
+  read_at = nullptr;
+  return 0;
+}
+
+bool AllocationIsValid(const VideoLayersAllocation& allocation) {
+  // Since all multivalue fields are stored in (rtp_stream_id, spatial_id) order
+  // assume `allocation.active_spatial_layers` is already sorted. It is simpler
+  // to assemble it in the sorted way than to resort during serialization.
+  if (!absl::c_is_sorted(
+          allocation.active_spatial_layers,
+          [](const VideoLayersAllocation::SpatialLayer& lhs,
+             const VideoLayersAllocation::SpatialLayer& rhs) {
+            return std::make_tuple(lhs.rtp_stream_index, lhs.spatial_id) <
+                   std::make_tuple(rhs.rtp_stream_index, rhs.spatial_id);
+          })) {
+    return false;
+  }
+
+  int max_rtp_stream_idx = 0;
+  for (const auto& spatial_layer : allocation.active_spatial_layers) {
+    if (spatial_layer.rtp_stream_index < 0 ||
+        spatial_layer.rtp_stream_index >= 4) {
+      return false;
+    }
+    if (spatial_layer.spatial_id < 0 || spatial_layer.spatial_id >= 4) {
+      return false;
+    }
+    if (spatial_layer.target_bitrate_per_temporal_layer.empty() ||
+        spatial_layer.target_bitrate_per_temporal_layer.size() > 4) {
+      return false;
+    }
+    if (max_rtp_stream_idx < spatial_layer.rtp_stream_index) {
+      max_rtp_stream_idx = spatial_layer.rtp_stream_index;
+    }
+    if (allocation.resolution_and_frame_rate_is_valid) {
+      // TODO(danilchap): Add check width and height are no more than 0x10000
+      // when width and height become larger type and thus would support maximum
+      // resolution.
+      if (spatial_layer.width <= 0) {
+        return false;
+      }
+      if (spatial_layer.height <= 0) {
+        return false;
+      }
+      if (spatial_layer.frame_rate_fps < 0 ||
+          spatial_layer.frame_rate_fps > 255) {
+        return false;
+      }
+    }
+  }
+  if (allocation.rtp_stream_index < 0 ||
+      allocation.rtp_stream_index > max_rtp_stream_idx) {
+    return false;
+  }
+  return true;
+}
+
+struct SpatialLayersBitmasks {
+  int max_rtp_stream_id = 0;
+  uint8_t spatial_layer_bitmask[kMaxNumRtpStreams] = {};
+  bool bitmasks_are_the_same = true;
+};
+
+SpatialLayersBitmasks SpatialLayersBitmasksPerRtpStream(
+    const VideoLayersAllocation& allocation) {
+  RTC_DCHECK(AllocationIsValid(allocation));
+  SpatialLayersBitmasks result;
+  for (const auto& layer : allocation.active_spatial_layers) {
+    result.spatial_layer_bitmask[layer.rtp_stream_index] |=
+        (1u << layer.spatial_id);
+    if (result.max_rtp_stream_id < layer.rtp_stream_index) {
+      result.max_rtp_stream_id = layer.rtp_stream_index;
+    }
+  }
+  for (int i = 1; i <= result.max_rtp_stream_id; ++i) {
+    if (result.spatial_layer_bitmask[i] != result.spatial_layer_bitmask[0]) {
+      result.bitmasks_are_the_same = false;
+      break;
+    }
+  }
+  return result;
 }
 
 }  // namespace
 
-// TODO(bugs.webrtc.org/12000): Review and revise the content and encoding of
-// this extension. This is an experimental first version.
-
-//  0                   1                   2
-//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// | NS|RSID|T|X|Res| Bit encoded data...
-// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-// NS: Number of spatial layers/simulcast streams - 1. 2 bits, thus allowing
-// passing number of layers/streams up-to 4.
-// RSID: RTP stream id this allocation is sent on, numbered from 0. 2 bits.
-// T: indicates if all spatial layers have the same amount of temporal layers.
-// X: indicates if resolution and frame rate per spatial layer is present.
-// Res: 2 bits reserved for future use.
-// Bit encoded data: consists of following fields written in order:
-//  1) T=1: Nt - 2-bit value of number of temporal layers - 1
-//     T=0: NS 2-bit values of numbers of temporal layers - 1 for all spatial
-//     layers from lower to higher.
-//  2) Bitrates:
-//     One value for each spatial x temporal layer.
-//     Format: RSID (2-bit) SID(2-bit),folowed by bitrate for all temporal
-//     layers for the RSID,SID tuple. All bitrates are in kbps. All bitrates are
-//     total required bitrate to receive the corresponding layer, i.e. in
-//     simulcast mode they include only corresponding spatial layer, in full-svc
-//     all lower spatial layers are included. All lower temporal layers are also
-//     included. All bitrates are written using unsigned Exponential Golomb
-//     encoding.
-//  3) [only if X bit is set]. Encoded width, 16-bit, height, 16-bit,
-//    max frame rate 8-bit per spatial layer in order from lower to higher.
+//                           +-+-+-+-+-+-+-+-+
+//                           |RID| NS| sl_bm |
+//                           +-+-+-+-+-+-+-+-+
+// Spatial layer bitmask     |sl0_bm |sl1_bm |
+//   up to 2 bytes           |---------------|
+//   when sl_bm == 0         |sl2_bm |sl3_bm |
+//                           +-+-+-+-+-+-+-+-+
+//   Number of temporal      |#tl|#tl|#tl|#tl|
+// layers per spatial layer  :---------------:
+//    up to 4 bytes          |      ...      |
+//                           +-+-+-+-+-+-+-+-+
+//  Target bitrate in kpbs   |               |
+//   per temporal layer      :      ...      :
+//    leb128 encoded         |               |
+//                           +-+-+-+-+-+-+-+-+
+// Resolution and framerate  |               |
+// 5 bytes per spatial layer + width-1 for   +
+//      (optional)           | rid=0, sid=0  |
+//                           +---------------+
+//                           |               |
+//                           + height-1 for  +
+//                           | rid=0, sid=0  |
+//                           +---------------+
+//                           | max framerate |
+//                           +-+-+-+-+-+-+-+-+
+//                           :      ...      :
+//                           +-+-+-+-+-+-+-+-+
+//
+// RID: RTP stream index this allocation is sent on, numbered from 0. 2 bits.
+// NS: Number of RTP streams - 1. 2 bits, thus allowing up-to 4 RTP streams.
+// sl_bm: BitMask of the active Spatial Layers when same for all RTP streams or
+//     0 otherwise. 4 bits thus allows up to 4 spatial layers per RTP streams.
+// slX_bm: BitMask of the active Spatial Layers for RTP stream with index=X.
+//     byte-aligned. When NS < 2, takes ones byte, otherwise uses two bytes.
+// #tl: 2-bit value of number of temporal layers-1, thus allowing up-to 4
+//     temporal layer per spatial layer. One per spatial layer per RTP stream.
+//     values are stored in (RTP stream id, spatial id) ascending order.
+//     zero-padded to byte alignment.
+// Target bitrate in kbps. Values are stored using leb128 encoding.
+//     one value per temporal layer.  values are stored in
+//     (RTP stream id, spatial id, temporal id) ascending order.
+//     All bitrates are total required bitrate to receive the corresponding
+//     layer, i.e. in simulcast mode they include only corresponding spatial
+//     layer, in full-svc all lower spatial layers are included. All lower
+//     temporal layers are also included.
+// Resolution and framerate.
+//     Optional. Presense is infered from the rtp header extension size.
+//     Encoded (width - 1), 16-bit, (height - 1), 16-bit,  max frame rate 8-bit
+//     per spatial layer per RTP stream.
+//     Values are stored in (RTP stream id, spatial id) ascending order.
 
 bool RtpVideoLayersAllocationExtension::Write(
     rtc::ArrayView<uint8_t> data,
     const VideoLayersAllocation& allocation) {
-  RTC_DCHECK_LT(allocation.rtp_stream_index,
-                VideoLayersAllocation::kMaxSpatialIds);
-  RTC_DCHECK_GE(data.size(), ValueSize(allocation));
-  rtc::BitBufferWriter writer(data.data(), data.size());
-
-  // NS:
-  if (allocation.active_spatial_layers.empty())
+  if (allocation.active_spatial_layers.empty()) {
     return false;
-  writer.WriteBits(allocation.active_spatial_layers.size() - 1, 2);
-
-  // RSID:
-  writer.WriteBits(allocation.rtp_stream_index, 2);
-
-  // T:
-  bool num_tls_is_the_same = true;
-  size_t first_layers_number_of_temporal_layers =
-      allocation.active_spatial_layers.front()
-          .target_bitrate_per_temporal_layer.size();
-  for (const auto& spatial_layer : allocation.active_spatial_layers) {
-    if (first_layers_number_of_temporal_layers !=
-        spatial_layer.target_bitrate_per_temporal_layer.size()) {
-      num_tls_is_the_same = false;
-      break;
-    }
   }
-  writer.WriteBits(num_tls_is_the_same ? 1 : 0, 1);
 
-  // X:
-  writer.WriteBits(allocation.resolution_and_frame_rate_is_valid ? 1 : 0, 1);
+  RTC_DCHECK(AllocationIsValid(allocation));
+  RTC_DCHECK_GE(data.size(), ValueSize(allocation));
 
-  // RESERVED:
-  writer.WriteBits(/*val=*/0, /*bit_count=*/2);
-
-  if (num_tls_is_the_same) {
-    writer.WriteBits(first_layers_number_of_temporal_layers - 1, 2);
+  SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
+  uint8_t* write_at = data.data();
+  // First half of the header byte.
+  *write_at = (allocation.rtp_stream_index << 6);
+  // number of rtp stream - 1 is the same as the maximum rtp_stream_id.
+  *write_at |= slb.max_rtp_stream_id << 4;
+  if (slb.bitmasks_are_the_same) {
+    // Second half of the header byte.
+    *write_at |= slb.spatial_layer_bitmask[0];
   } else {
-    for (const auto& spatial_layer : allocation.active_spatial_layers) {
-      writer.WriteBits(
-          spatial_layer.target_bitrate_per_temporal_layer.size() - 1, 2);
+    // spatial layer bitmasks when they are different for different RTP streams.
+    *++write_at =
+        (slb.spatial_layer_bitmask[0] << 4) | slb.spatial_layer_bitmask[1];
+    if (slb.max_rtp_stream_id >= 2) {
+      *++write_at =
+          (slb.spatial_layer_bitmask[2] << 4) | slb.spatial_layer_bitmask[3];
     }
   }
+  ++write_at;
 
+  {  // Number of temporal layers.
+    int bit_offset = 8;
+    *write_at = 0;
+    for (const auto& layer : allocation.active_spatial_layers) {
+      if (bit_offset == 0) {
+        bit_offset = 6;
+        *++write_at = 0;
+      } else {
+        bit_offset -= 2;
+      }
+      *write_at |=
+          ((layer.target_bitrate_per_temporal_layer.size() - 1) << bit_offset);
+    }
+    ++write_at;
+  }
+
+  // Target bitrates.
   for (const auto& spatial_layer : allocation.active_spatial_layers) {
-    writer.WriteBits(spatial_layer.rtp_stream_index, 2);
-    writer.WriteBits(spatial_layer.spatial_id, 2);
     for (const DataRate& bitrate :
          spatial_layer.target_bitrate_per_temporal_layer) {
-      writer.WriteExponentialGolomb(bitrate.kbps());
+      write_at += WriteLeb128(bitrate.kbps(), write_at);
     }
   }
 
   if (allocation.resolution_and_frame_rate_is_valid) {
     for (const auto& spatial_layer : allocation.active_spatial_layers) {
-      writer.WriteUInt16(spatial_layer.width);
-      writer.WriteUInt16(spatial_layer.height);
-      writer.WriteUInt8(spatial_layer.frame_rate_fps);
+      ByteWriter<uint16_t>::WriteBigEndian(write_at, spatial_layer.width - 1);
+      write_at += 2;
+      ByteWriter<uint16_t>::WriteBigEndian(write_at, spatial_layer.height - 1);
+      write_at += 2;
+      *write_at = spatial_layer.frame_rate_fps;
+      ++write_at;
     }
   }
+  RTC_DCHECK_EQ(write_at - data.data(), ValueSize(allocation));
   return true;
 }
 
 bool RtpVideoLayersAllocationExtension::Parse(
     rtc::ArrayView<const uint8_t> data,
     VideoLayersAllocation* allocation) {
-  if (data.size() == 0)
+  if (data.empty() || allocation == nullptr) {
     return false;
-  rtc::BitBuffer reader(data.data(), data.size());
-  if (!allocation)
-    return false;
+  }
+  const uint8_t* read_at = data.data();
+  const uint8_t* const end = data.data() + data.size();
+
   allocation->active_spatial_layers.clear();
+  // Header byte.
+  allocation->rtp_stream_index = *read_at >> 6;
+  int num_rtp_streams = 1 + ((*read_at >> 4) & 0b11);
+  uint8_t spatial_layers_bitmasks[kMaxNumRtpStreams];
+  spatial_layers_bitmasks[0] = *read_at & 0b1111;
 
-  uint32_t val;
-  // NS:
-  if (!reader.ReadBits(&val, 2))
-    return false;
-  int active_spatial_layers = val + 1;
-
-  // RSID:
-  if (!reader.ReadBits(&val, 2))
-    return false;
-  allocation->rtp_stream_index = val;
-
-  // T:
-  if (!reader.ReadBits(&val, 1))
-    return false;
-  bool num_tls_is_constant = (val == 1);
-
-  // X:
-  if (!reader.ReadBits(&val, 1))
-    return false;
-  allocation->resolution_and_frame_rate_is_valid = (val == 1);
-
-  // RESERVED:
-  if (!reader.ReadBits(&val, 2))
-    return false;
-
-  int number_of_temporal_layers[VideoLayersAllocation::kMaxSpatialIds];
-  if (num_tls_is_constant) {
-    if (!reader.ReadBits(&val, 2))
-      return false;
-    for (int sl_idx = 0; sl_idx < active_spatial_layers; ++sl_idx) {
-      number_of_temporal_layers[sl_idx] = val + 1;
+  if (spatial_layers_bitmasks[0] != 0) {
+    for (int i = 1; i < num_rtp_streams; ++i) {
+      spatial_layers_bitmasks[i] = spatial_layers_bitmasks[0];
     }
   } else {
-    for (int sl_idx = 0; sl_idx < active_spatial_layers; ++sl_idx) {
-      if (!reader.ReadBits(&val, 2))
+    // Spatial layer bitmasks when they are different for different RTP streams.
+    if (++read_at == end) {
+      return false;
+    }
+    spatial_layers_bitmasks[0] = *read_at >> 4;
+    spatial_layers_bitmasks[1] = *read_at & 0b1111;
+    if (num_rtp_streams > 2) {
+      if (++read_at == end) {
         return false;
-      number_of_temporal_layers[sl_idx] = val + 1;
-      if (number_of_temporal_layers[sl_idx] >
-          VideoLayersAllocation::kMaxTemporalIds)
+      }
+      spatial_layers_bitmasks[2] = *read_at >> 4;
+      spatial_layers_bitmasks[3] = *read_at & 0b1111;
+    }
+  }
+  if (++read_at == end) {
+    return false;
+  }
+
+  // Read number of temporal layers,
+  // Create `allocation->active_spatial_layers` while iterating though it.
+  int bit_offset = 8;
+  for (int stream_idx = 0; stream_idx < num_rtp_streams; ++stream_idx) {
+    for (int sid = 0; sid < VideoLayersAllocation::kMaxSpatialIds; ++sid) {
+      if ((spatial_layers_bitmasks[stream_idx] & (1 << sid)) == 0) {
+        continue;
+      }
+
+      if (bit_offset == 0) {
+        bit_offset = 6;
+        if (++read_at == end) {
+          return false;
+        }
+      } else {
+        bit_offset -= 2;
+      }
+      int num_temporal_layers = 1 + ((*read_at >> bit_offset) & 0b11);
+      allocation->active_spatial_layers.emplace_back();
+      auto& layer = allocation->active_spatial_layers.back();
+      layer.rtp_stream_index = stream_idx;
+      layer.spatial_id = sid;
+      layer.target_bitrate_per_temporal_layer.resize(num_temporal_layers,
+                                                     DataRate::Zero());
+    }
+  }
+  if (++read_at == end) {
+    return false;
+  }
+
+  // Target bitrates.
+  for (auto& layer : allocation->active_spatial_layers) {
+    for (DataRate& rate : layer.target_bitrate_per_temporal_layer) {
+      rate = DataRate::KilobitsPerSec(ReadLeb128(read_at, end));
+      if (read_at == nullptr) {
         return false;
+      }
     }
   }
 
-  for (int sl_idx = 0; sl_idx < active_spatial_layers; ++sl_idx) {
-    allocation->active_spatial_layers.emplace_back();
-    auto& spatial_layer = allocation->active_spatial_layers.back();
-    auto& temporal_layers = spatial_layer.target_bitrate_per_temporal_layer;
-    if (!reader.ReadBits(&val, 2))
-      return false;
-    spatial_layer.rtp_stream_index = val;
-    if (!reader.ReadBits(&val, 2))
-      return false;
-    spatial_layer.spatial_id = val;
-    for (int tl_idx = 0; tl_idx < number_of_temporal_layers[sl_idx]; ++tl_idx) {
-      reader.ReadExponentialGolomb(&val);
-      temporal_layers.push_back(DataRate::KilobitsPerSec(val));
-    }
+  if (read_at == end) {
+    allocation->resolution_and_frame_rate_is_valid = false;
+    return true;
   }
 
-  if (allocation->resolution_and_frame_rate_is_valid) {
-    for (auto& spatial_layer : allocation->active_spatial_layers) {
-      if (!reader.ReadUInt16(&spatial_layer.width))
-        return false;
-      if (!reader.ReadUInt16(&spatial_layer.height))
-        return false;
-      if (!reader.ReadUInt8(&spatial_layer.frame_rate_fps))
-        return false;
-    }
+  if (read_at + 5 * allocation->active_spatial_layers.size() != end) {
+    // data is left, but it size is not what can be used for resolutions and
+    // framerates.
+    return false;
+  }
+  allocation->resolution_and_frame_rate_is_valid = true;
+  for (auto& layer : allocation->active_spatial_layers) {
+    layer.width = 1 + ByteReader<uint16_t, 2>::ReadBigEndian(read_at);
+    read_at += 2;
+    layer.height = 1 + ByteReader<uint16_t, 2>::ReadBigEndian(read_at);
+    read_at += 2;
+    layer.frame_rate_fps = *read_at;
+    ++read_at;
   }
   return true;
 }
@@ -227,34 +376,26 @@
   if (allocation.active_spatial_layers.empty()) {
     return 0;
   }
-  size_t size_in_bits = 8;  // Fixed first byte.¨
-  bool num_tls_is_the_same = true;
-  size_t first_layers_number_of_temporal_layers =
-      allocation.active_spatial_layers.front()
-          .target_bitrate_per_temporal_layer.size();
-  for (const auto& spatial_layer : allocation.active_spatial_layers) {
-    if (first_layers_number_of_temporal_layers !=
-        spatial_layer.target_bitrate_per_temporal_layer.size()) {
-      num_tls_is_the_same = false;
-    }
-    size_in_bits += 4;  // RSID, SID tuple.
-    for (const auto& bitrate :
-         spatial_layer.target_bitrate_per_temporal_layer) {
-      size_in_bits += SizeExponentialGolomb(bitrate.kbps());
+  size_t result = 1;  // header
+  SpatialLayersBitmasks slb = SpatialLayersBitmasksPerRtpStream(allocation);
+  if (!slb.bitmasks_are_the_same) {
+    ++result;
+    if (slb.max_rtp_stream_id >= 2) {
+      ++result;
     }
   }
-  if (num_tls_is_the_same) {
-    size_in_bits += 2;
-  } else {
-    for (const auto& spatial_layer : allocation.active_spatial_layers) {
-      size_in_bits +=
-          2 * spatial_layer.target_bitrate_per_temporal_layer.size();
+  // 2 bits per active spatial layer, rounded up to full byte, i.e.
+  // 0.25 byte per active spatial layer.
+  result += (allocation.active_spatial_layers.size() + 3) / 4;
+  for (const auto& spatial_layer : allocation.active_spatial_layers) {
+    for (DataRate value : spatial_layer.target_bitrate_per_temporal_layer) {
+      result += Leb128Size(value.kbps());
     }
   }
   if (allocation.resolution_and_frame_rate_is_valid) {
-    size_in_bits += allocation.active_spatial_layers.size() * 5 * 8;
+    result += 5 * allocation.active_spatial_layers.size();
   }
-  return (size_in_bits + 7) / 8;
+  return result;
 }
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension_unittest.cc b/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension_unittest.cc
index e51c637..c8363ae 100644
--- a/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_video_layers_allocation_extension_unittest.cc
@@ -11,6 +11,7 @@
 #include "modules/rtp_rtcp/source/rtp_video_layers_allocation_extension.h"
 
 #include "api/video/video_layers_allocation.h"
+#include "rtc_base/bit_buffer.h"
 #include "rtc_base/buffer.h"
 
 #include "test/gmock.h"
@@ -62,6 +63,96 @@
 }
 
 TEST(RtpVideoLayersAllocationExtension,
+     CanWriteAndParseAllocationWithDifferentNumerOfSpatialLayers) {
+  VideoLayersAllocation written_allocation;
+  written_allocation.rtp_stream_index = 1;
+  written_allocation.active_spatial_layers = {
+      {/*rtp_stream_index*/ 0,
+       /*spatial_id*/ 0,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+      {/*rtp_stream_index*/ 1,
+       /*spatial_id*/ 0,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(100)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+      {/*rtp_stream_index*/ 1,
+       /*spatial_id*/ 1,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+  };
+  rtc::Buffer buffer(
+      RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
+  EXPECT_TRUE(
+      RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
+  VideoLayersAllocation parsed_allocation;
+  EXPECT_TRUE(
+      RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
+  EXPECT_EQ(written_allocation, parsed_allocation);
+}
+
+TEST(RtpVideoLayersAllocationExtension,
+     CanWriteAndParseAllocationWithSkippedLowerSpatialLayer) {
+  VideoLayersAllocation written_allocation;
+  written_allocation.rtp_stream_index = 1;
+  written_allocation.active_spatial_layers = {
+      {/*rtp_stream_index*/ 0,
+       /*spatial_id*/ 0,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+      {/*rtp_stream_index*/ 1,
+       /*spatial_id*/ 1,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+  };
+  rtc::Buffer buffer(
+      RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
+  EXPECT_TRUE(
+      RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
+  VideoLayersAllocation parsed_allocation;
+  EXPECT_TRUE(
+      RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
+  EXPECT_EQ(written_allocation, parsed_allocation);
+}
+
+TEST(RtpVideoLayersAllocationExtension,
+     CanWriteAndParseAllocationWithSkippedRtpStreamIds) {
+  VideoLayersAllocation written_allocation;
+  written_allocation.rtp_stream_index = 2;
+  written_allocation.active_spatial_layers = {
+      {/*rtp_stream_index*/ 0,
+       /*spatial_id*/ 0,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(50)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+      {/*rtp_stream_index*/ 2,
+       /*spatial_id*/ 0,
+       /*target_bitrate_per_temporal_layer*/ {DataRate::KilobitsPerSec(200)},
+       /*width*/ 0,
+       /*height*/ 0,
+       /*frame_rate_fps*/ 0},
+  };
+  rtc::Buffer buffer(
+      RtpVideoLayersAllocationExtension::ValueSize(written_allocation));
+  EXPECT_TRUE(
+      RtpVideoLayersAllocationExtension::Write(buffer, written_allocation));
+  VideoLayersAllocation parsed_allocation;
+  EXPECT_TRUE(
+      RtpVideoLayersAllocationExtension::Parse(buffer, &parsed_allocation));
+  EXPECT_EQ(written_allocation, parsed_allocation);
+}
+
+TEST(RtpVideoLayersAllocationExtension,
      CanWriteAndParseAllocationWithDifferentNumerOfTemporalLayers) {
   VideoLayersAllocation written_allocation;
   written_allocation.rtp_stream_index = 1;
@@ -110,7 +201,7 @@
           /*frame_rate_fps*/ 8,
       },
       {
-          /*rtp_stream_index*/ 0,
+          /*rtp_stream_index*/ 1,
           /*spatial_id*/ 1,
           /*target_bitrate_per_temporal_layer*/
           {DataRate::KilobitsPerSec(100), DataRate::KilobitsPerSec(200)},
diff --git a/modules/rtp_rtcp/source/ulpfec_generator.cc b/modules/rtp_rtcp/source/ulpfec_generator.cc
index 76d1bb5..4873693 100644
--- a/modules/rtp_rtcp/source/ulpfec_generator.cc
+++ b/modules/rtp_rtcp/source/ulpfec_generator.cc
@@ -77,7 +77,7 @@
       fec_(ForwardErrorCorrection::CreateUlpfec(kUnknownSsrc)),
       num_protected_frames_(0),
       min_num_media_packets_(1),
-      keyframe_in_process_(false),
+      media_contains_keyframe_(false),
       fec_bitrate_(/*max_window_size_ms=*/1000, RateStatistics::kBpsScale) {}
 
 // Used by FlexFecSender, payload types are unused.
@@ -89,7 +89,7 @@
       fec_(std::move(fec)),
       num_protected_frames_(0),
       min_num_media_packets_(1),
-      keyframe_in_process_(false),
+      media_contains_keyframe_(false),
       fec_bitrate_(/*max_window_size_ms=*/1000, RateStatistics::kBpsScale) {}
 
 UlpfecGenerator::~UlpfecGenerator() = default;
@@ -111,7 +111,7 @@
   RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
   RTC_DCHECK(generated_fec_packets_.empty());
 
-  if (media_packets_.empty()) {
+  {
     MutexLock lock(&mutex_);
     if (pending_params_) {
       current_params_ = *pending_params_;
@@ -123,13 +123,12 @@
         min_num_media_packets_ = 1;
       }
     }
-
-    keyframe_in_process_ = packet.is_key_frame();
   }
-  RTC_DCHECK_EQ(packet.is_key_frame(), keyframe_in_process_);
 
-  bool complete_frame = false;
-  const bool marker_bit = packet.Marker();
+  if (packet.is_key_frame()) {
+    media_contains_keyframe_ = true;
+  }
+  const bool complete_frame = packet.Marker();
   if (media_packets_.size() < kUlpfecMaxMediaPackets) {
     // Our packet masks can only protect up to |kUlpfecMaxMediaPackets| packets.
     auto fec_packet = std::make_unique<ForwardErrorCorrection::Packet>();
@@ -142,9 +141,8 @@
     last_media_packet_ = packet;
   }
 
-  if (marker_bit) {
+  if (complete_frame) {
     ++num_protected_frames_;
-    complete_frame = true;
   }
 
   auto params = CurrentParams();
@@ -154,7 +152,7 @@
   // less than |kMaxExcessOverhead|, and
   // (2) at least |min_num_media_packets_| media packets is reached.
   if (complete_frame &&
-      (num_protected_frames_ == params.max_fec_frames ||
+      (num_protected_frames_ >= params.max_fec_frames ||
        (ExcessOverheadBelowMax() && MinimumMediaPacketsReached()))) {
     // We are not using Unequal Protection feature of the parity erasure code.
     constexpr int kNumImportantPackets = 0;
@@ -190,8 +188,8 @@
 
 const FecProtectionParams& UlpfecGenerator::CurrentParams() const {
   RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
-  return keyframe_in_process_ ? current_params_.keyframe_params
-                              : current_params_.delta_params;
+  return media_contains_keyframe_ ? current_params_.keyframe_params
+                                  : current_params_.delta_params;
 }
 
 size_t UlpfecGenerator::MaxPacketOverhead() const {
@@ -265,6 +263,7 @@
   last_media_packet_.reset();
   generated_fec_packets_.clear();
   num_protected_frames_ = 0;
+  media_contains_keyframe_ = false;
 }
 
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/ulpfec_generator.h b/modules/rtp_rtcp/source/ulpfec_generator.h
index 32ddc6c..934a1d5 100644
--- a/modules/rtp_rtcp/source/ulpfec_generator.h
+++ b/modules/rtp_rtcp/source/ulpfec_generator.h
@@ -59,6 +59,9 @@
 
   absl::optional<RtpState> GetRtpState() override { return absl::nullopt; }
 
+  // Currently used protection params.
+  const FecProtectionParams& CurrentParams() const;
+
  private:
   struct Params {
     Params();
@@ -90,8 +93,6 @@
   // (e.g. (2k,2m) vs (k,m)) are generally more effective at recovering losses.
   bool MinimumMediaPacketsReached() const;
 
-  const FecProtectionParams& CurrentParams() const;
-
   void ResetState();
 
   const int red_payload_type_;
@@ -110,7 +111,7 @@
   int num_protected_frames_ RTC_GUARDED_BY(race_checker_);
   int min_num_media_packets_ RTC_GUARDED_BY(race_checker_);
   Params current_params_ RTC_GUARDED_BY(race_checker_);
-  bool keyframe_in_process_ RTC_GUARDED_BY(race_checker_);
+  bool media_contains_keyframe_ RTC_GUARDED_BY(race_checker_);
 
   mutable Mutex mutex_;
   absl::optional<Params> pending_params_ RTC_GUARDED_BY(mutex_);
diff --git a/modules/rtp_rtcp/source/ulpfec_generator_unittest.cc b/modules/rtp_rtcp/source/ulpfec_generator_unittest.cc
index db005dd..c07e81d 100644
--- a/modules/rtp_rtcp/source/ulpfec_generator_unittest.cc
+++ b/modules/rtp_rtcp/source/ulpfec_generator_unittest.cc
@@ -217,4 +217,57 @@
   }
 }
 
+TEST_F(UlpfecGeneratorTest, UpdatesProtectionParameters) {
+  const FecProtectionParams kKeyFrameParams = {25, /*max_fec_frames=*/2,
+                                               kFecMaskRandom};
+  const FecProtectionParams kDeltaFrameParams = {25, /*max_fec_frames=*/5,
+                                                 kFecMaskRandom};
+
+  ulpfec_generator_.SetProtectionParameters(kDeltaFrameParams, kKeyFrameParams);
+
+  // No params applied yet.
+  EXPECT_EQ(ulpfec_generator_.CurrentParams().max_fec_frames, 0);
+
+  // Helper function to add a single-packet frame market as either key-frame
+  // or delta-frame.
+  auto add_frame = [&](bool is_keyframe) {
+    packet_generator_.NewFrame(1);
+    std::unique_ptr<AugmentedPacket> packet =
+        packet_generator_.NextPacket(0, 10);
+    RtpPacketToSend rtp_packet(nullptr);
+    EXPECT_TRUE(rtp_packet.Parse(packet->data.data(), packet->data.size()));
+    rtp_packet.set_is_key_frame(is_keyframe);
+    ulpfec_generator_.AddPacketAndGenerateFec(rtp_packet);
+  };
+
+  // Add key-frame, keyframe params should apply, no FEC generated yet.
+  add_frame(true);
+  EXPECT_EQ(ulpfec_generator_.CurrentParams().max_fec_frames, 2);
+  EXPECT_TRUE(ulpfec_generator_.GetFecPackets().empty());
+
+  // Add delta-frame, generated FEC packet. Params will not be updated until
+  // next added packet though.
+  add_frame(false);
+  EXPECT_EQ(ulpfec_generator_.CurrentParams().max_fec_frames, 2);
+  EXPECT_FALSE(ulpfec_generator_.GetFecPackets().empty());
+
+  // Add delta-frame, now params get updated.
+  add_frame(false);
+  EXPECT_EQ(ulpfec_generator_.CurrentParams().max_fec_frames, 5);
+  EXPECT_TRUE(ulpfec_generator_.GetFecPackets().empty());
+
+  // Add yet another delta-frame.
+  add_frame(false);
+  EXPECT_EQ(ulpfec_generator_.CurrentParams().max_fec_frames, 5);
+  EXPECT_TRUE(ulpfec_generator_.GetFecPackets().empty());
+
+  // Add key-frame, params immediately switch to key-frame ones. The two
+  // buffered frames plus the key-frame is protected and fec emitted,
+  // even though the frame count is technically over the keyframe frame count
+  // threshold.
+  add_frame(true);
+  EXPECT_EQ(ulpfec_generator_.CurrentParams().max_fec_frames, 2);
+  EXPECT_FALSE(ulpfec_generator_.GetFecPackets().empty());
+}
+
 }  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc b/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc
index 261c8f7..2aebbea 100644
--- a/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc
+++ b/modules/rtp_rtcp/source/ulpfec_header_reader_writer.cc
@@ -57,7 +57,7 @@
 
 bool UlpfecHeaderReader::ReadFecHeader(
     ForwardErrorCorrection::ReceivedFecPacket* fec_packet) const {
-  uint8_t* data = fec_packet->pkt->data.data();
+  uint8_t* data = fec_packet->pkt->data.MutableData();
   if (fec_packet->pkt->data.size() < kPacketMaskOffset) {
     return false;  // Truncated packet.
   }
@@ -108,7 +108,7 @@
     const uint8_t* packet_mask,
     size_t packet_mask_size,
     ForwardErrorCorrection::Packet* fec_packet) const {
-  uint8_t* data = fec_packet->data.data();
+  uint8_t* data = fec_packet->data.MutableData();
   // Set E bit to zero.
   data[0] &= 0x7f;
   // Set L bit based on packet mask size. (Note that the packet mask
diff --git a/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc b/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc
index 19da2c8..a190a54 100644
--- a/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc
+++ b/modules/rtp_rtcp/source/ulpfec_header_reader_writer_unittest.cc
@@ -53,8 +53,9 @@
   UlpfecHeaderWriter writer;
   std::unique_ptr<Packet> written_packet(new Packet());
   written_packet->data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet->data.MutableData();
   for (size_t i = 0; i < written_packet->data.size(); ++i) {
-    written_packet->data[i] = i;  // Actual content doesn't matter.
+    data[i] = i;  // Actual content doesn't matter.
   }
   writer.FinalizeFecHeader(kMediaSsrc, kMediaStartSeqNum, packet_mask,
                            packet_mask_size, written_packet.get());
@@ -85,7 +86,8 @@
   EXPECT_EQ(written_packet.data.size() - expected_fec_header_size,
             read_packet.protection_length);
   EXPECT_EQ(0, memcmp(expected_packet_mask,
-                      &read_packet.pkt->data[read_packet.packet_mask_offset],
+                      read_packet.pkt->data.MutableData() +
+                          read_packet.packet_mask_offset,
                       read_packet.packet_mask_size));
   // Verify that the call to ReadFecHeader did not tamper with the payload.
   EXPECT_EQ(0, memcmp(written_packet.data.data() + expected_fec_header_size,
@@ -147,8 +149,9 @@
   auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd);
   Packet written_packet;
   written_packet.data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet.data.MutableData();
   for (size_t i = 0; i < written_packet.data.size(); ++i) {
-    written_packet.data[i] = i;
+    data[i] = i;
   }
 
   UlpfecHeaderWriter writer;
@@ -171,8 +174,9 @@
   auto packet_mask = GeneratePacketMask(packet_mask_size, 0xabcd);
   Packet written_packet;
   written_packet.data.SetSize(kMediaPacketLength);
+  uint8_t* data = written_packet.data.MutableData();
   for (size_t i = 0; i < written_packet.data.size(); ++i) {
-    written_packet.data[i] = i;
+    data[i] = i;
   }
 
   UlpfecHeaderWriter writer;
diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
index 26993ca..fee0b9c 100644
--- a/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
+++ b/modules/rtp_rtcp/source/ulpfec_receiver_impl.cc
@@ -135,8 +135,9 @@
     received_packet->pkt->data.SetData(rtp_packet.data(),
                                        rtp_packet.headers_size());
     // Set payload type.
-    received_packet->pkt->data[1] &= 0x80;          // Reset RED payload type.
-    received_packet->pkt->data[1] += payload_type;  // Set media payload type.
+    uint8_t& payload_type_byte = received_packet->pkt->data.MutableData()[1];
+    payload_type_byte &= 0x80;          // Reset RED payload type.
+    payload_type_byte += payload_type;  // Set media payload type.
     // Copy payload data.
     received_packet->pkt->data.AppendData(red_payload.data(),
                                           red_payload.size());
diff --git a/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc b/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc
index 4d6aa3d..9dbaeb8 100644
--- a/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/ulpfec_receiver_unittest.cc
@@ -158,7 +158,7 @@
   std::list<ForwardErrorCorrection::Packet*> fec_packets;
   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
   ByteWriter<uint16_t>::WriteBigEndian(
-      &fec_packets.front()->data[fec_garbage_offset], 0x4711);
+      fec_packets.front()->data.MutableData() + fec_garbage_offset, 0x4711);
 
   // Inject first media packet, then first FEC packet, skipping the second media
   // packet to cause a recovery from the FEC packet.
diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc
index 1378802..e87be03 100644
--- a/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc
+++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_h264.cc
@@ -264,7 +264,7 @@
     uint8_t original_nal_header = fnri | original_nal_type;
     rtp_payload =
         rtp_payload.Slice(kNalHeaderSize, rtp_payload.size() - kNalHeaderSize);
-    rtp_payload[0] = original_nal_header;
+    rtp_payload.MutableData()[0] = original_nal_header;
     parsed_payload->video_payload = std::move(rtp_payload);
   } else {
     parsed_payload->video_payload =
diff --git a/modules/video_coding/codecs/interface/libvpx_interface.cc b/modules/video_coding/codecs/interface/libvpx_interface.cc
new file mode 100644
index 0000000..b24922f
--- /dev/null
+++ b/modules/video_coding/codecs/interface/libvpx_interface.cc
@@ -0,0 +1,373 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_coding/codecs/interface/libvpx_interface.h"
+
+#include <memory>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace {
+class LibvpxFacade : public LibvpxInterface {
+ public:
+  LibvpxFacade() = default;
+  ~LibvpxFacade() override = default;
+
+  vpx_image_t* img_alloc(vpx_image_t* img,
+                         vpx_img_fmt_t fmt,
+                         unsigned int d_w,
+                         unsigned int d_h,
+                         unsigned int align) const override {
+    return ::vpx_img_alloc(img, fmt, d_w, d_h, align);
+  }
+
+  vpx_image_t* img_wrap(vpx_image_t* img,
+                        vpx_img_fmt_t fmt,
+                        unsigned int d_w,
+                        unsigned int d_h,
+                        unsigned int stride_align,
+                        unsigned char* img_data) const override {
+    return ::vpx_img_wrap(img, fmt, d_w, d_h, stride_align, img_data);
+  }
+
+  void img_free(vpx_image_t* img) const override { ::vpx_img_free(img); }
+
+  vpx_codec_err_t codec_enc_config_set(
+      vpx_codec_ctx_t* ctx,
+      const vpx_codec_enc_cfg_t* cfg) const override {
+    return ::vpx_codec_enc_config_set(ctx, cfg);
+  }
+
+  vpx_codec_err_t codec_enc_config_default(vpx_codec_iface_t* iface,
+                                           vpx_codec_enc_cfg_t* cfg,
+                                           unsigned int usage) const override {
+    return ::vpx_codec_enc_config_default(iface, cfg, usage);
+  }
+
+  vpx_codec_err_t codec_enc_init(vpx_codec_ctx_t* ctx,
+                                 vpx_codec_iface_t* iface,
+                                 const vpx_codec_enc_cfg_t* cfg,
+                                 vpx_codec_flags_t flags) const override {
+    return ::vpx_codec_enc_init(ctx, iface, cfg, flags);
+  }
+
+  vpx_codec_err_t codec_enc_init_multi(vpx_codec_ctx_t* ctx,
+                                       vpx_codec_iface_t* iface,
+                                       vpx_codec_enc_cfg_t* cfg,
+                                       int num_enc,
+                                       vpx_codec_flags_t flags,
+                                       vpx_rational_t* dsf) const override {
+    return ::vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf);
+  }
+
+  vpx_codec_err_t codec_destroy(vpx_codec_ctx_t* ctx) const override {
+    return ::vpx_codec_destroy(ctx);
+  }
+
+  // For types related to these parameters, see section
+  // "VP8 encoder control function parameter type" in vpx/vp8cx.h.
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                uint32_t param) const override {
+    // We need an explicit call for each type since vpx_codec_control is a
+    // macro that gets expanded into another call based on the parameter name.
+    switch (ctrl_id) {
+      case VP8E_SET_ENABLEAUTOALTREF:
+        return vpx_codec_control(ctx, VP8E_SET_ENABLEAUTOALTREF, param);
+      case VP8E_SET_NOISE_SENSITIVITY:
+        return vpx_codec_control(ctx, VP8E_SET_NOISE_SENSITIVITY, param);
+      case VP8E_SET_SHARPNESS:
+        return vpx_codec_control(ctx, VP8E_SET_SHARPNESS, param);
+      case VP8E_SET_STATIC_THRESHOLD:
+        return vpx_codec_control(ctx, VP8E_SET_STATIC_THRESHOLD, param);
+      case VP8E_SET_ARNR_MAXFRAMES:
+        return vpx_codec_control(ctx, VP8E_SET_ARNR_MAXFRAMES, param);
+      case VP8E_SET_ARNR_STRENGTH:
+        return vpx_codec_control(ctx, VP8E_SET_ARNR_STRENGTH, param);
+      case VP8E_SET_CQ_LEVEL:
+        return vpx_codec_control(ctx, VP8E_SET_CQ_LEVEL, param);
+      case VP8E_SET_MAX_INTRA_BITRATE_PCT:
+        return vpx_codec_control(ctx, VP8E_SET_MAX_INTRA_BITRATE_PCT, param);
+      case VP9E_SET_MAX_INTER_BITRATE_PCT:
+        return vpx_codec_control(ctx, VP9E_SET_MAX_INTER_BITRATE_PCT, param);
+      case VP8E_SET_GF_CBR_BOOST_PCT:
+        return vpx_codec_control(ctx, VP8E_SET_GF_CBR_BOOST_PCT, param);
+      case VP8E_SET_SCREEN_CONTENT_MODE:
+        return vpx_codec_control(ctx, VP8E_SET_SCREEN_CONTENT_MODE, param);
+      case VP9E_SET_GF_CBR_BOOST_PCT:
+        return vpx_codec_control(ctx, VP9E_SET_GF_CBR_BOOST_PCT, param);
+      case VP9E_SET_LOSSLESS:
+        return vpx_codec_control(ctx, VP9E_SET_LOSSLESS, param);
+      case VP9E_SET_FRAME_PARALLEL_DECODING:
+        return vpx_codec_control(ctx, VP9E_SET_FRAME_PARALLEL_DECODING, param);
+      case VP9E_SET_AQ_MODE:
+        return vpx_codec_control(ctx, VP9E_SET_AQ_MODE, param);
+      case VP9E_SET_FRAME_PERIODIC_BOOST:
+        return vpx_codec_control(ctx, VP9E_SET_FRAME_PERIODIC_BOOST, param);
+      case VP9E_SET_NOISE_SENSITIVITY:
+        return vpx_codec_control(ctx, VP9E_SET_NOISE_SENSITIVITY, param);
+      case VP9E_SET_MIN_GF_INTERVAL:
+        return vpx_codec_control(ctx, VP9E_SET_MIN_GF_INTERVAL, param);
+      case VP9E_SET_MAX_GF_INTERVAL:
+        return vpx_codec_control(ctx, VP9E_SET_MAX_GF_INTERVAL, param);
+      case VP9E_SET_TARGET_LEVEL:
+        return vpx_codec_control(ctx, VP9E_SET_TARGET_LEVEL, param);
+      case VP9E_SET_ROW_MT:
+        return vpx_codec_control(ctx, VP9E_SET_ROW_MT, param);
+      case VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST:
+        return vpx_codec_control(ctx, VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST,
+                                 param);
+      case VP9E_SET_SVC_INTER_LAYER_PRED:
+        return vpx_codec_control(ctx, VP9E_SET_SVC_INTER_LAYER_PRED, param);
+      case VP9E_SET_SVC_GF_TEMPORAL_REF:
+        return vpx_codec_control(ctx, VP9E_SET_SVC_GF_TEMPORAL_REF, param);
+      case VP9E_SET_POSTENCODE_DROP:
+        return vpx_codec_control(ctx, VP9E_SET_POSTENCODE_DROP, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                int param) const override {
+    switch (ctrl_id) {
+      case VP8E_SET_FRAME_FLAGS:
+        return vpx_codec_control(ctx, VP8E_SET_FRAME_FLAGS, param);
+      case VP8E_SET_TEMPORAL_LAYER_ID:
+        return vpx_codec_control(ctx, VP8E_SET_TEMPORAL_LAYER_ID, param);
+      case VP9E_SET_SVC:
+        return vpx_codec_control(ctx, VP9E_SET_SVC, param);
+      case VP8E_SET_CPUUSED:
+        return vpx_codec_control(ctx, VP8E_SET_CPUUSED, param);
+      case VP8E_SET_TOKEN_PARTITIONS:
+        return vpx_codec_control(ctx, VP8E_SET_TOKEN_PARTITIONS, param);
+      case VP8E_SET_TUNING:
+        return vpx_codec_control(ctx, VP8E_SET_TUNING, param);
+      case VP9E_SET_TILE_COLUMNS:
+        return vpx_codec_control(ctx, VP9E_SET_TILE_COLUMNS, param);
+      case VP9E_SET_TILE_ROWS:
+        return vpx_codec_control(ctx, VP9E_SET_TILE_ROWS, param);
+      case VP9E_SET_TPL:
+        return vpx_codec_control(ctx, VP9E_SET_TPL, param);
+      case VP9E_SET_ALT_REF_AQ:
+        return vpx_codec_control(ctx, VP9E_SET_ALT_REF_AQ, param);
+      case VP9E_SET_TUNE_CONTENT:
+        return vpx_codec_control(ctx, VP9E_SET_TUNE_CONTENT, param);
+      case VP9E_SET_COLOR_SPACE:
+        return vpx_codec_control(ctx, VP9E_SET_COLOR_SPACE, param);
+      case VP9E_SET_COLOR_RANGE:
+        return vpx_codec_control(ctx, VP9E_SET_COLOR_RANGE, param);
+      case VP9E_SET_DELTA_Q_UV:
+        return vpx_codec_control(ctx, VP9E_SET_DELTA_Q_UV, param);
+      case VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR:
+        return vpx_codec_control(ctx, VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR,
+                                 param);
+      case VP9E_SET_DISABLE_LOOPFILTER:
+        return vpx_codec_control(ctx, VP9E_SET_DISABLE_LOOPFILTER, param);
+
+      default:
+        if (param >= 0) {
+          // Might be intended for uint32_t but int literal used, try fallback.
+          return codec_control(ctx, ctrl_id, static_cast<uint32_t>(param));
+        }
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                int* param) const override {
+    switch (ctrl_id) {
+      case VP8E_GET_LAST_QUANTIZER:
+        return vpx_codec_control(ctx, VP8E_GET_LAST_QUANTIZER, param);
+      case VP8E_GET_LAST_QUANTIZER_64:
+        return vpx_codec_control(ctx, VP8E_GET_LAST_QUANTIZER_64, param);
+      case VP9E_SET_RENDER_SIZE:
+        return vpx_codec_control(ctx, VP9E_SET_RENDER_SIZE, param);
+      case VP9E_GET_LEVEL:
+        return vpx_codec_control(ctx, VP9E_GET_LEVEL, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_roi_map* param) const override {
+    switch (ctrl_id) {
+      case VP8E_SET_ROI_MAP:
+        return vpx_codec_control(ctx, VP8E_SET_ROI_MAP, param);
+      case VP9E_SET_ROI_MAP:
+        return vpx_codec_control(ctx, VP9E_SET_ROI_MAP, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_active_map* param) const override {
+    switch (ctrl_id) {
+      case VP8E_SET_ACTIVEMAP:
+        return vpx_codec_control(ctx, VP8E_SET_ACTIVEMAP, param);
+      case VP9E_GET_ACTIVEMAP:
+        return vpx_codec_control(ctx, VP8E_SET_ACTIVEMAP, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_scaling_mode* param) const override {
+    switch (ctrl_id) {
+      case VP8E_SET_SCALEMODE:
+        return vpx_codec_control(ctx, VP8E_SET_SCALEMODE, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_svc_extra_cfg_t* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_SVC_PARAMETERS:
+        return vpx_codec_control_(ctx, VP9E_SET_SVC_PARAMETERS, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_svc_frame_drop_t* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_SVC_FRAME_DROP_LAYER:
+        return vpx_codec_control_(ctx, VP9E_SET_SVC_FRAME_DROP_LAYER, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                void* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_SVC_PARAMETERS:
+        return vpx_codec_control_(ctx, VP9E_SET_SVC_PARAMETERS, param);
+      case VP9E_REGISTER_CX_CALLBACK:
+        return vpx_codec_control_(ctx, VP9E_REGISTER_CX_CALLBACK, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_svc_layer_id_t* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_SVC_LAYER_ID:
+        return vpx_codec_control_(ctx, VP9E_SET_SVC_LAYER_ID, param);
+      case VP9E_GET_SVC_LAYER_ID:
+        return vpx_codec_control_(ctx, VP9E_GET_SVC_LAYER_ID, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(
+      vpx_codec_ctx_t* ctx,
+      vp8e_enc_control_id ctrl_id,
+      vpx_svc_ref_frame_config_t* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_SVC_REF_FRAME_CONFIG:
+        return vpx_codec_control_(ctx, VP9E_SET_SVC_REF_FRAME_CONFIG, param);
+      case VP9E_GET_SVC_REF_FRAME_CONFIG:
+        return vpx_codec_control_(ctx, VP9E_GET_SVC_REF_FRAME_CONFIG, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(
+      vpx_codec_ctx_t* ctx,
+      vp8e_enc_control_id ctrl_id,
+      vpx_svc_spatial_layer_sync_t* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_SVC_SPATIAL_LAYER_SYNC:
+        return vpx_codec_control_(ctx, VP9E_SET_SVC_SPATIAL_LAYER_SYNC, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                vp8e_enc_control_id ctrl_id,
+                                vpx_rc_funcs_t* param) const override {
+    switch (ctrl_id) {
+      case VP9E_SET_EXTERNAL_RATE_CONTROL:
+        return vpx_codec_control_(ctx, VP9E_SET_EXTERNAL_RATE_CONTROL, param);
+      default:
+        RTC_NOTREACHED() << "Unsupported libvpx ctrl_id: " << ctrl_id;
+    }
+    return VPX_CODEC_ERROR;
+  }
+
+  vpx_codec_err_t codec_encode(vpx_codec_ctx_t* ctx,
+                               const vpx_image_t* img,
+                               vpx_codec_pts_t pts,
+                               uint64_t duration,
+                               vpx_enc_frame_flags_t flags,
+                               uint64_t deadline) const override {
+    return ::vpx_codec_encode(ctx, img, pts, duration, flags, deadline);
+  }
+
+  const vpx_codec_cx_pkt_t* codec_get_cx_data(
+      vpx_codec_ctx_t* ctx,
+      vpx_codec_iter_t* iter) const override {
+    return ::vpx_codec_get_cx_data(ctx, iter);
+  }
+
+  const char* codec_error_detail(vpx_codec_ctx_t* ctx) const override {
+    return ::vpx_codec_error_detail(ctx);
+  }
+
+  const char* codec_error(vpx_codec_ctx_t* ctx) const override {
+    return ::vpx_codec_error(ctx);
+  }
+
+  const char* codec_err_to_string(vpx_codec_err_t err) const override {
+    return ::vpx_codec_err_to_string(err);
+  }
+};
+
+}  // namespace
+
+std::unique_ptr<LibvpxInterface> LibvpxInterface::Create() {
+  return std::make_unique<LibvpxFacade>();
+}
+
+}  // namespace webrtc
diff --git a/modules/video_coding/codecs/interface/libvpx_interface.h b/modules/video_coding/codecs/interface/libvpx_interface.h
new file mode 100644
index 0000000..3dea24d
--- /dev/null
+++ b/modules/video_coding/codecs/interface/libvpx_interface.h
@@ -0,0 +1,128 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CODING_CODECS_INTERFACE_LIBVPX_INTERFACE_H_
+#define MODULES_VIDEO_CODING_CODECS_INTERFACE_LIBVPX_INTERFACE_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_image.h"
+
+namespace webrtc {
+
+// This interface is a proxy to the static libvpx functions, so that they
+// can be mocked for testing. Currently supports VP8 encoder functions.
+// TODO(sprang): Extend this to VP8 decoder and VP9 encoder/decoder too.
+class LibvpxInterface {
+ public:
+  LibvpxInterface() = default;
+  virtual ~LibvpxInterface() = default;
+
+  virtual vpx_image_t* img_alloc(vpx_image_t* img,
+                                 vpx_img_fmt_t fmt,
+                                 unsigned int d_w,
+                                 unsigned int d_h,
+                                 unsigned int align) const = 0;
+  virtual vpx_image_t* img_wrap(vpx_image_t* img,
+                                vpx_img_fmt_t fmt,
+                                unsigned int d_w,
+                                unsigned int d_h,
+                                unsigned int stride_align,
+                                unsigned char* img_data) const = 0;
+  virtual void img_free(vpx_image_t* img) const = 0;
+
+  virtual vpx_codec_err_t codec_enc_config_set(
+      vpx_codec_ctx_t* ctx,
+      const vpx_codec_enc_cfg_t* cfg) const = 0;
+  virtual vpx_codec_err_t codec_enc_config_default(
+      vpx_codec_iface_t* iface,
+      vpx_codec_enc_cfg_t* cfg,
+      unsigned int usage) const = 0;
+
+  virtual vpx_codec_err_t codec_enc_init(vpx_codec_ctx_t* ctx,
+                                         vpx_codec_iface_t* iface,
+                                         const vpx_codec_enc_cfg_t* cfg,
+                                         vpx_codec_flags_t flags) const = 0;
+  virtual vpx_codec_err_t codec_enc_init_multi(vpx_codec_ctx_t* ctx,
+                                               vpx_codec_iface_t* iface,
+                                               vpx_codec_enc_cfg_t* cfg,
+                                               int num_enc,
+                                               vpx_codec_flags_t flags,
+                                               vpx_rational_t* dsf) const = 0;
+  virtual vpx_codec_err_t codec_destroy(vpx_codec_ctx_t* ctx) const = 0;
+
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        uint32_t param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        int param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        int* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_roi_map* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_active_map* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_scaling_mode* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_svc_extra_cfg_t* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_svc_frame_drop_t* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        void* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_svc_layer_id_t* param) const = 0;
+  virtual vpx_codec_err_t codec_control(
+      vpx_codec_ctx_t* ctx,
+      vp8e_enc_control_id ctrl_id,
+      vpx_svc_ref_frame_config_t* param) const = 0;
+  virtual vpx_codec_err_t codec_control(
+      vpx_codec_ctx_t* ctx,
+      vp8e_enc_control_id ctrl_id,
+      vpx_svc_spatial_layer_sync_t* param) const = 0;
+  virtual vpx_codec_err_t codec_control(vpx_codec_ctx_t* ctx,
+                                        vp8e_enc_control_id ctrl_id,
+                                        vpx_rc_funcs_t* param) const = 0;
+  virtual vpx_codec_err_t codec_encode(vpx_codec_ctx_t* ctx,
+                                       const vpx_image_t* img,
+                                       vpx_codec_pts_t pts,
+                                       uint64_t duration,
+                                       vpx_enc_frame_flags_t flags,
+                                       uint64_t deadline) const = 0;
+
+  virtual const vpx_codec_cx_pkt_t* codec_get_cx_data(
+      vpx_codec_ctx_t* ctx,
+      vpx_codec_iter_t* iter) const = 0;
+
+  virtual const char* codec_error_detail(vpx_codec_ctx_t* ctx) const = 0;
+  virtual const char* codec_error(vpx_codec_ctx_t* ctx) const = 0;
+  virtual const char* codec_err_to_string(vpx_codec_err_t err) const = 0;
+
+  // Returns interface wrapping the actual libvpx functions.
+  static std::unique_ptr<LibvpxInterface> Create();
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CODING_CODECS_INTERFACE_LIBVPX_INTERFACE_H_
diff --git a/modules/video_coding/codecs/interface/mock_libvpx_interface.h b/modules/video_coding/codecs/interface/mock_libvpx_interface.h
new file mode 100644
index 0000000..6dfe733
--- /dev/null
+++ b/modules/video_coding/codecs/interface/mock_libvpx_interface.h
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef MODULES_VIDEO_CODING_CODECS_INTERFACE_MOCK_LIBVPX_INTERFACE_H_
+#define MODULES_VIDEO_CODING_CODECS_INTERFACE_MOCK_LIBVPX_INTERFACE_H_
+
+#include "modules/video_coding/codecs/interface/libvpx_interface.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+class MockLibvpxInterface : public LibvpxInterface {
+ public:
+  MOCK_METHOD(
+      vpx_image_t*,
+      img_alloc,
+      (vpx_image_t*, vpx_img_fmt_t, unsigned int, unsigned int, unsigned int),
+      (const, override));
+  MOCK_METHOD(vpx_image_t*,
+              img_wrap,
+              (vpx_image_t*,
+               vpx_img_fmt_t,
+               unsigned int,
+               unsigned int,
+               unsigned int,
+               unsigned char*),
+              (const, override));
+  MOCK_METHOD(void, img_free, (vpx_image_t * img), (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_enc_config_set,
+              (vpx_codec_ctx_t*, const vpx_codec_enc_cfg_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_enc_config_default,
+              (vpx_codec_iface_t*, vpx_codec_enc_cfg_t*, unsigned int),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_enc_init,
+              (vpx_codec_ctx_t*,
+               vpx_codec_iface_t*,
+               const vpx_codec_enc_cfg_t*,
+               vpx_codec_flags_t),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_enc_init_multi,
+              (vpx_codec_ctx_t*,
+               vpx_codec_iface_t*,
+               vpx_codec_enc_cfg_t*,
+               int,
+               vpx_codec_flags_t,
+               vpx_rational_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_destroy,
+              (vpx_codec_ctx_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, uint32_t),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, int),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, int*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_roi_map*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_active_map*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_scaling_mode*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_svc_extra_cfg_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_svc_frame_drop_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, void*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_svc_layer_id_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*,
+               vp8e_enc_control_id,
+               vpx_svc_ref_frame_config_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*,
+               vp8e_enc_control_id,
+               vpx_svc_spatial_layer_sync_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_control,
+              (vpx_codec_ctx_t*, vp8e_enc_control_id, vpx_rc_funcs_t*),
+              (const, override));
+  MOCK_METHOD(vpx_codec_err_t,
+              codec_encode,
+              (vpx_codec_ctx_t*,
+               const vpx_image_t*,
+               vpx_codec_pts_t,
+               uint64_t,
+               vpx_enc_frame_flags_t,
+               uint64_t),
+              (const, override));
+  MOCK_METHOD(const vpx_codec_cx_pkt_t*,
+              codec_get_cx_data,
+              (vpx_codec_ctx_t*, vpx_codec_iter_t*),
+              (const, override));
+  MOCK_METHOD(const char*,
+              codec_error_detail,
+              (vpx_codec_ctx_t*),
+              (const, override));
+  MOCK_METHOD(const char*, codec_error, (vpx_codec_ctx_t*), (const, override));
+  MOCK_METHOD(const char*,
+              codec_err_to_string,
+              (vpx_codec_err_t),
+              (const, override));
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_VIDEO_CODING_CODECS_INTERFACE_MOCK_LIBVPX_INTERFACE_H_
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 6ee7190..7181c23 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -76,6 +76,7 @@
     "../api:scoped_refptr",
     "synchronization:mutex",
     "system:arch",
+    "system:no_unique_address",
     "system:rtc_export",
     "system:unused",
     "third_party/base64",
@@ -125,6 +126,8 @@
 
   if (is_win) {
     sources += [
+      "win/create_direct3d_device.cc",
+      "win/create_direct3d_device.h",
       "win/get_activation_factory.cc",
       "win/get_activation_factory.h",
       "win/hstring.cc",
@@ -483,6 +486,7 @@
     ":refcount",
     "../api:scoped_refptr",
     "synchronization:sequence_checker",
+    "system:no_unique_address",
   ]
   absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
@@ -586,6 +590,7 @@
     ":refcount",
     "../api:scoped_refptr",
     "synchronization:sequence_checker",
+    "system:no_unique_address",
   ]
 }
 
@@ -662,6 +667,13 @@
   }
 }
 
+rtc_source_set("async_resolver") {
+  # TODO(bugs.webrtc.org/9987): This build target will soon contain
+  # async_resolver source files (see
+  # https://webrtc-review.googlesource.com/c/src/+/196903).
+  sources = [ "async_resolver.h" ]
+}
+
 rtc_source_set("net_helpers") {
   # TODO(bugs.webrtc.org/9987): This build target will soon contain
   #                             the following files:
@@ -834,6 +846,7 @@
     "synchronization:sequence_checker",
     "system:file_wrapper",
     "system:inline",
+    "system:no_unique_address",
     "system:rtc_export",
     "task_utils:pending_task_safety_flag",
     "task_utils:repeating_task",
@@ -907,12 +920,10 @@
     "openssl.h",
     "openssl_adapter.cc",
     "openssl_adapter.h",
-    "openssl_certificate.cc",
-    "openssl_certificate.h",
     "openssl_digest.cc",
     "openssl_digest.h",
-    "openssl_identity.cc",
-    "openssl_identity.h",
+    "openssl_key_pair.cc",
+    "openssl_key_pair.h",
     "openssl_session_cache.cc",
     "openssl_session_cache.h",
     "openssl_stream_adapter.cc",
@@ -958,6 +969,23 @@
     "unique_id_generator.h",
   ]
 
+  # If we are building the SSL library ourselves, we know it's BoringSSL.
+  if (rtc_build_ssl) {
+    sources += [
+      "boringssl_certificate.cc",
+      "boringssl_certificate.h",
+      "boringssl_identity.cc",
+      "boringssl_identity.h",
+    ]
+  } else {
+    sources += [
+      "openssl_certificate.cc",
+      "openssl_certificate.h",
+      "openssl_identity.cc",
+      "openssl_identity.h",
+    ]
+  }
+
   if (build_with_chromium) {
     include_dirs = [ "../../boringssl/src/include" ]
     public_configs += [ ":rtc_base_chromium_config" ]
diff --git a/rtc_base/OWNERS b/rtc_base/OWNERS
index 107bbcd..ce7968c 100644
--- a/rtc_base/OWNERS
+++ b/rtc_base/OWNERS
@@ -1,10 +1,8 @@
 hta@webrtc.org
 juberti@webrtc.org
-kwiberg@webrtc.org
 mflodman@webrtc.org
-qingsi@webrtc.org
-sergeyu@chromium.org
 tommi@webrtc.org
+mbonadei@webrtc.org
 
 per-file rate_statistics*=sprang@webrtc.org
 per-file rate_statistics*=stefan@webrtc.org
diff --git a/rtc_base/async_resolver.h b/rtc_base/async_resolver.h
new file mode 100644
index 0000000..3c3ad82
--- /dev/null
+++ b/rtc_base/async_resolver.h
@@ -0,0 +1,17 @@
+/*
+ *  Copyright 2008 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_ASYNC_RESOLVER_H_
+#define RTC_BASE_ASYNC_RESOLVER_H_
+
+// Placeholder header for the refactoring in:
+// https://webrtc-review.googlesource.com/c/src/+/196903
+
+#endif  // RTC_BASE_ASYNC_RESOLVER_H_
diff --git a/rtc_base/boringssl_certificate.cc b/rtc_base/boringssl_certificate.cc
new file mode 100644
index 0000000..4e55cf3
--- /dev/null
+++ b/rtc_base/boringssl_certificate.cc
@@ -0,0 +1,410 @@
+/*
+ *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/boringssl_certificate.h"
+
+#if defined(WEBRTC_WIN)
+// Must be included first before openssl headers.
+#include "rtc_base/win32.h"  // NOLINT
+#endif                       // WEBRTC_WIN
+
+#include <openssl/asn1.h>
+#include <openssl/bytestring.h>
+#include <openssl/digest.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/pool.h>
+#include <openssl/rand.h>
+#include <time.h>
+
+#include <cstring>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/helpers.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/openssl_digest.h"
+#include "rtc_base/openssl_key_pair.h"
+#include "rtc_base/openssl_utility.h"
+
+namespace rtc {
+namespace {
+
+// List of OIDs of signature algorithms accepted by WebRTC.
+// Taken from openssl/nid.h.
+static const uint8_t kMD5WithRSA[] = {0x2b, 0x0e, 0x03, 0x02, 0x03};
+static const uint8_t kMD5WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                                0x0d, 0x01, 0x01, 0x04};
+static const uint8_t kECDSAWithSHA1[] = {0x2a, 0x86, 0x48, 0xce,
+                                         0x3d, 0x04, 0x01};
+static const uint8_t kDSAWithSHA1[] = {0x2a, 0x86, 0x48, 0xce,
+                                       0x38, 0x04, 0x03};
+static const uint8_t kDSAWithSHA1_2[] = {0x2b, 0x0e, 0x03, 0x02, 0x1b};
+static const uint8_t kSHA1WithRSA[] = {0x2b, 0x0e, 0x03, 0x02, 0x1d};
+static const uint8_t kSHA1WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                                 0x0d, 0x01, 0x01, 0x05};
+static const uint8_t kECDSAWithSHA224[] = {0x2a, 0x86, 0x48, 0xce,
+                                           0x3d, 0x04, 0x03, 0x01};
+static const uint8_t kSHA224WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                                   0x0d, 0x01, 0x01, 0x0e};
+static const uint8_t kDSAWithSHA224[] = {0x60, 0x86, 0x48, 0x01, 0x65,
+                                         0x03, 0x04, 0x03, 0x01};
+static const uint8_t kECDSAWithSHA256[] = {0x2a, 0x86, 0x48, 0xce,
+                                           0x3d, 0x04, 0x03, 0x02};
+static const uint8_t kSHA256WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                                   0x0d, 0x01, 0x01, 0x0b};
+static const uint8_t kDSAWithSHA256[] = {0x60, 0x86, 0x48, 0x01, 0x65,
+                                         0x03, 0x04, 0x03, 0x02};
+static const uint8_t kECDSAWithSHA384[] = {0x2a, 0x86, 0x48, 0xce,
+                                           0x3d, 0x04, 0x03, 0x03};
+static const uint8_t kSHA384WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                                   0x0d, 0x01, 0x01, 0x0c};
+static const uint8_t kECDSAWithSHA512[] = {0x2a, 0x86, 0x48, 0xce,
+                                           0x3d, 0x04, 0x03, 0x04};
+static const uint8_t kSHA512WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                                   0x0d, 0x01, 0x01, 0x0d};
+
+#if !defined(NDEBUG)
+// Print a certificate to the log, for debugging.
+static void PrintCert(BoringSSLCertificate* cert) {
+  // Since we're using CRYPTO_BUFFER, we can't use X509_print_ex, so we'll just
+  // print the PEM string.
+  RTC_DLOG(LS_VERBOSE) << "PEM representation of certificate:\n"
+                       << cert->ToPEMString();
+}
+#endif
+
+bool AddSHA256SignatureAlgorithm(CBB* cbb, KeyType key_type) {
+  // An AlgorithmIdentifier is described in RFC 5280, 4.1.1.2.
+  CBB sequence, oid, params;
+  if (!CBB_add_asn1(cbb, &sequence, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&sequence, &oid, CBS_ASN1_OBJECT)) {
+    return false;
+  }
+
+  switch (key_type) {
+    case KT_RSA:
+      if (!CBB_add_bytes(&oid, kSHA256WithRSAEncryption,
+                         sizeof(kSHA256WithRSAEncryption)) ||
+          !CBB_add_asn1(&sequence, &params, CBS_ASN1_NULL)) {
+        return false;
+      }
+      break;
+    case KT_ECDSA:
+      if (!CBB_add_bytes(&oid, kECDSAWithSHA256, sizeof(kECDSAWithSHA256))) {
+        return false;
+      }
+      break;
+    default:
+      RTC_NOTREACHED();
+      return false;
+  }
+  if (!CBB_flush(cbb)) {
+    return false;
+  }
+  return true;
+}
+
+// Adds an X.509 Common Name to |cbb|.
+bool AddCommonName(CBB* cbb, const std::string& common_name) {
+  // See RFC 4519.
+  static const uint8_t kCommonName[] = {0x55, 0x04, 0x03};
+
+  if (common_name.empty()) {
+    RTC_LOG(LS_ERROR) << "Common name cannot be empty.";
+    return false;
+  }
+
+  // See RFC 5280, section 4.1.2.4.
+  CBB rdns;
+  if (!CBB_add_asn1(cbb, &rdns, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+
+  CBB rdn, attr, type, value;
+  if (!CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET) ||
+      !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&type, kCommonName, sizeof(kCommonName)) ||
+      !CBB_add_asn1(&attr, &value, CBS_ASN1_UTF8STRING) ||
+      !CBB_add_bytes(&value,
+                     reinterpret_cast<const uint8_t*>(common_name.c_str()),
+                     common_name.size()) ||
+      !CBB_flush(cbb)) {
+    return false;
+  }
+
+  return true;
+}
+
+bool AddTime(CBB* cbb, time_t time) {
+  bssl::UniquePtr<ASN1_TIME> asn1_time(ASN1_TIME_new());
+  if (!asn1_time) {
+    return false;
+  }
+
+  if (!ASN1_TIME_set(asn1_time.get(), time)) {
+    return false;
+  }
+
+  unsigned tag;
+  switch (asn1_time->type) {
+    case V_ASN1_UTCTIME:
+      tag = CBS_ASN1_UTCTIME;
+      break;
+    case V_ASN1_GENERALIZEDTIME:
+      tag = CBS_ASN1_GENERALIZEDTIME;
+      break;
+    default:
+      return false;
+  }
+
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, tag) ||
+      !CBB_add_bytes(&child, asn1_time->data, asn1_time->length) ||
+      !CBB_flush(cbb)) {
+    return false;
+  }
+
+  return true;
+}
+
+// Generate a self-signed certificate, with the public key from the
+// given key pair. Caller is responsible for freeing the returned object.
+static bssl::UniquePtr<CRYPTO_BUFFER> MakeCertificate(
+    EVP_PKEY* pkey,
+    const SSLIdentityParams& params) {
+  RTC_LOG(LS_INFO) << "Making certificate for " << params.common_name;
+
+  // See RFC 5280, section 4.1. First, construct the TBSCertificate.
+  bssl::ScopedCBB cbb;
+  CBB tbs_cert, version, validity;
+  uint8_t* tbs_cert_bytes;
+  size_t tbs_cert_len;
+  uint64_t serial_number;
+  if (!CBB_init(cbb.get(), 64) ||
+      !CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&tbs_cert, &version,
+                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+      !CBB_add_asn1_uint64(&version, 2) ||
+      !RAND_bytes(reinterpret_cast<uint8_t*>(&serial_number),
+                  sizeof(serial_number)) ||
+      !CBB_add_asn1_uint64(&tbs_cert, serial_number) ||
+      !AddSHA256SignatureAlgorithm(&tbs_cert, params.key_params.type()) ||
+      !AddCommonName(&tbs_cert, params.common_name) ||  // issuer
+      !CBB_add_asn1(&tbs_cert, &validity, CBS_ASN1_SEQUENCE) ||
+      !AddTime(&validity, params.not_before) ||
+      !AddTime(&validity, params.not_after) ||
+      !AddCommonName(&tbs_cert, params.common_name) ||  // subject
+      !EVP_marshal_public_key(&tbs_cert, pkey) ||       // subjectPublicKeyInfo
+      !CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len)) {
+    return nullptr;
+  }
+
+  bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(tbs_cert_bytes);
+
+  // Sign the TBSCertificate and write the entire certificate.
+  CBB cert, signature;
+  bssl::ScopedEVP_MD_CTX ctx;
+  uint8_t* sig_out;
+  size_t sig_len;
+  uint8_t* cert_bytes;
+  size_t cert_len;
+  if (!CBB_init(cbb.get(), tbs_cert_len) ||
+      !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_bytes(&cert, tbs_cert_bytes, tbs_cert_len) ||
+      !AddSHA256SignatureAlgorithm(&cert, params.key_params.type()) ||
+      !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) ||
+      !CBB_add_u8(&signature, 0 /* no unused bits */) ||
+      !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr, pkey) ||
+      // Compute the maximum signature length.
+      !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes,
+                      tbs_cert_len) ||
+      !CBB_reserve(&signature, &sig_out, sig_len) ||
+      // Actually sign the TBSCertificate.
+      !EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes,
+                      tbs_cert_len) ||
+      !CBB_did_write(&signature, sig_len) ||
+      !CBB_finish(cbb.get(), &cert_bytes, &cert_len)) {
+    return nullptr;
+  }
+  bssl::UniquePtr<uint8_t> delete_cert_bytes(cert_bytes);
+
+  RTC_LOG(LS_INFO) << "Returning certificate";
+  return bssl::UniquePtr<CRYPTO_BUFFER>(
+      CRYPTO_BUFFER_new(cert_bytes, cert_len, openssl::GetBufferPool()));
+}
+
+}  // namespace
+
+BoringSSLCertificate::BoringSSLCertificate(
+    bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer)
+    : cert_buffer_(std::move(cert_buffer)) {
+  RTC_DCHECK(cert_buffer_ != nullptr);
+}
+
+std::unique_ptr<BoringSSLCertificate> BoringSSLCertificate::Generate(
+    OpenSSLKeyPair* key_pair,
+    const SSLIdentityParams& params) {
+  SSLIdentityParams actual_params(params);
+  if (actual_params.common_name.empty()) {
+    // Use a random string, arbitrarily 8 chars long.
+    actual_params.common_name = CreateRandomString(8);
+  }
+  bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer =
+      MakeCertificate(key_pair->pkey(), actual_params);
+  if (!cert_buffer) {
+    openssl::LogSSLErrors("Generating certificate");
+    return nullptr;
+  }
+  auto ret = std::make_unique<BoringSSLCertificate>(std::move(cert_buffer));
+#if !defined(NDEBUG)
+  PrintCert(ret.get());
+#endif
+  return ret;
+}
+
+std::unique_ptr<BoringSSLCertificate> BoringSSLCertificate::FromPEMString(
+    const std::string& pem_string) {
+  std::string der;
+  if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) {
+    return nullptr;
+  }
+  bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer(
+      CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(der.c_str()),
+                        der.length(), openssl::GetBufferPool()));
+  if (!cert_buffer) {
+    return nullptr;
+  }
+  return std::make_unique<BoringSSLCertificate>(std::move(cert_buffer));
+}
+
+#define OID_MATCHES(oid, oid_other)      \
+  (CBS_len(&oid) == sizeof(oid_other) && \
+  0 == memcmp(CBS_data(&oid), oid_other, sizeof(oid_other)))
+
+bool BoringSSLCertificate::GetSignatureDigestAlgorithm(
+    std::string* algorithm) const {
+  CBS oid;
+  if (!openssl::ParseCertificate(cert_buffer_.get(), &oid, nullptr)) {
+    RTC_LOG(LS_ERROR) << "Failed to parse certificate.";
+    return false;
+  }
+  if (OID_MATCHES(oid, kMD5WithRSA) ||
+      OID_MATCHES(oid, kMD5WithRSAEncryption)) {
+    *algorithm = DIGEST_MD5;
+    return true;
+  }
+  if (OID_MATCHES(oid, kECDSAWithSHA1) || OID_MATCHES(oid, kDSAWithSHA1) ||
+      OID_MATCHES(oid, kDSAWithSHA1_2) || OID_MATCHES(oid, kSHA1WithRSA) ||
+      OID_MATCHES(oid, kSHA1WithRSAEncryption)) {
+    *algorithm = DIGEST_SHA_1;
+    return true;
+  }
+  if (OID_MATCHES(oid, kECDSAWithSHA224) ||
+      OID_MATCHES(oid, kSHA224WithRSAEncryption) ||
+      OID_MATCHES(oid, kDSAWithSHA224)) {
+    *algorithm = DIGEST_SHA_224;
+    return true;
+  }
+  if (OID_MATCHES(oid, kECDSAWithSHA256) ||
+      OID_MATCHES(oid, kSHA256WithRSAEncryption) ||
+      OID_MATCHES(oid, kDSAWithSHA256)) {
+    *algorithm = DIGEST_SHA_256;
+    return true;
+  }
+  if (OID_MATCHES(oid, kECDSAWithSHA384) ||
+      OID_MATCHES(oid, kSHA384WithRSAEncryption)) {
+    *algorithm = DIGEST_SHA_384;
+    return true;
+  }
+  if (OID_MATCHES(oid, kECDSAWithSHA512) ||
+      OID_MATCHES(oid, kSHA512WithRSAEncryption)) {
+    *algorithm = DIGEST_SHA_512;
+    return true;
+  }
+  // Unknown algorithm.  There are several unhandled options that are less
+  // common and more complex.
+  RTC_LOG(LS_ERROR) << "Unknown signature algorithm.";
+  algorithm->clear();
+  return false;
+}
+
+bool BoringSSLCertificate::ComputeDigest(const std::string& algorithm,
+                                         unsigned char* digest,
+                                         size_t size,
+                                         size_t* length) const {
+  return ComputeDigest(cert_buffer_.get(), algorithm, digest, size, length);
+}
+
+bool BoringSSLCertificate::ComputeDigest(const CRYPTO_BUFFER* cert_buffer,
+                                         const std::string& algorithm,
+                                         unsigned char* digest,
+                                         size_t size,
+                                         size_t* length) {
+  const EVP_MD* md = nullptr;
+  unsigned int n = 0;
+  if (!OpenSSLDigest::GetDigestEVP(algorithm, &md)) {
+    return false;
+  }
+  if (size < static_cast<size_t>(EVP_MD_size(md))) {
+    return false;
+  }
+  if (!EVP_Digest(CRYPTO_BUFFER_data(cert_buffer),
+                  CRYPTO_BUFFER_len(cert_buffer), digest, &n, md, nullptr)) {
+    return false;
+  }
+  *length = n;
+  return true;
+}
+
+BoringSSLCertificate::~BoringSSLCertificate() {}
+
+std::unique_ptr<SSLCertificate> BoringSSLCertificate::Clone() const {
+  return std::make_unique<BoringSSLCertificate>(
+      bssl::UpRef(cert_buffer_.get()));
+}
+
+std::string BoringSSLCertificate::ToPEMString() const {
+  return SSLIdentity::DerToPem(kPemTypeCertificate,
+                               CRYPTO_BUFFER_data(cert_buffer_.get()),
+                               CRYPTO_BUFFER_len(cert_buffer_.get()));
+}
+
+void BoringSSLCertificate::ToDER(Buffer* der_buffer) const {
+  der_buffer->SetData(CRYPTO_BUFFER_data(cert_buffer_.get()),
+                      CRYPTO_BUFFER_len(cert_buffer_.get()));
+}
+
+bool BoringSSLCertificate::operator==(const BoringSSLCertificate& other) const {
+  return CRYPTO_BUFFER_len(cert_buffer_.get()) ==
+             CRYPTO_BUFFER_len(other.cert_buffer_.get()) &&
+         0 == memcmp(CRYPTO_BUFFER_data(cert_buffer_.get()),
+                     CRYPTO_BUFFER_data(other.cert_buffer_.get()),
+                     CRYPTO_BUFFER_len(cert_buffer_.get()));
+}
+
+bool BoringSSLCertificate::operator!=(const BoringSSLCertificate& other) const {
+  return !(*this == other);
+}
+
+int64_t BoringSSLCertificate::CertificateExpirationTime() const {
+  int64_t ret;
+  if (!openssl::ParseCertificate(cert_buffer_.get(), nullptr, &ret)) {
+    RTC_LOG(LS_ERROR) << "Failed to parse certificate.";
+    return -1;
+  }
+  return ret;
+}
+
+}  // namespace rtc
diff --git a/rtc_base/boringssl_certificate.h b/rtc_base/boringssl_certificate.h
new file mode 100644
index 0000000..740763d
--- /dev/null
+++ b/rtc_base/boringssl_certificate.h
@@ -0,0 +1,80 @@
+/*
+ *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_BORINGSSL_CERTIFICATE_H_
+#define RTC_BASE_BORINGSSL_CERTIFICATE_H_
+
+#include <openssl/ossl_typ.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "rtc_base/buffer.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
+
+namespace rtc {
+
+class OpenSSLKeyPair;
+
+// BoringSSLCertificate encapsulates a BoringSSL CRYPTO_BUFFER object holding a
+// certificate, which is also reference counted inside the BoringSSL library.
+// This offers binary size and memory improvements over the OpenSSL X509
+// object.
+class BoringSSLCertificate final : public SSLCertificate {
+ public:
+  explicit BoringSSLCertificate(bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer);
+
+  static std::unique_ptr<BoringSSLCertificate> Generate(
+      OpenSSLKeyPair* key_pair,
+      const SSLIdentityParams& params);
+  static std::unique_ptr<BoringSSLCertificate> FromPEMString(
+      const std::string& pem_string);
+
+  ~BoringSSLCertificate() override;
+
+  std::unique_ptr<SSLCertificate> Clone() const override;
+
+  CRYPTO_BUFFER* cert_buffer() const { return cert_buffer_.get(); }
+
+  std::string ToPEMString() const override;
+  void ToDER(Buffer* der_buffer) const override;
+  bool operator==(const BoringSSLCertificate& other) const;
+  bool operator!=(const BoringSSLCertificate& other) const;
+
+  // Compute the digest of the certificate given |algorithm|.
+  bool ComputeDigest(const std::string& algorithm,
+                     unsigned char* digest,
+                     size_t size,
+                     size_t* length) const override;
+
+  // Compute the digest of a certificate as a CRYPTO_BUFFER.
+  static bool ComputeDigest(const CRYPTO_BUFFER* cert_buffer,
+                            const std::string& algorithm,
+                            unsigned char* digest,
+                            size_t size,
+                            size_t* length);
+
+  bool GetSignatureDigestAlgorithm(std::string* algorithm) const override;
+
+  int64_t CertificateExpirationTime() const override;
+
+ private:
+  // A handle to the DER encoded certificate data.
+  bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer_;
+  RTC_DISALLOW_COPY_AND_ASSIGN(BoringSSLCertificate);
+};
+
+}  // namespace rtc
+
+#endif  // RTC_BASE_BORINGSSL_CERTIFICATE_H_
diff --git a/rtc_base/boringssl_identity.cc b/rtc_base/boringssl_identity.cc
new file mode 100644
index 0000000..d22c8ce
--- /dev/null
+++ b/rtc_base/boringssl_identity.cc
@@ -0,0 +1,215 @@
+/*
+ *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/boringssl_identity.h"
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/pool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "absl/memory/memory.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/openssl.h"
+#include "rtc_base/openssl_utility.h"
+
+namespace rtc {
+
+BoringSSLIdentity::BoringSSLIdentity(
+    std::unique_ptr<OpenSSLKeyPair> key_pair,
+    std::unique_ptr<BoringSSLCertificate> certificate)
+    : key_pair_(std::move(key_pair)) {
+  RTC_DCHECK(key_pair_ != nullptr);
+  RTC_DCHECK(certificate != nullptr);
+  std::vector<std::unique_ptr<SSLCertificate>> certs;
+  certs.push_back(std::move(certificate));
+  cert_chain_.reset(new SSLCertChain(std::move(certs)));
+}
+
+BoringSSLIdentity::BoringSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,
+                                     std::unique_ptr<SSLCertChain> cert_chain)
+    : key_pair_(std::move(key_pair)), cert_chain_(std::move(cert_chain)) {
+  RTC_DCHECK(key_pair_ != nullptr);
+  RTC_DCHECK(cert_chain_ != nullptr);
+}
+
+BoringSSLIdentity::~BoringSSLIdentity() = default;
+
+std::unique_ptr<BoringSSLIdentity> BoringSSLIdentity::CreateInternal(
+    const SSLIdentityParams& params) {
+  auto key_pair = OpenSSLKeyPair::Generate(params.key_params);
+  if (key_pair) {
+    std::unique_ptr<BoringSSLCertificate> certificate(
+        BoringSSLCertificate::Generate(key_pair.get(), params));
+    if (certificate != nullptr) {
+      return absl::WrapUnique(
+          new BoringSSLIdentity(std::move(key_pair), std::move(certificate)));
+    }
+  }
+  RTC_LOG(LS_ERROR) << "Identity generation failed.";
+  return nullptr;
+}
+
+// static
+std::unique_ptr<BoringSSLIdentity> BoringSSLIdentity::CreateWithExpiration(
+    const std::string& common_name,
+    const KeyParams& key_params,
+    time_t certificate_lifetime) {
+  SSLIdentityParams params;
+  params.key_params = key_params;
+  params.common_name = common_name;
+  time_t now = time(nullptr);
+  params.not_before = now + kCertificateWindowInSeconds;
+  params.not_after = now + certificate_lifetime;
+  if (params.not_before > params.not_after)
+    return nullptr;
+  return CreateInternal(params);
+}
+
+std::unique_ptr<BoringSSLIdentity> BoringSSLIdentity::CreateForTest(
+    const SSLIdentityParams& params) {
+  return CreateInternal(params);
+}
+
+std::unique_ptr<SSLIdentity> BoringSSLIdentity::CreateFromPEMStrings(
+    const std::string& private_key,
+    const std::string& certificate) {
+  std::unique_ptr<BoringSSLCertificate> cert(
+      BoringSSLCertificate::FromPEMString(certificate));
+  if (!cert) {
+    RTC_LOG(LS_ERROR)
+        << "Failed to create BoringSSLCertificate from PEM string.";
+    return nullptr;
+  }
+
+  auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
+  if (!key_pair) {
+    RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
+    return nullptr;
+  }
+
+  return absl::WrapUnique(
+      new BoringSSLIdentity(std::move(key_pair), std::move(cert)));
+}
+
+std::unique_ptr<SSLIdentity> BoringSSLIdentity::CreateFromPEMChainStrings(
+    const std::string& private_key,
+    const std::string& certificate_chain) {
+  bssl::UniquePtr<BIO> bio(
+      BIO_new_mem_buf(certificate_chain.data(),
+                      rtc::dchecked_cast<int>(certificate_chain.size())));
+  if (!bio) {
+    return nullptr;
+  }
+  BIO_set_mem_eof_return(bio.get(), 0);
+  std::vector<std::unique_ptr<SSLCertificate>> certs;
+  while (true) {
+    char* name;
+    char* header;
+    unsigned char* data;
+    long len;  // NOLINT
+    int ret = PEM_read_bio(bio.get(), &name, &header, &data, &len);
+    if (ret == 0) {
+      uint32_t err = ERR_peek_error();
+      if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
+          ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
+        break;
+      }
+      RTC_LOG(LS_ERROR) << "Failed to parse certificate from PEM string.";
+      return nullptr;
+    }
+    bssl::UniquePtr<char> owned_name(name);
+    bssl::UniquePtr<char> owned_header(header);
+    bssl::UniquePtr<unsigned char> owned_data(data);
+    if (strcmp(owned_name.get(), PEM_STRING_X509) != 0) {
+      RTC_LOG(LS_ERROR)
+          << "Non-certificate found while parsing certificate chain: "
+          << owned_name.get();
+      return nullptr;
+    }
+    bssl::UniquePtr<CRYPTO_BUFFER> crypto_buffer(
+        CRYPTO_BUFFER_new(data, len, openssl::GetBufferPool()));
+    if (!crypto_buffer) {
+      return nullptr;
+    }
+    certs.emplace_back(new BoringSSLCertificate(std::move(crypto_buffer)));
+  }
+  if (certs.empty()) {
+    RTC_LOG(LS_ERROR) << "Found no certificates in PEM string.";
+    return nullptr;
+  }
+
+  auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
+  if (!key_pair) {
+    RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
+    return nullptr;
+  }
+
+  return absl::WrapUnique(new BoringSSLIdentity(
+      std::move(key_pair), std::make_unique<SSLCertChain>(std::move(certs))));
+}
+
+const BoringSSLCertificate& BoringSSLIdentity::certificate() const {
+  return *static_cast<const BoringSSLCertificate*>(&cert_chain_->Get(0));
+}
+
+const SSLCertChain& BoringSSLIdentity::cert_chain() const {
+  return *cert_chain_.get();
+}
+
+std::unique_ptr<SSLIdentity> BoringSSLIdentity::CloneInternal() const {
+  // We cannot use std::make_unique here because the referenced
+  // BoringSSLIdentity constructor is private.
+  return absl::WrapUnique(
+      new BoringSSLIdentity(key_pair_->Clone(), cert_chain_->Clone()));
+}
+
+bool BoringSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
+  std::vector<CRYPTO_BUFFER*> cert_buffers;
+  for (size_t i = 0; i < cert_chain_->GetSize(); ++i) {
+    cert_buffers.push_back(
+        static_cast<const BoringSSLCertificate*>(&cert_chain_->Get(i))
+            ->cert_buffer());
+  }
+  // 1 is the documented success return code.
+  if (1 != SSL_CTX_set_chain_and_key(ctx, &cert_buffers[0], cert_buffers.size(),
+                                     key_pair_->pkey(), nullptr)) {
+    openssl::LogSSLErrors("Configuring key and certificate");
+    return false;
+  }
+  return true;
+}
+
+std::string BoringSSLIdentity::PrivateKeyToPEMString() const {
+  return key_pair_->PrivateKeyToPEMString();
+}
+
+std::string BoringSSLIdentity::PublicKeyToPEMString() const {
+  return key_pair_->PublicKeyToPEMString();
+}
+
+bool BoringSSLIdentity::operator==(const BoringSSLIdentity& other) const {
+  return *this->key_pair_ == *other.key_pair_ &&
+         this->certificate() == other.certificate();
+}
+
+bool BoringSSLIdentity::operator!=(const BoringSSLIdentity& other) const {
+  return !(*this == other);
+}
+
+}  // namespace rtc
diff --git a/rtc_base/boringssl_identity.h b/rtc_base/boringssl_identity.h
new file mode 100644
index 0000000..71b29b4
--- /dev/null
+++ b/rtc_base/boringssl_identity.h
@@ -0,0 +1,76 @@
+/*
+ *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_BORINGSSL_IDENTITY_H_
+#define RTC_BASE_BORINGSSL_IDENTITY_H_
+
+#include <openssl/ossl_typ.h>
+
+#include <ctime>
+#include <memory>
+#include <string>
+
+#include "rtc_base/boringssl_certificate.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/openssl_key_pair.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
+
+namespace rtc {
+
+// Holds a keypair and certificate together, and a method to generate them
+// consistently. Uses CRYPTO_BUFFER instead of X509, which offers binary size
+// and memory improvements.
+class BoringSSLIdentity final : public SSLIdentity {
+ public:
+  static std::unique_ptr<BoringSSLIdentity> CreateWithExpiration(
+      const std::string& common_name,
+      const KeyParams& key_params,
+      time_t certificate_lifetime);
+  static std::unique_ptr<BoringSSLIdentity> CreateForTest(
+      const SSLIdentityParams& params);
+  static std::unique_ptr<SSLIdentity> CreateFromPEMStrings(
+      const std::string& private_key,
+      const std::string& certificate);
+  static std::unique_ptr<SSLIdentity> CreateFromPEMChainStrings(
+      const std::string& private_key,
+      const std::string& certificate_chain);
+  ~BoringSSLIdentity() override;
+
+  const BoringSSLCertificate& certificate() const override;
+  const SSLCertChain& cert_chain() const override;
+
+  // Configure an SSL context object to use our key and certificate.
+  bool ConfigureIdentity(SSL_CTX* ctx);
+
+  std::string PrivateKeyToPEMString() const override;
+  std::string PublicKeyToPEMString() const override;
+  bool operator==(const BoringSSLIdentity& other) const;
+  bool operator!=(const BoringSSLIdentity& other) const;
+
+ private:
+  BoringSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,
+                    std::unique_ptr<BoringSSLCertificate> certificate);
+  BoringSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,
+                    std::unique_ptr<SSLCertChain> cert_chain);
+  std::unique_ptr<SSLIdentity> CloneInternal() const override;
+
+  static std::unique_ptr<BoringSSLIdentity> CreateInternal(
+      const SSLIdentityParams& params);
+
+  std::unique_ptr<OpenSSLKeyPair> key_pair_;
+  std::unique_ptr<SSLCertChain> cert_chain_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(BoringSSLIdentity);
+};
+
+}  // namespace rtc
+
+#endif  // RTC_BASE_BORINGSSL_IDENTITY_H_
diff --git a/rtc_base/buffer_queue.h b/rtc_base/buffer_queue.h
index 24a9b04..5895530 100644
--- a/rtc_base/buffer_queue.h
+++ b/rtc_base/buffer_queue.h
@@ -19,6 +19,7 @@
 #include "rtc_base/buffer.h"
 #include "rtc_base/constructor_magic.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace rtc {
@@ -55,7 +56,7 @@
   }
 
  private:
-  webrtc::SequenceChecker sequence_checker_;
+  RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_;
   const size_t capacity_;
   const size_t default_size_;
   std::deque<Buffer*> queue_ RTC_GUARDED_BY(sequence_checker_);
diff --git a/rtc_base/callback_list.cc b/rtc_base/callback_list.cc
index ac947e2..88d0b6f 100644
--- a/rtc_base/callback_list.cc
+++ b/rtc_base/callback_list.cc
@@ -21,17 +21,76 @@
   RTC_CHECK(!send_in_progress_);
 }
 
+void CallbackListReceivers::RemoveReceivers(const void* removal_tag) {
+  RTC_CHECK(!send_in_progress_);
+  RTC_DCHECK(removal_tag != nullptr);
+
+  // We divide the receivers_ vector into three regions: from right to left, the
+  // "keep" region, the "todo" region, and the "remove" region. The "todo"
+  // region initially covers the whole vector.
+  size_t first_todo = 0;                    // First element of the "todo"
+                                            // region.
+  size_t first_remove = receivers_.size();  // First element of the "remove"
+                                            // region.
+
+  // Loop until the "todo" region is empty.
+  while (first_todo != first_remove) {
+    if (receivers_[first_todo].removal_tag != removal_tag) {
+      // The first element of the "todo" region should be kept. Move the
+      // "keep"/"todo" boundary.
+      ++first_todo;
+    } else if (receivers_[first_remove - 1].removal_tag == removal_tag) {
+      // The last element of the "todo" region should be removed. Move the
+      // "todo"/"remove" boundary.
+      --first_remove;
+    } else {
+      // The first element of the "todo" region should be removed, and the last
+      // element of the "todo" region should be kept. Swap them, and then shrink
+      // the "todo" region from both ends.
+      RTC_DCHECK_NE(first_todo, first_remove - 1);
+      using std::swap;
+      swap(receivers_[first_todo], receivers_[first_remove - 1]);
+      RTC_DCHECK_NE(receivers_[first_todo].removal_tag, removal_tag);
+      ++first_todo;
+      RTC_DCHECK_EQ(receivers_[first_remove - 1].removal_tag, removal_tag);
+      --first_remove;
+    }
+  }
+
+  // Discard the remove region.
+  receivers_.resize(first_remove);
+}
+
 void CallbackListReceivers::Foreach(
     rtc::FunctionView<void(UntypedFunction&)> fv) {
   RTC_CHECK(!send_in_progress_);
   send_in_progress_ = true;
   for (auto& r : receivers_) {
-    fv(r);
+    fv(r.function);
   }
   send_in_progress_ = false;
 }
 
 template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<1>);
+template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<2>);
+template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<3>);
+template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<4>);
+template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::NontrivialUntypedFunctionArgs);
+template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::FunctionPointerUntypedFunctionArgs);
+
+template void CallbackListReceivers::AddReceiver(
     UntypedFunction::TrivialUntypedFunctionArgs<1>);
 template void CallbackListReceivers::AddReceiver(
     UntypedFunction::TrivialUntypedFunctionArgs<2>);
diff --git a/rtc_base/callback_list.h b/rtc_base/callback_list.h
index 659b838..18d48b0 100644
--- a/rtc_base/callback_list.h
+++ b/rtc_base/callback_list.h
@@ -33,19 +33,52 @@
   ~CallbackListReceivers();
 
   template <typename UntypedFunctionArgsT>
+  RTC_NO_INLINE void AddReceiver(const void* removal_tag,
+                                 UntypedFunctionArgsT args) {
+    RTC_CHECK(!send_in_progress_);
+    RTC_DCHECK(removal_tag != nullptr);
+    receivers_.push_back({removal_tag, UntypedFunction::Create(args)});
+  }
+
+  template <typename UntypedFunctionArgsT>
   RTC_NO_INLINE void AddReceiver(UntypedFunctionArgsT args) {
     RTC_CHECK(!send_in_progress_);
-    receivers_.push_back(UntypedFunction::Create(args));
+    receivers_.push_back({nullptr, UntypedFunction::Create(args)});
   }
 
+  void RemoveReceivers(const void* removal_tag);
+
   void Foreach(rtc::FunctionView<void(UntypedFunction&)> fv);
 
  private:
-  std::vector<UntypedFunction> receivers_;
+  struct Callback {
+    const void* removal_tag;
+    UntypedFunction function;
+  };
+  std::vector<Callback> receivers_;
   bool send_in_progress_ = false;
 };
 
 extern template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<1>);
+extern template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<2>);
+extern template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<3>);
+extern template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::TrivialUntypedFunctionArgs<4>);
+extern template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::NontrivialUntypedFunctionArgs);
+extern template void CallbackListReceivers::AddReceiver(
+    const void*,
+    UntypedFunction::FunctionPointerUntypedFunctionArgs);
+
+extern template void CallbackListReceivers::AddReceiver(
     UntypedFunction::TrivialUntypedFunctionArgs<1>);
 extern template void CallbackListReceivers::AddReceiver(
     UntypedFunction::TrivialUntypedFunctionArgs<2>);
@@ -125,11 +158,6 @@
 //     foo_callbacks_.AddReceiver(std::forward<F>(callback));
 //   }
 //
-// Removing callbacks
-// ------------------
-//
-// TODO(kwiberg): The current design doesn’t support removing callbacks, only
-// adding them, but removal support can easily be added.
 template <typename... ArgT>
 class CallbackList {
  public:
@@ -141,16 +169,35 @@
 
   // Adds a new receiver. The receiver (a callable object or a function pointer)
   // must be movable, but need not be copyable. Its call signature should be
-  // `void(ArgT...)`.
+  // `void(ArgT...)`. The removal tag is a pointer to an arbitrary object that
+  // you own, and that will stay alive until the CallbackList is gone, or until
+  // all receivers using it as a removal tag have been removed; you can use it
+  // to remove the receiver.
+  template <typename F>
+  void AddReceiver(const void* removal_tag, F&& f) {
+    receivers_.AddReceiver(
+        removal_tag,
+        UntypedFunction::PrepareArgs<void(ArgT...)>(std::forward<F>(f)));
+  }
+
+  // Adds a new receiver with no removal tag.
   template <typename F>
   void AddReceiver(F&& f) {
     receivers_.AddReceiver(
         UntypedFunction::PrepareArgs<void(ArgT...)>(std::forward<F>(f)));
   }
 
+  // Removes all receivers that were added with the given removal tag.
+  void RemoveReceivers(const void* removal_tag) {
+    receivers_.RemoveReceivers(removal_tag);
+  }
+
   // Calls all receivers with the given arguments. While the Send is in
   // progress, no method calls are allowed; specifically, this means that the
   // callbacks may not do anything with this CallbackList instance.
+  //
+  // Note: Receivers are called serially, but not necessarily in the same order
+  // they were added.
   template <typename... ArgU>
   void Send(ArgU&&... args) {
     receivers_.Foreach([&](UntypedFunction& f) {
diff --git a/rtc_base/callback_list_unittest.cc b/rtc_base/callback_list_unittest.cc
index 811f85e..119f88f 100644
--- a/rtc_base/callback_list_unittest.cc
+++ b/rtc_base/callback_list_unittest.cc
@@ -207,8 +207,53 @@
 
   EXPECT_EQ(index, 2);
 }
+
 // todo(glahiru): Add a test case to catch some error for Karl's first fix
 // todo(glahiru): Add a test for rtc::Bind
 // which used the following code in the Send
+
+TEST(CallbackList, RemoveOneReceiver) {
+  int removal_tag[2];
+  CallbackList<> c;
+  int accumulator = 0;
+  c.AddReceiver([&accumulator] { accumulator += 1; });
+  c.AddReceiver(&removal_tag[0], [&accumulator] { accumulator += 10; });
+  c.AddReceiver(&removal_tag[1], [&accumulator] { accumulator += 100; });
+  c.Send();
+  EXPECT_EQ(accumulator, 111);
+  c.RemoveReceivers(&removal_tag[0]);
+  c.Send();
+  EXPECT_EQ(accumulator, 212);
+}
+
+TEST(CallbackList, RemoveZeroReceivers) {
+  int removal_tag[3];
+  CallbackList<> c;
+  int accumulator = 0;
+  c.AddReceiver([&accumulator] { accumulator += 1; });
+  c.AddReceiver(&removal_tag[0], [&accumulator] { accumulator += 10; });
+  c.AddReceiver(&removal_tag[1], [&accumulator] { accumulator += 100; });
+  c.Send();
+  EXPECT_EQ(accumulator, 111);
+  c.RemoveReceivers(&removal_tag[2]);
+  c.Send();
+  EXPECT_EQ(accumulator, 222);
+}
+
+TEST(CallbackList, RemoveManyReceivers) {
+  int removal_tag;
+  CallbackList<> c;
+  int accumulator = 0;
+  c.AddReceiver([&accumulator] { accumulator += 1; });
+  c.AddReceiver(&removal_tag, [&accumulator] { accumulator += 10; });
+  c.AddReceiver([&accumulator] { accumulator += 100; });
+  c.AddReceiver(&removal_tag, [&accumulator] { accumulator += 1000; });
+  c.Send();
+  EXPECT_EQ(accumulator, 1111);
+  c.RemoveReceivers(&removal_tag);
+  c.Send();
+  EXPECT_EQ(accumulator, 1212);
+}
+
 }  // namespace
 }  // namespace webrtc
diff --git a/rtc_base/checks.h b/rtc_base/checks.h
index 508de2a..21fca7e 100644
--- a/rtc_base/checks.h
+++ b/rtc_base/checks.h
@@ -95,7 +95,7 @@
 //   messages if the condition doesn't hold. Prefer them to raw RTC_CHECK and
 //   RTC_DCHECK.
 //
-// - FATAL() aborts unconditionally.
+// - RTC_FATAL() aborts unconditionally.
 
 namespace rtc {
 namespace webrtc_checks_impl {
@@ -454,8 +454,7 @@
         RTC_UNREACHABLE_FILE_AND_LINE_CALL_ARGS);      \
   } while (0)
 
-// TODO(bugs.webrtc.org/8454): Add an RTC_ prefix or rename differently.
-#define FATAL()                                                      \
+#define RTC_FATAL()                                                  \
   ::rtc::webrtc_checks_impl::FatalLogCall<false>(__FILE__, __LINE__, \
                                                  "FATAL()") &        \
       ::rtc::webrtc_checks_impl::LogStreamer<>()
diff --git a/rtc_base/checks_unittest.cc b/rtc_base/checks_unittest.cc
index 91e04cf..95deba9 100644
--- a/rtc_base/checks_unittest.cc
+++ b/rtc_base/checks_unittest.cc
@@ -21,7 +21,7 @@
 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 TEST(ChecksDeathTest, Checks) {
 #if RTC_CHECK_MSG_ENABLED
-  EXPECT_DEATH(FATAL() << "message",
+  EXPECT_DEATH(RTC_FATAL() << "message",
                "\n\n#\n"
                "# Fatal error in: \\S+, line \\w+\n"
                "# last system error: \\w+\n"
@@ -45,7 +45,7 @@
                "# Check failed: false\n"
                "# Hi there!");
 #else
-  EXPECT_DEATH(FATAL() << "message",
+  EXPECT_DEATH(RTC_FATAL() << "message",
                "\n\n#\n"
                "# Fatal error in: \\S+, line \\w+\n"
                "# last system error: \\w+\n"
diff --git a/rtc_base/copy_on_write_buffer.h b/rtc_base/copy_on_write_buffer.h
index 68c6ad5..87bf625 100644
--- a/rtc_base/copy_on_write_buffer.h
+++ b/rtc_base/copy_on_write_buffer.h
@@ -86,7 +86,7 @@
   template <typename T = uint8_t,
             typename std::enable_if<
                 internal::BufferCompat<uint8_t, T>::value>::type* = nullptr>
-  T* data() {
+  T* MutableData() {
     RTC_DCHECK(IsConsistent());
     if (!buffer_) {
       return nullptr;
@@ -95,6 +95,14 @@
     return buffer_->data<T>() + offset_;
   }
 
+  // TODO(bugs.webrtc.org/12334): Delete when all usage updated to MutableData()
+  template <typename T = uint8_t,
+            typename std::enable_if<
+                internal::BufferCompat<uint8_t, T>::value>::type* = nullptr>
+  T* data() {
+    return MutableData<T>();
+  }
+
   // Get const pointer to the data. This will not create a copy of the
   // underlying data if it is shared with other buffers.
   template <typename T = uint8_t,
@@ -146,9 +154,10 @@
     return !(*this == buf);
   }
 
+  // TODO(bugs.webrtc.org/12334): Delete when all usage updated to MutableData()
   uint8_t& operator[](size_t index) {
     RTC_DCHECK_LT(index, size());
-    return data()[index];
+    return MutableData()[index];
   }
 
   uint8_t operator[](size_t index) const {
diff --git a/rtc_base/copy_on_write_buffer_unittest.cc b/rtc_base/copy_on_write_buffer_unittest.cc
index b35cd79..5c29c10 100644
--- a/rtc_base/copy_on_write_buffer_unittest.cc
+++ b/rtc_base/copy_on_write_buffer_unittest.cc
@@ -280,7 +280,8 @@
   EXPECT_EQ(data2, cdata1);
 }
 
-TEST(CopyOnWriteBufferTest, TestBacketRead) {
+// TODO(bugs.webrtc.org/12334): Delete when all reads become const
+TEST(CopyOnWriteBufferTest, SeveralReads) {
   CopyOnWriteBuffer buf1(kTestData, 3, 10);
   CopyOnWriteBuffer buf2(buf1);
 
@@ -292,7 +293,7 @@
   EnsureBuffersDontShareData(buf1, buf2);
 }
 
-TEST(CopyOnWriteBufferTest, TestBacketReadConst) {
+TEST(CopyOnWriteBufferTest, SeveralConstReads) {
   CopyOnWriteBuffer buf1(kTestData, 3, 10);
   CopyOnWriteBuffer buf2(buf1);
 
@@ -304,13 +305,13 @@
   EnsureBuffersShareData(buf1, buf2);
 }
 
-TEST(CopyOnWriteBufferTest, TestBacketWrite) {
+TEST(CopyOnWriteBufferTest, SeveralWrites) {
   CopyOnWriteBuffer buf1(kTestData, 3, 10);
   CopyOnWriteBuffer buf2(buf1);
 
   EnsureBuffersShareData(buf1, buf2);
   for (size_t i = 0; i != 3u; ++i) {
-    buf1[i] = kTestData[i] + 1;
+    buf1.MutableData()[i] = kTestData[i] + 1;
   }
   EXPECT_EQ(buf1.size(), 3u);
   EXPECT_EQ(buf1.capacity(), 10u);
@@ -335,7 +336,7 @@
 TEST(CopyOnWriteBufferTest, WritingCopiesData) {
   CopyOnWriteBuffer buf(kTestData, 10, 10);
   CopyOnWriteBuffer slice = buf.Slice(3, 4);
-  slice[0] = 0xaa;
+  slice.MutableData()[0] = 0xaa;
   EXPECT_NE(buf.cdata() + 3, slice.cdata());
   EXPECT_EQ(0, memcmp(buf.cdata(), kTestData, 10));
 }
@@ -343,7 +344,7 @@
 TEST(CopyOnWriteBufferTest, WritingToBufferDoesntAffectsSlice) {
   CopyOnWriteBuffer buf(kTestData, 10, 10);
   CopyOnWriteBuffer slice = buf.Slice(3, 4);
-  buf[0] = 0xaa;
+  buf.MutableData()[0] = 0xaa;
   EXPECT_NE(buf.cdata() + 3, slice.cdata());
   EXPECT_EQ(0, memcmp(slice.cdata(), kTestData + 3, 4));
 }
@@ -361,7 +362,7 @@
   CopyOnWriteBuffer buf(kTestData, 10, 10);
   CopyOnWriteBuffer slice = buf.Slice(3, 7);
   CopyOnWriteBuffer slice2 = buf.Slice(3, 7);
-  slice2[0] = 0xaa;
+  slice2.MutableData()[0] = 0xaa;
   EXPECT_EQ(buf.cdata() + 3, slice.cdata());
 }
 
diff --git a/rtc_base/fake_network.h b/rtc_base/fake_network.h
index 8bd50b6..1bbdd46 100644
--- a/rtc_base/fake_network.h
+++ b/rtc_base/fake_network.h
@@ -70,10 +70,11 @@
     ++start_count_;
     if (start_count_ == 1) {
       sent_first_update_ = false;
-      rtc::Thread::Current()->Post(RTC_FROM_HERE, this);
+      rtc::Thread::Current()->Post(RTC_FROM_HERE, this, kUpdateNetworksMessage);
     } else {
       if (sent_first_update_) {
-        SignalNetworksChanged();
+        rtc::Thread::Current()->Post(RTC_FROM_HERE, this,
+                                     kSignalNetworksMessage);
       }
     }
   }
@@ -81,7 +82,15 @@
   void StopUpdating() override { --start_count_; }
 
   // MessageHandler interface.
-  void OnMessage(Message* msg) override { DoUpdateNetworks(); }
+  void OnMessage(Message* msg) override {
+    if (msg->message_id == kUpdateNetworksMessage) {
+      DoUpdateNetworks();
+    } else if (msg->message_id == kSignalNetworksMessage) {
+      SignalNetworksChanged();
+    } else {
+      RTC_CHECK(false);
+    }
+  }
 
   using NetworkManagerBase::set_default_local_addresses;
   using NetworkManagerBase::set_enumeration_permission;
@@ -129,6 +138,9 @@
   int start_count_ = 0;
   bool sent_first_update_ = false;
 
+  static constexpr uint32_t kUpdateNetworksMessage = 1;
+  static constexpr uint32_t kSignalNetworksMessage = 2;
+
   std::unique_ptr<webrtc::MdnsResponderInterface> mdns_responder_;
 };
 
diff --git a/rtc_base/ip_address.h b/rtc_base/ip_address.h
index ae135a6..8725417 100644
--- a/rtc_base/ip_address.h
+++ b/rtc_base/ip_address.h
@@ -80,12 +80,12 @@
   bool operator<(const IPAddress& other) const;
   bool operator>(const IPAddress& other) const;
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
   inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
       std::ostream& os) {           // no-presubmit-check TODO(webrtc:8982)
     return os << ToString();
   }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
   int family() const { return family_; }
   in_addr ipv4_address() const;
diff --git a/rtc_base/keep_ref_until_done.h b/rtc_base/keep_ref_until_done.h
index 7bebd82..5ae0ed1 100644
--- a/rtc_base/keep_ref_until_done.h
+++ b/rtc_base/keep_ref_until_done.h
@@ -12,29 +12,23 @@
 #define RTC_BASE_KEEP_REF_UNTIL_DONE_H_
 
 #include "api/scoped_refptr.h"
-#include "rtc_base/bind.h"
 #include "rtc_base/callback.h"
-#include "rtc_base/ref_count.h"
 
 namespace rtc {
 
-namespace impl {
-template <class T>
-static inline void DoNothing(const scoped_refptr<T>& object) {}
-}  // namespace impl
-
 // KeepRefUntilDone keeps a reference to |object| until the returned
 // callback goes out of scope. If the returned callback is copied, the
 // reference will be released when the last callback goes out of scope.
 template <class ObjectT>
 static inline Callback0<void> KeepRefUntilDone(ObjectT* object) {
-  return rtc::Bind(&impl::DoNothing<ObjectT>, scoped_refptr<ObjectT>(object));
+  scoped_refptr<ObjectT> p(object);
+  return [p] {};
 }
 
 template <class ObjectT>
 static inline Callback0<void> KeepRefUntilDone(
     const scoped_refptr<ObjectT>& object) {
-  return rtc::Bind(&impl::DoNothing<ObjectT>, object);
+  return [object] {};
 }
 
 }  // namespace rtc
diff --git a/rtc_base/message_digest.h b/rtc_base/message_digest.h
index 36f00b5..691330e 100644
--- a/rtc_base/message_digest.h
+++ b/rtc_base/message_digest.h
@@ -45,7 +45,8 @@
   static MessageDigest* Create(const std::string& alg);
 };
 
-// A whitelist of approved digest algorithms from RFC 4572 (FIPS 180).
+// A check that an algorithm is in a list of approved digest algorithms
+// from RFC 4572 (FIPS 180).
 bool IsFips180DigestAlgorithm(const std::string& alg);
 
 // Functions to create hashes.
diff --git a/rtc_base/nat_socket_factory.cc b/rtc_base/nat_socket_factory.cc
index 7c853e9..3edf4ce 100644
--- a/rtc_base/nat_socket_factory.cc
+++ b/rtc_base/nat_socket_factory.cc
@@ -230,10 +230,10 @@
     return connected_ ? CS_CONNECTED : CS_CLOSED;
   }
   int GetOption(Option opt, int* value) override {
-    return socket_->GetOption(opt, value);
+    return socket_ ? socket_->GetOption(opt, value) : -1;
   }
   int SetOption(Option opt, int value) override {
-    return socket_->SetOption(opt, value);
+    return socket_ ? socket_->SetOption(opt, value) : -1;
   }
 
   void OnConnectEvent(AsyncSocket* socket) {
diff --git a/rtc_base/net_helpers.h b/rtc_base/net_helpers.h
index c6aa4be..172a222 100644
--- a/rtc_base/net_helpers.h
+++ b/rtc_base/net_helpers.h
@@ -23,6 +23,7 @@
 #include "rtc_base/ip_address.h"
 #include "rtc_base/socket_address.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 #include "rtc_base/system/rtc_export.h"
 #include "rtc_base/task_utils/pending_task_safety_flag.h"
 #include "rtc_base/thread.h"
@@ -62,7 +63,7 @@
   bool recursion_check_ =
       false;  // Protects against SignalDone calling into Destroy.
   bool destroy_called_ = false;
-  webrtc::SequenceChecker sequence_checker_;
+  RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_;
 };
 
 // rtc namespaced wrappers for inet_ntop and inet_pton so we can avoid
diff --git a/rtc_base/network.cc b/rtc_base/network.cc
index 8aabdcb..07c39ae 100644
--- a/rtc_base/network.cc
+++ b/rtc_base/network.cc
@@ -131,7 +131,7 @@
 }
 
 #if !defined(__native_client__)
-bool IsIgnoredIPv6(const InterfaceAddress& ip) {
+bool IsIgnoredIPv6(bool allow_mac_based_ipv6, const InterfaceAddress& ip) {
   if (ip.family() != AF_INET6) {
     return false;
   }
@@ -144,7 +144,7 @@
   }
 
   // Any MAC based IPv6 should be avoided to prevent the MAC tracking.
-  if (IPIsMacBased(ip)) {
+  if (IPIsMacBased(ip) && !allow_mac_based_ipv6) {
     return true;
   }
 
@@ -478,11 +478,15 @@
   return nullptr;
 }
 
-BasicNetworkManager::BasicNetworkManager() {}
+BasicNetworkManager::BasicNetworkManager()
+    : allow_mac_based_ipv6_(
+          webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
 
 BasicNetworkManager::BasicNetworkManager(
     NetworkMonitorFactory* network_monitor_factory)
-    : network_monitor_factory_(network_monitor_factory) {}
+    : network_monitor_factory_(network_monitor_factory),
+      allow_mac_based_ipv6_(
+          webrtc::field_trial::IsEnabled("WebRTC-AllowMACBasedIPv6")) {}
 
 BasicNetworkManager::~BasicNetworkManager() {}
 
@@ -535,7 +539,7 @@
 
     // Special case for IPv6 address.
     if (cursor->ifa_addr->sa_family == AF_INET6) {
-      if (IsIgnoredIPv6(ip)) {
+      if (IsIgnoredIPv6(allow_mac_based_ipv6_, ip)) {
         continue;
       }
       scope_id =
@@ -713,7 +717,7 @@
             scope_id = v6_addr->sin6_scope_id;
             ip = IPAddress(v6_addr->sin6_addr);
 
-            if (IsIgnoredIPv6(InterfaceAddress(ip))) {
+            if (IsIgnoredIPv6(allow_mac_based_ipv6_, InterfaceAddress(ip))) {
               continue;
             }
 
diff --git a/rtc_base/network.h b/rtc_base/network.h
index 7103f0f..3107b72 100644
--- a/rtc_base/network.h
+++ b/rtc_base/network.h
@@ -293,6 +293,7 @@
       nullptr;
   std::unique_ptr<NetworkMonitorInterface> network_monitor_
       RTC_GUARDED_BY(thread_);
+  bool allow_mac_based_ipv6_ = false;
 };
 
 // Represents a Unix-type network interface, with a name and single address.
diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc
index 13f888e..73ddd81 100644
--- a/rtc_base/network_unittest.cc
+++ b/rtc_base/network_unittest.cc
@@ -33,6 +33,7 @@
 #if defined(WEBRTC_WIN)
 #include "rtc_base/logging.h"  // For RTC_LOG_GLE
 #endif
+#include "test/field_trial.h"
 
 using ::testing::Contains;
 using ::testing::Not;
@@ -1240,4 +1241,42 @@
   }
 }
 
+#if defined(WEBRTC_POSIX)
+TEST_F(NetworkTest, IgnoresMACBasedIPv6Address) {
+  std::string ipv6_address = "2607:fc20:f340:1dc8:214:22ff:fe01:2345";
+  std::string ipv6_mask = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF";
+  BasicNetworkManager manager;
+  manager.StartUpdating();
+
+  // IPSec interface; name is in form "ipsec<index>".
+  char if_name[20] = "ipsec11";
+  ifaddrs* addr_list =
+      InstallIpv6Network(if_name, ipv6_address, ipv6_mask, manager);
+
+  BasicNetworkManager::NetworkList list;
+  manager.GetNetworks(&list);
+  EXPECT_EQ(list.size(), 0u);
+  ReleaseIfAddrs(addr_list);
+}
+
+TEST_F(NetworkTest, WebRTC_AllowMACBasedIPv6Address) {
+  webrtc::test::ScopedFieldTrials field_trials(
+      "WebRTC-AllowMACBasedIPv6/Enabled/");
+  std::string ipv6_address = "2607:fc20:f340:1dc8:214:22ff:fe01:2345";
+  std::string ipv6_mask = "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF";
+  BasicNetworkManager manager;
+  manager.StartUpdating();
+
+  // IPSec interface; name is in form "ipsec<index>".
+  char if_name[20] = "ipsec11";
+  ifaddrs* addr_list =
+      InstallIpv6Network(if_name, ipv6_address, ipv6_mask, manager);
+
+  BasicNetworkManager::NetworkList list;
+  manager.GetNetworks(&list);
+  EXPECT_EQ(list.size(), 1u);
+  ReleaseIfAddrs(addr_list);
+}
+#endif
+
 }  // namespace rtc
diff --git a/rtc_base/openssl_adapter.cc b/rtc_base/openssl_adapter.cc
index 8fd882c..e5c2c42 100644
--- a/rtc_base/openssl_adapter.cc
+++ b/rtc_base/openssl_adapter.cc
@@ -13,6 +13,9 @@
 #include <errno.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/pool.h>
+#endif
 #include <openssl/rand.h>
 #include <openssl/x509.h>
 #include <string.h>
@@ -20,13 +23,24 @@
 
 #include <memory>
 
+// Use CRYPTO_BUFFER APIs if available and we have no dependency on X509
+// objects.
+#if defined(OPENSSL_IS_BORINGSSL) && \
+    defined(WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS)
+#define WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
+#endif
+
 #include "absl/memory/memory.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/openssl.h"
-#include "rtc_base/openssl_certificate.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include "rtc_base/boringssl_identity.h"
+#else
+#include "rtc_base/openssl_identity.h"
+#endif
 #include "rtc_base/openssl_utility.h"
 #include "rtc_base/string_encode.h"
 #include "rtc_base/thread.h"
@@ -223,8 +237,13 @@
 
 void OpenSSLAdapter::SetIdentity(std::unique_ptr<SSLIdentity> identity) {
   RTC_DCHECK(!identity_);
+#ifdef OPENSSL_IS_BORINGSSL
+  identity_ =
+      absl::WrapUnique(static_cast<BoringSSLIdentity*>(identity.release()));
+#else
   identity_ =
       absl::WrapUnique(static_cast<OpenSSLIdentity*>(identity.release()));
+#endif
 }
 
 void OpenSSLAdapter::SetRole(SSLRole role) {
@@ -797,7 +816,70 @@
 
 #endif
 
+#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
+// static
+enum ssl_verify_result_t OpenSSLAdapter::SSLVerifyCallback(SSL* ssl,
+                                                           uint8_t* out_alert) {
+  // Get our stream pointer from the SSL context.
+  OpenSSLAdapter* stream =
+      reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
+
+  ssl_verify_result_t ret = stream->SSLVerifyInternal(ssl, out_alert);
+
+  // Should only be used for debugging and development.
+  if (ret != ssl_verify_ok && stream->ignore_bad_cert_) {
+    RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
+    return ssl_verify_ok;
+  }
+
+  return ret;
+}
+
+enum ssl_verify_result_t OpenSSLAdapter::SSLVerifyInternal(SSL* ssl,
+                                                           uint8_t* out_alert) {
+  if (ssl_cert_verifier_ == nullptr) {
+    RTC_LOG(LS_WARNING) << "Built-in trusted root certificates disabled but no "
+                           "SSL verify callback provided.";
+    return ssl_verify_invalid;
+  }
+
+  RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback.";
+  const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
+  if (sk_CRYPTO_BUFFER_num(chain) == 0) {
+    RTC_LOG(LS_ERROR) << "Peer certificate chain empty?";
+    return ssl_verify_invalid;
+  }
+
+  BoringSSLCertificate cert(bssl::UpRef(sk_CRYPTO_BUFFER_value(chain, 0)));
+  if (!ssl_cert_verifier_->Verify(cert)) {
+    RTC_LOG(LS_WARNING) << "Failed to verify certificate using custom callback";
+    return ssl_verify_invalid;
+  }
+
+  custom_cert_verifier_status_ = true;
+  RTC_LOG(LS_INFO) << "Validated certificate using custom callback";
+  return ssl_verify_ok;
+}
+#else  // WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
 int OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) {
+  // Get our stream pointer from the store
+  SSL* ssl = reinterpret_cast<SSL*>(
+      X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()));
+
+  OpenSSLAdapter* stream =
+      reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
+  ok = stream->SSLVerifyInternal(ok, ssl, store);
+
+  // Should only be used for debugging and development.
+  if (!ok && stream->ignore_bad_cert_) {
+    RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
+    return 1;
+  }
+
+  return ok;
+}
+
+int OpenSSLAdapter::SSLVerifyInternal(int ok, SSL* ssl, X509_STORE_CTX* store) {
 #if !defined(NDEBUG)
   if (!ok) {
     char data[256];
@@ -814,33 +896,40 @@
                       << X509_verify_cert_error_string(err);
   }
 #endif
-  // Get our stream pointer from the store
-  SSL* ssl = reinterpret_cast<SSL*>(
-      X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()));
-
-  OpenSSLAdapter* stream =
-      reinterpret_cast<OpenSSLAdapter*>(SSL_get_app_data(ssl));
-
-  if (!ok && stream->ssl_cert_verifier_ != nullptr) {
-    RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback.";
-    const OpenSSLCertificate cert(X509_STORE_CTX_get_current_cert(store));
-    if (stream->ssl_cert_verifier_->Verify(cert)) {
-      stream->custom_cert_verifier_status_ = true;
-      RTC_LOG(LS_INFO) << "Validated certificate using custom callback";
-      ok = true;
-    } else {
-      RTC_LOG(LS_INFO) << "Failed to verify certificate using custom callback";
-    }
+  if (ssl_cert_verifier_ == nullptr) {
+    return ok;
   }
 
-  // Should only be used for debugging and development.
-  if (!ok && stream->ignore_bad_cert_) {
-    RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
-    ok = 1;
+  RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback.";
+#ifdef OPENSSL_IS_BORINGSSL
+  // Convert X509 to CRYPTO_BUFFER.
+  uint8_t* data = nullptr;
+  int length = i2d_X509(X509_STORE_CTX_get_current_cert(store), &data);
+  if (length < 0) {
+    RTC_LOG(LS_ERROR) << "Failed to encode X509.";
+    return ok;
+  }
+  bssl::UniquePtr<uint8_t> owned_data(data);
+  bssl::UniquePtr<CRYPTO_BUFFER> crypto_buffer(
+      CRYPTO_BUFFER_new(data, length, openssl::GetBufferPool()));
+  if (!crypto_buffer) {
+    RTC_LOG(LS_ERROR) << "Failed to allocate CRYPTO_BUFFER.";
+    return ok;
+  }
+  const BoringSSLCertificate cert(std::move(crypto_buffer));
+#else
+  const OpenSSLCertificate cert(X509_STORE_CTX_get_current_cert(store));
+#endif
+  if (!ssl_cert_verifier_->Verify(cert)) {
+    RTC_LOG(LS_INFO) << "Failed to verify certificate using custom callback";
+    return ok;
   }
 
-  return ok;
+  custom_cert_verifier_status_ = true;
+  RTC_LOG(LS_INFO) << "Validated certificate using custom callback";
+  return 1;
 }
+#endif  // !defined(WEBRTC_USE_CRYPTO_BUFFER_CALLBACK)
 
 int OpenSSLAdapter::NewSSLSessionCallback(SSL* ssl, SSL_SESSION* session) {
   OpenSSLAdapter* stream =
@@ -852,8 +941,15 @@
 }
 
 SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) {
+#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
+  // If X509 objects aren't used, we can use these methods to avoid
+  // linking the sizable crypto/x509 code.
+  SSL_CTX* ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_with_buffers_method()
+                                                   : TLS_with_buffers_method());
+#else
   SSL_CTX* ctx =
       SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
+#endif
   if (ctx == nullptr) {
     unsigned long error = ERR_get_error();  // NOLINT: type used by OpenSSL.
     RTC_LOG(LS_WARNING) << "SSL_CTX creation failed: " << '"'
@@ -877,8 +973,16 @@
   SSL_CTX_set_info_callback(ctx, SSLInfoCallback);
 #endif
 
+#ifdef OPENSSL_IS_BORINGSSL
+  SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool());
+#endif
+
+#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK
+  SSL_CTX_set_custom_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
+#else
   SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback);
   SSL_CTX_set_verify_depth(ctx, 4);
+#endif
   // Use defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers
   // (note that SHA256 and SHA384 only select legacy CBC ciphers).
   // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining
diff --git a/rtc_base/openssl_adapter.h b/rtc_base/openssl_adapter.h
index 6f1f7dc..76b003a 100644
--- a/rtc_base/openssl_adapter.h
+++ b/rtc_base/openssl_adapter.h
@@ -11,6 +11,7 @@
 #ifndef RTC_BASE_OPENSSL_ADAPTER_H_
 #define RTC_BASE_OPENSSL_ADAPTER_H_
 
+#include <openssl/ossl_typ.h>
 #include <stddef.h>
 #include <stdint.h>
 
@@ -21,7 +22,11 @@
 #include "rtc_base/async_socket.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/message_handler.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include "rtc_base/boringssl_identity.h"
+#else
 #include "rtc_base/openssl_identity.h"
+#endif
 #include "rtc_base/openssl_session_cache.h"
 #include "rtc_base/socket.h"
 #include "rtc_base/socket_address.h"
@@ -109,7 +114,16 @@
   // In debug builds, logs info about the state of the SSL connection.
   static void SSLInfoCallback(const SSL* ssl, int where, int ret);
 #endif
+
+#if defined(OPENSSL_IS_BORINGSSL) && \
+    defined(WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS)
+  static enum ssl_verify_result_t SSLVerifyCallback(SSL* ssl,
+                                                    uint8_t* out_alert);
+  enum ssl_verify_result_t SSLVerifyInternal(SSL* ssl, uint8_t* out_alert);
+#else
   static int SSLVerifyCallback(int ok, X509_STORE_CTX* store);
+  int SSLVerifyInternal(int ok, SSL* ssl, X509_STORE_CTX* store);
+#endif
   friend class OpenSSLStreamAdapter;  // for custom_verify_callback_;
 
   // If the SSL_CTX was created with |enable_cache| set to true, this callback
@@ -123,7 +137,12 @@
   SSLCertificateVerifier* ssl_cert_verifier_ = nullptr;
   // The current connection state of the (d)TLS connection.
   SSLState state_;
+
+#ifdef OPENSSL_IS_BORINGSSL
+  std::unique_ptr<BoringSSLIdentity> identity_;
+#else
   std::unique_ptr<OpenSSLIdentity> identity_;
+#endif
   // Indicates whethere this is a client or a server.
   SSLRole role_;
   bool ssl_read_needs_write_;
diff --git a/rtc_base/openssl_identity.cc b/rtc_base/openssl_identity.cc
index c94df40..3794d98 100644
--- a/rtc_base/openssl_identity.cc
+++ b/rtc_base/openssl_identity.cc
@@ -20,10 +20,8 @@
 #endif                       // WEBRTC_WIN
 
 #include <openssl/bio.h>
-#include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/pem.h>
-#include <openssl/rsa.h>
 #include <stdint.h>
 
 #include "absl/memory/memory.h"
@@ -35,160 +33,6 @@
 
 namespace rtc {
 
-// We could have exposed a myriad of parameters for the crypto stuff,
-// but keeping it simple seems best.
-
-// Generate a key pair. Caller is responsible for freeing the returned object.
-static EVP_PKEY* MakeKey(const KeyParams& key_params) {
-  RTC_LOG(LS_INFO) << "Making key pair";
-  EVP_PKEY* pkey = EVP_PKEY_new();
-  if (key_params.type() == KT_RSA) {
-    int key_length = key_params.rsa_params().mod_size;
-    BIGNUM* exponent = BN_new();
-    RSA* rsa = RSA_new();
-    if (!pkey || !exponent || !rsa ||
-        !BN_set_word(exponent, key_params.rsa_params().pub_exp) ||
-        !RSA_generate_key_ex(rsa, key_length, exponent, nullptr) ||
-        !EVP_PKEY_assign_RSA(pkey, rsa)) {
-      EVP_PKEY_free(pkey);
-      BN_free(exponent);
-      RSA_free(rsa);
-      RTC_LOG(LS_ERROR) << "Failed to make RSA key pair";
-      return nullptr;
-    }
-    // ownership of rsa struct was assigned, don't free it.
-    BN_free(exponent);
-  } else if (key_params.type() == KT_ECDSA) {
-    if (key_params.ec_curve() == EC_NIST_P256) {
-      EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
-
-      // Ensure curve name is included when EC key is serialized.
-      // Without this call, OpenSSL versions before 1.1.0 will create
-      // certificates that don't work for TLS.
-      // This is a no-op for BoringSSL and OpenSSL 1.1.0+
-      EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
-
-      if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) ||
-          !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) {
-        EVP_PKEY_free(pkey);
-        EC_KEY_free(ec_key);
-        RTC_LOG(LS_ERROR) << "Failed to make EC key pair";
-        return nullptr;
-      }
-      // ownership of ec_key struct was assigned, don't free it.
-    } else {
-      // Add generation of any other curves here.
-      EVP_PKEY_free(pkey);
-      RTC_LOG(LS_ERROR) << "ECDSA key requested for unknown curve";
-      return nullptr;
-    }
-  } else {
-    EVP_PKEY_free(pkey);
-    RTC_LOG(LS_ERROR) << "Key type requested not understood";
-    return nullptr;
-  }
-
-  RTC_LOG(LS_INFO) << "Returning key pair";
-  return pkey;
-}
-
-OpenSSLKeyPair* OpenSSLKeyPair::Generate(const KeyParams& key_params) {
-  EVP_PKEY* pkey = MakeKey(key_params);
-  if (!pkey) {
-    openssl::LogSSLErrors("Generating key pair");
-    return nullptr;
-  }
-  return new OpenSSLKeyPair(pkey);
-}
-
-OpenSSLKeyPair* OpenSSLKeyPair::FromPrivateKeyPEMString(
-    const std::string& pem_string) {
-  BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
-  if (!bio) {
-    RTC_LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
-    return nullptr;
-  }
-  BIO_set_mem_eof_return(bio, 0);
-  EVP_PKEY* pkey =
-      PEM_read_bio_PrivateKey(bio, nullptr, nullptr, const_cast<char*>("\0"));
-  BIO_free(bio);  // Frees the BIO, but not the pointed-to string.
-  if (!pkey) {
-    RTC_LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
-    return nullptr;
-  }
-  if (EVP_PKEY_missing_parameters(pkey) != 0) {
-    RTC_LOG(LS_ERROR)
-        << "The resulting key pair is missing public key parameters.";
-    EVP_PKEY_free(pkey);
-    return nullptr;
-  }
-  return new OpenSSLKeyPair(pkey);
-}
-
-OpenSSLKeyPair::~OpenSSLKeyPair() {
-  EVP_PKEY_free(pkey_);
-}
-
-OpenSSLKeyPair* OpenSSLKeyPair::GetReference() {
-  AddReference();
-  return new OpenSSLKeyPair(pkey_);
-}
-
-void OpenSSLKeyPair::AddReference() {
-  EVP_PKEY_up_ref(pkey_);
-}
-
-std::string OpenSSLKeyPair::PrivateKeyToPEMString() const {
-  BIO* temp_memory_bio = BIO_new(BIO_s_mem());
-  if (!temp_memory_bio) {
-    RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
-    RTC_NOTREACHED();
-    return "";
-  }
-  if (!PEM_write_bio_PrivateKey(temp_memory_bio, pkey_, nullptr, nullptr, 0,
-                                nullptr, nullptr)) {
-    RTC_LOG_F(LS_ERROR) << "Failed to write private key";
-    BIO_free(temp_memory_bio);
-    RTC_NOTREACHED();
-    return "";
-  }
-  BIO_write(temp_memory_bio, "\0", 1);
-  char* buffer;
-  BIO_get_mem_data(temp_memory_bio, &buffer);
-  std::string priv_key_str = buffer;
-  BIO_free(temp_memory_bio);
-  return priv_key_str;
-}
-
-std::string OpenSSLKeyPair::PublicKeyToPEMString() const {
-  BIO* temp_memory_bio = BIO_new(BIO_s_mem());
-  if (!temp_memory_bio) {
-    RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
-    RTC_NOTREACHED();
-    return "";
-  }
-  if (!PEM_write_bio_PUBKEY(temp_memory_bio, pkey_)) {
-    RTC_LOG_F(LS_ERROR) << "Failed to write public key";
-    BIO_free(temp_memory_bio);
-    RTC_NOTREACHED();
-    return "";
-  }
-  BIO_write(temp_memory_bio, "\0", 1);
-  char* buffer;
-  BIO_get_mem_data(temp_memory_bio, &buffer);
-  std::string pub_key_str = buffer;
-  BIO_free(temp_memory_bio);
-  return pub_key_str;
-}
-
-bool OpenSSLKeyPair::operator==(const OpenSSLKeyPair& other) const {
-  return EVP_PKEY_cmp(this->pkey_, other.pkey_) == 1;
-}
-
-bool OpenSSLKeyPair::operator!=(const OpenSSLKeyPair& other) const {
-  return !(*this == other);
-}
-
 OpenSSLIdentity::OpenSSLIdentity(
     std::unique_ptr<OpenSSLKeyPair> key_pair,
     std::unique_ptr<OpenSSLCertificate> certificate)
@@ -211,8 +55,7 @@
 
 std::unique_ptr<OpenSSLIdentity> OpenSSLIdentity::CreateInternal(
     const SSLIdentityParams& params) {
-  std::unique_ptr<OpenSSLKeyPair> key_pair(
-      OpenSSLKeyPair::Generate(params.key_params));
+  auto key_pair = OpenSSLKeyPair::Generate(params.key_params);
   if (key_pair) {
     std::unique_ptr<OpenSSLCertificate> certificate(
         OpenSSLCertificate::Generate(key_pair.get(), params));
@@ -221,7 +64,7 @@
           new OpenSSLIdentity(std::move(key_pair), std::move(certificate)));
     }
   }
-  RTC_LOG(LS_INFO) << "Identity generation failed";
+  RTC_LOG(LS_ERROR) << "Identity generation failed";
   return nullptr;
 }
 
@@ -256,8 +99,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<OpenSSLKeyPair> key_pair(
-      OpenSSLKeyPair::FromPrivateKeyPEMString(private_key));
+  auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
   if (!key_pair) {
     RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
     return nullptr;
@@ -298,8 +140,7 @@
     return nullptr;
   }
 
-  std::unique_ptr<OpenSSLKeyPair> key_pair(
-      OpenSSLKeyPair::FromPrivateKeyPEMString(private_key));
+  auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
   if (!key_pair) {
     RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
     return nullptr;
@@ -320,8 +161,8 @@
 std::unique_ptr<SSLIdentity> OpenSSLIdentity::CloneInternal() const {
   // We cannot use std::make_unique here because the referenced OpenSSLIdentity
   // constructor is private.
-  return absl::WrapUnique(new OpenSSLIdentity(
-      absl::WrapUnique(key_pair_->GetReference()), cert_chain_->Clone()));
+  return absl::WrapUnique(
+      new OpenSSLIdentity(key_pair_->Clone(), cert_chain_->Clone()));
 }
 
 bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
diff --git a/rtc_base/openssl_identity.h b/rtc_base/openssl_identity.h
index a2ac87c..00d6c74 100644
--- a/rtc_base/openssl_identity.h
+++ b/rtc_base/openssl_identity.h
@@ -17,45 +17,14 @@
 #include <memory>
 #include <string>
 
-#include "rtc_base/checks.h"
 #include "rtc_base/constructor_magic.h"
 #include "rtc_base/openssl_certificate.h"
+#include "rtc_base/openssl_key_pair.h"
 #include "rtc_base/ssl_certificate.h"
 #include "rtc_base/ssl_identity.h"
 
 namespace rtc {
 
-// OpenSSLKeyPair encapsulates an OpenSSL EVP_PKEY* keypair object,
-// which is reference counted inside the OpenSSL library.
-class OpenSSLKeyPair final {
- public:
-  explicit OpenSSLKeyPair(EVP_PKEY* pkey) : pkey_(pkey) {
-    RTC_DCHECK(pkey_ != nullptr);
-  }
-
-  static OpenSSLKeyPair* Generate(const KeyParams& key_params);
-  // Constructs a key pair from the private key PEM string. This must not result
-  // in missing public key parameters. Returns null on error.
-  static OpenSSLKeyPair* FromPrivateKeyPEMString(const std::string& pem_string);
-
-  virtual ~OpenSSLKeyPair();
-
-  virtual OpenSSLKeyPair* GetReference();
-
-  EVP_PKEY* pkey() const { return pkey_; }
-  std::string PrivateKeyToPEMString() const;
-  std::string PublicKeyToPEMString() const;
-  bool operator==(const OpenSSLKeyPair& other) const;
-  bool operator!=(const OpenSSLKeyPair& other) const;
-
- private:
-  void AddReference();
-
-  EVP_PKEY* pkey_;
-
-  RTC_DISALLOW_COPY_AND_ASSIGN(OpenSSLKeyPair);
-};
-
 // Holds a keypair and certificate together, and a method to generate
 // them consistently.
 class OpenSSLIdentity final : public SSLIdentity {
diff --git a/rtc_base/openssl_key_pair.cc b/rtc_base/openssl_key_pair.cc
new file mode 100644
index 0000000..911a751
--- /dev/null
+++ b/rtc_base/openssl_key_pair.cc
@@ -0,0 +1,192 @@
+/*
+ *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/openssl_key_pair.h"
+
+#include <memory>
+#include <utility>
+
+#if defined(WEBRTC_WIN)
+// Must be included first before openssl headers.
+#include "rtc_base/win32.h"  // NOLINT
+#endif                       // WEBRTC_WIN
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/openssl.h"
+#include "rtc_base/openssl_utility.h"
+
+namespace rtc {
+
+// We could have exposed a myriad of parameters for the crypto stuff,
+// but keeping it simple seems best.
+
+// Generate a key pair. Caller is responsible for freeing the returned object.
+static EVP_PKEY* MakeKey(const KeyParams& key_params) {
+  RTC_LOG(LS_INFO) << "Making key pair";
+  EVP_PKEY* pkey = EVP_PKEY_new();
+  if (key_params.type() == KT_RSA) {
+    int key_length = key_params.rsa_params().mod_size;
+    BIGNUM* exponent = BN_new();
+    RSA* rsa = RSA_new();
+    if (!pkey || !exponent || !rsa ||
+        !BN_set_word(exponent, key_params.rsa_params().pub_exp) ||
+        !RSA_generate_key_ex(rsa, key_length, exponent, nullptr) ||
+        !EVP_PKEY_assign_RSA(pkey, rsa)) {
+      EVP_PKEY_free(pkey);
+      BN_free(exponent);
+      RSA_free(rsa);
+      RTC_LOG(LS_ERROR) << "Failed to make RSA key pair";
+      return nullptr;
+    }
+    // ownership of rsa struct was assigned, don't free it.
+    BN_free(exponent);
+  } else if (key_params.type() == KT_ECDSA) {
+    if (key_params.ec_curve() == EC_NIST_P256) {
+      EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+      if (!ec_key) {
+        EVP_PKEY_free(pkey);
+        RTC_LOG(LS_ERROR) << "Failed to allocate EC key";
+        return nullptr;
+      }
+
+      // Ensure curve name is included when EC key is serialized.
+      // Without this call, OpenSSL versions before 1.1.0 will create
+      // certificates that don't work for TLS.
+      // This is a no-op for BoringSSL and OpenSSL 1.1.0+
+      EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE);
+
+      if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) ||
+          !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) {
+        EVP_PKEY_free(pkey);
+        EC_KEY_free(ec_key);
+        RTC_LOG(LS_ERROR) << "Failed to make EC key pair";
+        return nullptr;
+      }
+      // ownership of ec_key struct was assigned, don't free it.
+    } else {
+      // Add generation of any other curves here.
+      EVP_PKEY_free(pkey);
+      RTC_LOG(LS_ERROR) << "ECDSA key requested for unknown curve";
+      return nullptr;
+    }
+  } else {
+    EVP_PKEY_free(pkey);
+    RTC_LOG(LS_ERROR) << "Key type requested not understood";
+    return nullptr;
+  }
+
+  RTC_LOG(LS_INFO) << "Returning key pair";
+  return pkey;
+}
+
+std::unique_ptr<OpenSSLKeyPair> OpenSSLKeyPair::Generate(
+    const KeyParams& key_params) {
+  EVP_PKEY* pkey = MakeKey(key_params);
+  if (!pkey) {
+    openssl::LogSSLErrors("Generating key pair");
+    return nullptr;
+  }
+  return std::make_unique<OpenSSLKeyPair>(pkey);
+}
+
+std::unique_ptr<OpenSSLKeyPair> OpenSSLKeyPair::FromPrivateKeyPEMString(
+    const std::string& pem_string) {
+  BIO* bio =
+      BIO_new_mem_buf(const_cast<char*>(pem_string.data()), pem_string.size());
+  if (!bio) {
+    RTC_LOG(LS_ERROR) << "Failed to create a new BIO buffer.";
+    return nullptr;
+  }
+  BIO_set_mem_eof_return(bio, 0);
+  EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
+  BIO_free(bio);  // Frees the BIO, but not the pointed-to string.
+  if (!pkey) {
+    RTC_LOG(LS_ERROR) << "Failed to create the private key from PEM string.";
+    return nullptr;
+  }
+  if (EVP_PKEY_missing_parameters(pkey) != 0) {
+    RTC_LOG(LS_ERROR)
+        << "The resulting key pair is missing public key parameters.";
+    EVP_PKEY_free(pkey);
+    return nullptr;
+  }
+  return std::make_unique<OpenSSLKeyPair>(pkey);
+}
+
+OpenSSLKeyPair::~OpenSSLKeyPair() {
+  EVP_PKEY_free(pkey_);
+}
+
+std::unique_ptr<OpenSSLKeyPair> OpenSSLKeyPair::Clone() {
+  AddReference();
+  return std::make_unique<OpenSSLKeyPair>(pkey_);
+}
+
+void OpenSSLKeyPair::AddReference() {
+  EVP_PKEY_up_ref(pkey_);
+}
+
+std::string OpenSSLKeyPair::PrivateKeyToPEMString() const {
+  BIO* temp_memory_bio = BIO_new(BIO_s_mem());
+  if (!temp_memory_bio) {
+    RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
+    RTC_NOTREACHED();
+    return "";
+  }
+  if (!PEM_write_bio_PrivateKey(temp_memory_bio, pkey_, nullptr, nullptr, 0,
+                                nullptr, nullptr)) {
+    RTC_LOG_F(LS_ERROR) << "Failed to write private key";
+    BIO_free(temp_memory_bio);
+    RTC_NOTREACHED();
+    return "";
+  }
+  char* buffer;
+  size_t len = BIO_get_mem_data(temp_memory_bio, &buffer);
+  std::string priv_key_str(buffer, len);
+  BIO_free(temp_memory_bio);
+  return priv_key_str;
+}
+
+std::string OpenSSLKeyPair::PublicKeyToPEMString() const {
+  BIO* temp_memory_bio = BIO_new(BIO_s_mem());
+  if (!temp_memory_bio) {
+    RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio";
+    RTC_NOTREACHED();
+    return "";
+  }
+  if (!PEM_write_bio_PUBKEY(temp_memory_bio, pkey_)) {
+    RTC_LOG_F(LS_ERROR) << "Failed to write public key";
+    BIO_free(temp_memory_bio);
+    RTC_NOTREACHED();
+    return "";
+  }
+  BIO_write(temp_memory_bio, "\0", 1);
+  char* buffer;
+  BIO_get_mem_data(temp_memory_bio, &buffer);
+  std::string pub_key_str = buffer;
+  BIO_free(temp_memory_bio);
+  return pub_key_str;
+}
+
+bool OpenSSLKeyPair::operator==(const OpenSSLKeyPair& other) const {
+  return EVP_PKEY_cmp(this->pkey_, other.pkey_) == 1;
+}
+
+bool OpenSSLKeyPair::operator!=(const OpenSSLKeyPair& other) const {
+  return !(*this == other);
+}
+
+}  // namespace rtc
diff --git a/rtc_base/openssl_key_pair.h b/rtc_base/openssl_key_pair.h
new file mode 100644
index 0000000..a84c43b
--- /dev/null
+++ b/rtc_base/openssl_key_pair.h
@@ -0,0 +1,60 @@
+/*
+ *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_OPENSSL_KEY_PAIR_H_
+#define RTC_BASE_OPENSSL_KEY_PAIR_H_
+
+#include <openssl/ossl_typ.h>
+
+#include <memory>
+#include <string>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ssl_identity.h"
+
+namespace rtc {
+
+// OpenSSLKeyPair encapsulates an OpenSSL EVP_PKEY* keypair object,
+// which is reference counted inside the OpenSSL library.
+class OpenSSLKeyPair final {
+ public:
+  // Takes ownership of the key.
+  explicit OpenSSLKeyPair(EVP_PKEY* pkey) : pkey_(pkey) {
+    RTC_DCHECK(pkey_ != nullptr);
+  }
+
+  static std::unique_ptr<OpenSSLKeyPair> Generate(const KeyParams& key_params);
+  // Constructs a key pair from the private key PEM string. This must not result
+  // in missing public key parameters. Returns null on error.
+  static std::unique_ptr<OpenSSLKeyPair> FromPrivateKeyPEMString(
+      const std::string& pem_string);
+
+  ~OpenSSLKeyPair();
+
+  std::unique_ptr<OpenSSLKeyPair> Clone();
+
+  EVP_PKEY* pkey() const { return pkey_; }
+  std::string PrivateKeyToPEMString() const;
+  std::string PublicKeyToPEMString() const;
+  bool operator==(const OpenSSLKeyPair& other) const;
+  bool operator!=(const OpenSSLKeyPair& other) const;
+
+ private:
+  void AddReference();
+
+  EVP_PKEY* pkey_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(OpenSSLKeyPair);
+};
+
+}  // namespace rtc
+
+#endif  // RTC_BASE_OPENSSL_KEY_PAIR_H_
diff --git a/rtc_base/openssl_session_cache_unittest.cc b/rtc_base/openssl_session_cache_unittest.cc
index 1d3084b..0441d5c 100644
--- a/rtc_base/openssl_session_cache_unittest.cc
+++ b/rtc_base/openssl_session_cache_unittest.cc
@@ -19,10 +19,28 @@
 #include "rtc_base/gunit.h"
 #include "rtc_base/openssl.h"
 
+namespace {
+// Use methods that avoid X509 objects if possible.
+SSL_CTX* NewDtlsContext() {
+#ifdef OPENSSL_IS_BORINGSSL
+  return SSL_CTX_new(DTLS_with_buffers_method());
+#else
+  return SSL_CTX_new(DTLS_method());
+#endif
+}
+SSL_CTX* NewTlsContext() {
+#ifdef OPENSSL_IS_BORINGSSL
+  return SSL_CTX_new(TLS_with_buffers_method());
+#else
+  return SSL_CTX_new(TLS_method());
+#endif
+}
+}  // namespace
+
 namespace rtc {
 
 TEST(OpenSSLSessionCache, DTLSModeSetCorrectly) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
+  SSL_CTX* ssl_ctx = NewDtlsContext();
 
   OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx);
   EXPECT_EQ(session_cache.GetSSLMode(), SSL_MODE_DTLS);
@@ -31,7 +49,7 @@
 }
 
 TEST(OpenSSLSessionCache, TLSModeSetCorrectly) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(TLSv1_2_client_method());
+  SSL_CTX* ssl_ctx = NewTlsContext();
 
   OpenSSLSessionCache session_cache(SSL_MODE_TLS, ssl_ctx);
   EXPECT_EQ(session_cache.GetSSLMode(), SSL_MODE_TLS);
@@ -40,7 +58,7 @@
 }
 
 TEST(OpenSSLSessionCache, SSLContextSetCorrectly) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
+  SSL_CTX* ssl_ctx = NewDtlsContext();
 
   OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx);
   EXPECT_EQ(session_cache.GetSSLContext(), ssl_ctx);
@@ -49,7 +67,7 @@
 }
 
 TEST(OpenSSLSessionCache, InvalidLookupReturnsNullptr) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
+  SSL_CTX* ssl_ctx = NewDtlsContext();
 
   OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx);
   EXPECT_EQ(session_cache.LookupSession("Invalid"), nullptr);
@@ -60,7 +78,7 @@
 }
 
 TEST(OpenSSLSessionCache, SimpleValidSessionLookup) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
+  SSL_CTX* ssl_ctx = NewDtlsContext();
   SSL_SESSION* ssl_session = SSL_SESSION_new(ssl_ctx);
 
   OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx);
@@ -71,7 +89,7 @@
 }
 
 TEST(OpenSSLSessionCache, AddToExistingReplacesPrevious) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
+  SSL_CTX* ssl_ctx = NewDtlsContext();
   SSL_SESSION* ssl_session_1 = SSL_SESSION_new(ssl_ctx);
   SSL_SESSION* ssl_session_2 = SSL_SESSION_new(ssl_ctx);
 
diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc
index f59b4ed..63b8069 100644
--- a/rtc_base/openssl_stream_adapter.cc
+++ b/rtc_base/openssl_stream_adapter.cc
@@ -32,7 +32,12 @@
 #include "rtc_base/openssl.h"
 #include "rtc_base/openssl_adapter.h"
 #include "rtc_base/openssl_digest.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include "rtc_base/boringssl_identity.h"
+#else
 #include "rtc_base/openssl_identity.h"
+#endif
+#include "rtc_base/openssl_utility.h"
 #include "rtc_base/ssl_certificate.h"
 #include "rtc_base/stream.h"
 #include "rtc_base/task_utils/to_queued_task.h"
@@ -304,10 +309,14 @@
 
 void OpenSSLStreamAdapter::SetIdentity(std::unique_ptr<SSLIdentity> identity) {
   RTC_DCHECK(!identity_);
+#ifdef OPENSSL_IS_BORINGSSL
+  identity_.reset(static_cast<BoringSSLIdentity*>(identity.release()));
+#else
   identity_.reset(static_cast<OpenSSLIdentity*>(identity.release()));
+#endif
 }
 
-OpenSSLIdentity* OpenSSLStreamAdapter::GetIdentityForTesting() const {
+SSLIdentity* OpenSSLStreamAdapter::GetIdentityForTesting() const {
   return identity_.get();
 }
 
@@ -994,8 +1003,16 @@
 }
 
 SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() {
+#ifdef OPENSSL_IS_BORINGSSL
+  // If X509 objects aren't used, we can use these methods to avoid
+  // linking the sizable crypto/x509 code, using CRYPTO_BUFFER instead.
+  SSL_CTX* ctx =
+      SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_with_buffers_method()
+                                             : TLS_with_buffers_method());
+#else
   SSL_CTX* ctx =
       SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_method() : TLS_method());
+#endif
   if (ctx == nullptr) {
     return nullptr;
   }
@@ -1033,6 +1050,7 @@
   if (g_use_time_callback_for_testing) {
     SSL_CTX_set_current_time_cb(ctx, &TimeCallbackForTesting);
   }
+  SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool());
 #endif
 
   if (identity_ && !identity_->ConfigureIdentity(ctx)) {
@@ -1053,11 +1071,16 @@
   }
 
   // Configure a custom certificate verification callback to check the peer
-  // certificate digest. Note the second argument to SSL_CTX_set_verify is to
-  // override individual errors in the default verification logic, which is not
-  // what we want here.
+  // certificate digest.
+#ifdef OPENSSL_IS_BORINGSSL
+  // Use CRYPTO_BUFFER version of the callback if building with BoringSSL.
+  SSL_CTX_set_custom_verify(ctx, mode, SSLVerifyCallback);
+#else
+  // Note the second argument to SSL_CTX_set_verify is to override individual
+  // errors in the default verification logic, which is not what we want here.
   SSL_CTX_set_verify(ctx, mode, nullptr);
   SSL_CTX_set_cert_verify_callback(ctx, SSLVerifyCallback, nullptr);
+#endif
 
   // Select list of available ciphers. Note that !SHA256 and !SHA384 only
   // remove HMAC-SHA256 and HMAC-SHA384 cipher suites, not GCM cipher suites
@@ -1082,14 +1105,12 @@
     RTC_LOG(LS_WARNING) << "Missing digest or peer certificate.";
     return false;
   }
-  const OpenSSLCertificate* leaf_cert =
-      static_cast<const OpenSSLCertificate*>(&peer_cert_chain_->Get(0));
 
   unsigned char digest[EVP_MAX_MD_SIZE];
   size_t digest_length;
-  if (!OpenSSLCertificate::ComputeDigest(
-          leaf_cert->x509(), peer_certificate_digest_algorithm_, digest,
-          sizeof(digest), &digest_length)) {
+  if (!peer_cert_chain_->Get(0).ComputeDigest(
+          peer_certificate_digest_algorithm_, digest, sizeof(digest),
+          &digest_length)) {
     RTC_LOG(LS_WARNING) << "Failed to compute peer cert digest.";
     return false;
   }
@@ -1113,6 +1134,36 @@
   return peer_cert_chain_ ? peer_cert_chain_->Clone() : nullptr;
 }
 
+#ifdef OPENSSL_IS_BORINGSSL
+enum ssl_verify_result_t OpenSSLStreamAdapter::SSLVerifyCallback(
+    SSL* ssl,
+    uint8_t* out_alert) {
+  // Get our OpenSSLStreamAdapter from the context.
+  OpenSSLStreamAdapter* stream =
+      reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
+  const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
+  // Creates certificate chain.
+  std::vector<std::unique_ptr<SSLCertificate>> cert_chain;
+  for (CRYPTO_BUFFER* cert : chain) {
+    cert_chain.emplace_back(new BoringSSLCertificate(bssl::UpRef(cert)));
+  }
+  stream->peer_cert_chain_.reset(new SSLCertChain(std::move(cert_chain)));
+
+  // If the peer certificate digest isn't known yet, we'll wait to verify
+  // until it's known, and for now just return a success status.
+  if (stream->peer_certificate_digest_algorithm_.empty()) {
+    RTC_LOG(LS_INFO) << "Waiting to verify certificate until digest is known.";
+    // TODO(deadbeef): Use ssl_verify_retry?
+    return ssl_verify_ok;
+  }
+
+  if (!stream->VerifyPeerCertificate()) {
+    return ssl_verify_invalid;
+  }
+
+  return ssl_verify_ok;
+}
+#else   // OPENSSL_IS_BORINGSSL
 int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
   // Get our SSL structure and OpenSSLStreamAdapter from the store.
   SSL* ssl = reinterpret_cast<SSL*>(
@@ -1120,20 +1171,10 @@
   OpenSSLStreamAdapter* stream =
       reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
 
-#if defined(OPENSSL_IS_BORINGSSL)
-  STACK_OF(X509)* chain = SSL_get_peer_full_cert_chain(ssl);
-  // Creates certificate chain.
-  std::vector<std::unique_ptr<SSLCertificate>> cert_chain;
-  for (X509* cert : chain) {
-    cert_chain.emplace_back(new OpenSSLCertificate(cert));
-  }
-  stream->peer_cert_chain_.reset(new SSLCertChain(std::move(cert_chain)));
-#else
   // Record the peer's certificate.
   X509* cert = X509_STORE_CTX_get0_cert(store);
   stream->peer_cert_chain_.reset(
       new SSLCertChain(std::make_unique<OpenSSLCertificate>(cert)));
-#endif
 
   // If the peer certificate digest isn't known yet, we'll wait to verify
   // until it's known, and for now just return a success status.
@@ -1149,6 +1190,7 @@
 
   return 1;
 }
+#endif  // !OPENSSL_IS_BORINGSSL
 
 bool OpenSSLStreamAdapter::IsBoringSsl() {
 #ifdef OPENSSL_IS_BORINGSSL
diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h
index fbfccd6..a09737c 100644
--- a/rtc_base/openssl_stream_adapter.h
+++ b/rtc_base/openssl_stream_adapter.h
@@ -21,7 +21,11 @@
 
 #include "absl/types/optional.h"
 #include "rtc_base/buffer.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include "rtc_base/boringssl_identity.h"
+#else
 #include "rtc_base/openssl_identity.h"
+#endif
 #include "rtc_base/ssl_identity.h"
 #include "rtc_base/ssl_stream_adapter.h"
 #include "rtc_base/stream.h"
@@ -71,7 +75,7 @@
   ~OpenSSLStreamAdapter() override;
 
   void SetIdentity(std::unique_ptr<SSLIdentity> identity) override;
-  OpenSSLIdentity* GetIdentityForTesting() const override;
+  SSLIdentity* GetIdentityForTesting() const override;
 
   // Default argument is for compatibility
   void SetServerRole(SSLRole role = SSL_SERVER) override;
@@ -179,9 +183,16 @@
   SSL_CTX* SetupSSLContext();
   // Verify the peer certificate matches the signaled digest.
   bool VerifyPeerCertificate();
+
+#ifdef OPENSSL_IS_BORINGSSL
+  // SSL certificate verification callback. See SSL_CTX_set_custom_verify.
+  static enum ssl_verify_result_t SSLVerifyCallback(SSL* ssl,
+                                                    uint8_t* out_alert);
+#else
   // SSL certificate verification callback. See
   // SSL_CTX_set_cert_verify_callback.
   static int SSLVerifyCallback(X509_STORE_CTX* store, void* arg);
+#endif
 
   bool WaitingToVerifyPeerCertificate() const {
     return GetClientAuthEnabled() && !peer_certificate_verified_;
@@ -208,7 +219,11 @@
   SSL_CTX* ssl_ctx_;
 
   // Our key and certificate.
+#ifdef OPENSSL_IS_BORINGSSL
+  std::unique_ptr<BoringSSLIdentity> identity_;
+#else
   std::unique_ptr<OpenSSLIdentity> identity_;
+#endif
   // The certificate chain that the peer presented. Initially null, until the
   // connection is established.
   std::unique_ptr<SSLCertChain> peer_cert_chain_;
diff --git a/rtc_base/openssl_utility.cc b/rtc_base/openssl_utility.cc
index 1984eb0..b5d649c 100644
--- a/rtc_base/openssl_utility.cc
+++ b/rtc_base/openssl_utility.cc
@@ -14,6 +14,9 @@
 #include "rtc_base/win32.h"  // NOLINT
 #endif                       // WEBRTC_WIN
 
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/pool.h>
+#endif
 #include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
@@ -23,7 +26,7 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/openssl.h"
-#include "rtc_base/openssl_certificate.h"
+#include "rtc_base/ssl_identity.h"
 #ifndef WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 #include "rtc_base/ssl_roots.h"
 #endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
@@ -33,6 +36,10 @@
 
 // Holds various helper methods.
 namespace {
+
+// TODO(crbug.com/webrtc/11710): When OS certificate verification is available,
+// and we don't need VerifyPeerCertMatchesHost, don't compile this in order to
+// avoid a dependency on OpenSSL X509 objects (see crbug.com/webrtc/11410).
 void LogCertificates(SSL* ssl, X509* certificate) {
 // Logging certificates is extremely verbose. So it is disabled by default.
 #ifdef LOG_CERTIFICATES
@@ -65,6 +72,118 @@
 }
 }  // namespace
 
+#ifdef OPENSSL_IS_BORINGSSL
+bool ParseCertificate(CRYPTO_BUFFER* cert_buffer,
+                      CBS* signature_algorithm_oid,
+                      int64_t* expiration_time) {
+  CBS cbs;
+  CRYPTO_BUFFER_init_CBS(cert_buffer, &cbs);
+
+  //   Certificate  ::=  SEQUENCE  {
+  CBS certificate;
+  if (!CBS_get_asn1(&cbs, &certificate, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  //        tbsCertificate       TBSCertificate,
+  CBS tbs_certificate;
+  if (!CBS_get_asn1(&certificate, &tbs_certificate, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  //        signatureAlgorithm   AlgorithmIdentifier,
+  CBS signature_algorithm;
+  if (!CBS_get_asn1(&certificate, &signature_algorithm, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  if (!CBS_get_asn1(&signature_algorithm, signature_algorithm_oid,
+                    CBS_ASN1_OBJECT)) {
+    return false;
+  }
+  //        signatureValue       BIT STRING  }
+  if (!CBS_get_asn1(&certificate, nullptr, CBS_ASN1_BITSTRING)) {
+    return false;
+  }
+  if (CBS_len(&certificate)) {
+    return false;
+  }
+
+  // Now parse the inner TBSCertificate.
+  //        version         [0]  EXPLICIT Version DEFAULT v1,
+  if (!CBS_get_optional_asn1(
+          &tbs_certificate, nullptr, nullptr,
+          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)) {
+    return false;
+  }
+  //        serialNumber         CertificateSerialNumber,
+  if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_INTEGER)) {
+    return false;
+  }
+  //        signature            AlgorithmIdentifier
+  if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  //        issuer               Name,
+  if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  //        validity             Validity,
+  CBS validity;
+  if (!CBS_get_asn1(&tbs_certificate, &validity, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  // Skip over notBefore.
+  if (!CBS_get_any_asn1_element(&validity, nullptr, nullptr, nullptr)) {
+    return false;
+  }
+  // Parse notAfter.
+  CBS not_after;
+  unsigned not_after_tag;
+  if (!CBS_get_any_asn1(&validity, &not_after, &not_after_tag)) {
+    return false;
+  }
+  bool long_format;
+  if (not_after_tag == CBS_ASN1_UTCTIME) {
+    long_format = false;
+  } else if (not_after_tag == CBS_ASN1_GENERALIZEDTIME) {
+    long_format = true;
+  } else {
+    return false;
+  }
+  if (expiration_time) {
+    *expiration_time =
+        ASN1TimeToSec(CBS_data(&not_after), CBS_len(&not_after), long_format);
+  }
+  //        subject              Name,
+  if (!CBS_get_asn1_element(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  //        subjectPublicKeyInfo SubjectPublicKeyInfo,
+  if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) {
+    return false;
+  }
+  //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL
+  if (!CBS_get_optional_asn1(&tbs_certificate, nullptr, nullptr,
+                             0x01 | CBS_ASN1_CONTEXT_SPECIFIC)) {
+    return false;
+  }
+  //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL
+  if (!CBS_get_optional_asn1(&tbs_certificate, nullptr, nullptr,
+                             0x02 | CBS_ASN1_CONTEXT_SPECIFIC)) {
+    return false;
+  }
+  //        extensions      [3]  EXPLICIT Extensions OPTIONAL
+  if (!CBS_get_optional_asn1(
+          &tbs_certificate, nullptr, nullptr,
+          0x03 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)) {
+    return false;
+  }
+  if (CBS_len(&tbs_certificate)) {
+    return false;
+  }
+
+  return true;
+}
+#endif  // OPENSSL_IS_BORINGSSL
+
 bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host) {
   if (host.empty()) {
     RTC_DLOG(LS_ERROR) << "Hostname is empty. Cannot verify peer certificate.";
@@ -76,9 +195,28 @@
     return false;
   }
 
+#ifdef OPENSSL_IS_BORINGSSL
+  // We can't grab a X509 object directly, as the SSL context may have been
+  // initialized with TLS_with_buffers_method.
+  const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl);
+  if (chain == nullptr || sk_CRYPTO_BUFFER_num(chain) == 0) {
+    RTC_LOG(LS_ERROR)
+        << "SSL_get0_peer_certificates failed. This should never happen.";
+    return false;
+  }
+  CRYPTO_BUFFER* leaf = sk_CRYPTO_BUFFER_value(chain, 0);
+  bssl::UniquePtr<X509> x509(X509_parse_from_buffer(leaf));
+  if (!x509) {
+    RTC_LOG(LS_ERROR) << "Failed to parse certificate to X509 object.";
+    return false;
+  }
+  LogCertificates(ssl, x509.get());
+  return X509_check_host(x509.get(), host.c_str(), host.size(), 0, nullptr) ==
+         1;
+#else   // OPENSSL_IS_BORINGSSL
   X509* certificate = SSL_get_peer_certificate(ssl);
   if (certificate == nullptr) {
-    RTC_DLOG(LS_ERROR)
+    RTC_LOG(LS_ERROR)
         << "SSL_get_peer_certificate failed. This should never happen.";
     return false;
   }
@@ -89,6 +227,7 @@
       X509_check_host(certificate, host.c_str(), host.size(), 0, nullptr) == 1;
   X509_free(certificate);
   return is_valid_cert_name;
+#endif  // !defined(OPENSSL_IS_BORINGSSL)
 }
 
 void LogSSLErrors(const std::string& prefix) {
@@ -123,5 +262,12 @@
 }
 #endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
+#ifdef OPENSSL_IS_BORINGSSL
+CRYPTO_BUFFER_POOL* GetBufferPool() {
+  static CRYPTO_BUFFER_POOL* instance = CRYPTO_BUFFER_POOL_new();
+  return instance;
+}
+#endif
+
 }  // namespace openssl
 }  // namespace rtc
diff --git a/rtc_base/openssl_utility.h b/rtc_base/openssl_utility.h
index 022294d..ee29ccd 100644
--- a/rtc_base/openssl_utility.h
+++ b/rtc_base/openssl_utility.h
@@ -20,8 +20,21 @@
 // to OpenSSL that are commonly used and don't require global state should be
 // placed here.
 namespace openssl {
+
+#ifdef OPENSSL_IS_BORINGSSL
+// Does minimal parsing of a certificate (only verifying the presence of major
+// fields), primarily for the purpose of extracting the relevant out
+// parameters. Any that the caller is uninterested in can be null.
+bool ParseCertificate(CRYPTO_BUFFER* cert_buffer,
+                      CBS* signature_algorithm_oid,
+                      int64_t* expiration_time);
+#endif
+
 // Verifies that the hostname provided matches that in the peer certificate
 // attached to this SSL state.
+// TODO(crbug.com/webrtc/11710): When OS certificate verification is available,
+// skip compiling this as it adds a dependency on OpenSSL X509 objects, which we
+// are trying to avoid in favor of CRYPTO_BUFFERs (see crbug.com/webrtc/11410).
 bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host);
 
 // Logs all the errors in the OpenSSL errror queue from the current thread. A
@@ -35,6 +48,10 @@
 bool LoadBuiltinSSLRootCertificates(SSL_CTX* ssl_ctx);
 #endif  // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS
 
+#ifdef OPENSSL_IS_BORINGSSL
+CRYPTO_BUFFER_POOL* GetBufferPool();
+#endif
+
 }  // namespace openssl
 }  // namespace rtc
 
diff --git a/rtc_base/openssl_utility_unittest.cc b/rtc_base/openssl_utility_unittest.cc
index 9c9b971..d090524 100644
--- a/rtc_base/openssl_utility_unittest.cc
+++ b/rtc_base/openssl_utility_unittest.cc
@@ -24,8 +24,12 @@
 #include <openssl/crypto.h>
 #include <openssl/evp.h>
 #include <openssl/ssl.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/pool.h>
+#else
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
+#endif
 
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
@@ -169,14 +173,17 @@
     0x84, 0x0b, 0xc7, 0x15, 0x86, 0xc3, 0xfc, 0x48, 0x55, 0xb5, 0x81, 0x94,
     0x73, 0xbd, 0x18, 0xcd, 0x9d, 0x92, 0x47, 0xaa, 0xfd, 0x18};
 
+#ifdef OPENSSL_IS_BORINGSSL
+enum ssl_verify_result_t DummyVerifyCallback(SSL* ssl, uint8_t* out_alert) {
+  return ssl_verify_ok;
+}
+#endif
+
 // Creates a client SSL that has completed handshaking with a server that uses
 // the specified certificate (which must have private key kFakeSSLPrivateKey).
 // The server is deallocated. This client will have a peer certificate available
 // and is thus suitable for testing VerifyPeerCertMatchesHost.
 SSL* CreateSSLWithPeerCertificate(const unsigned char* cert, size_t cert_len) {
-  X509* x509 =
-      d2i_X509(nullptr, &cert, checked_cast<long>(cert_len));  // NOLINT
-  RTC_CHECK(x509);
 
   const unsigned char* key_ptr = kFakeSSLPrivateKey;
   EVP_PKEY* key = d2i_PrivateKey(
@@ -184,14 +191,33 @@
       checked_cast<long>(arraysize(kFakeSSLPrivateKey)));  // NOLINT
   RTC_CHECK(key);
 
-  SSL_CTX* ctx = SSL_CTX_new(SSLv23_method());
+#ifdef OPENSSL_IS_BORINGSSL
+  SSL_CTX* ctx = SSL_CTX_new(TLS_with_buffers_method());
+#else
+  SSL_CTX* ctx = SSL_CTX_new(TLS_method());
+#endif
   SSL* client = SSL_new(ctx);
   SSL* server = SSL_new(ctx);
   SSL_set_connect_state(client);
   SSL_set_accept_state(server);
 
+#ifdef OPENSSL_IS_BORINGSSL
+  bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer(CRYPTO_BUFFER_new(
+      static_cast<const uint8_t*>(cert), cert_len, openssl::GetBufferPool()));
+  RTC_CHECK(cert_buffer);
+  std::vector<CRYPTO_BUFFER*> cert_buffers;
+  cert_buffers.push_back(cert_buffer.get());
+  RTC_CHECK(1 == SSL_set_chain_and_key(server, cert_buffers.data(),
+                                       cert_buffers.size(), key, nullptr));
+  // When using crypto buffers we don't get any built-in verification.
+  SSL_set_custom_verify(client, SSL_VERIFY_PEER, DummyVerifyCallback);
+#else
+  X509* x509 =
+      d2i_X509(nullptr, &cert, checked_cast<long>(cert_len));  // NOLINT
+  RTC_CHECK(x509);
   RTC_CHECK(SSL_use_certificate(server, x509));
   RTC_CHECK(SSL_use_PrivateKey(server, key));
+#endif
 
   BIO* bio1;
   BIO* bio2;
@@ -221,13 +247,19 @@
   SSL_free(server);
   SSL_CTX_free(ctx);
   EVP_PKEY_free(key);
+#ifndef OPENSSL_IS_BORINGSSL
   X509_free(x509);
+#endif
   return client;
 }
 }  // namespace
 
 TEST(OpenSSLUtilityTest, VerifyPeerCertMatchesHostFailsOnNoPeerCertificate) {
-  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
+#ifdef OPENSSL_IS_BORINGSSL
+  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLS_with_buffers_method());
+#else
+  SSL_CTX* ssl_ctx = SSL_CTX_new(DTLS_method());
+#endif
   SSL* ssl = SSL_new(ssl_ctx);
 
   EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "webrtc.org"));
diff --git a/rtc_base/operations_chain.h b/rtc_base/operations_chain.h
index 44a3d9a..a7252d4 100644
--- a/rtc_base/operations_chain.h
+++ b/rtc_base/operations_chain.h
@@ -25,6 +25,7 @@
 #include "rtc_base/ref_count.h"
 #include "rtc_base/ref_counted_object.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 
 namespace rtc {
 
@@ -183,7 +184,7 @@
   std::function<void()> CreateOperationsChainCallback();
   void OnOperationComplete();
 
-  webrtc::SequenceChecker sequence_checker_;
+  RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_;
   // FIFO-list of operations that are chained. An operation that is executing
   // remains on this list until it has completed by invoking the callback passed
   // to it.
diff --git a/rtc_base/physical_socket_server.cc b/rtc_base/physical_socket_server.cc
index cf6e792..3cb7c20 100644
--- a/rtc_base/physical_socket_server.cc
+++ b/rtc_base/physical_socket_server.cc
@@ -335,10 +335,17 @@
 #if defined(WEBRTC_POSIX)
   if (sopt == IPV6_TCLASS) {
     // Set the IPv4 option in all cases to support dual-stack sockets.
+    // Don't bother checking the return code, as this is expected to fail if
+    // it's not actually dual-stack.
     ::setsockopt(s_, IPPROTO_IP, IP_TOS, (SockOptArg)&value, sizeof(value));
   }
 #endif
-  return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
+  int result =
+      ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value));
+  if (result != 0) {
+    UpdateLastError();
+  }
+  return result;
 }
 
 int PhysicalSocket::Send(const void* pv, size_t cb) {
diff --git a/rtc_base/random.h b/rtc_base/random.h
index 0e2d103..b3b9fd1 100644
--- a/rtc_base/random.h
+++ b/rtc_base/random.h
@@ -66,7 +66,8 @@
   double Exponential(double lambda);
 
  private:
-  // Outputs a nonzero 64-bit random number.
+  // Outputs a nonzero 64-bit random number using Xorshift algorithm.
+  // https://en.wikipedia.org/wiki/Xorshift
   uint64_t NextOutput() {
     state_ ^= state_ >> 12;
     state_ ^= state_ << 25;
diff --git a/rtc_base/rate_tracker.cc b/rtc_base/rate_tracker.cc
index 5c82792..e39dadb 100644
--- a/rtc_base/rate_tracker.cc
+++ b/rtc_base/rate_tracker.cc
@@ -108,14 +108,18 @@
 }
 
 void RateTracker::AddSamples(int64_t sample_count) {
+  AddSamplesAtTime(Time(), sample_count);
+}
+
+void RateTracker::AddSamplesAtTime(int64_t current_time_ms,
+                                   int64_t sample_count) {
   RTC_DCHECK_LE(0, sample_count);
   EnsureInitialized();
-  int64_t current_time = Time();
   // Advance the current bucket as needed for the current time, and reset
   // bucket counts as we advance.
-  for (size_t i = 0;
-       i <= bucket_count_ &&
-       current_time >= bucket_start_time_milliseconds_ + bucket_milliseconds_;
+  for (size_t i = 0; i <= bucket_count_ &&
+                     current_time_ms >=
+                         bucket_start_time_milliseconds_ + bucket_milliseconds_;
        ++i) {
     bucket_start_time_milliseconds_ += bucket_milliseconds_;
     current_bucket_ = NextBucketIndex(current_bucket_);
@@ -125,7 +129,8 @@
   // the entire buffer of samples has been expired.
   bucket_start_time_milliseconds_ +=
       bucket_milliseconds_ *
-      ((current_time - bucket_start_time_milliseconds_) / bucket_milliseconds_);
+      ((current_time_ms - bucket_start_time_milliseconds_) /
+       bucket_milliseconds_);
   // Add all samples in the bucket that includes the current time.
   sample_buckets_[current_bucket_] += sample_count;
   total_sample_count_ += sample_count;
diff --git a/rtc_base/rate_tracker.h b/rtc_base/rate_tracker.h
index e42d40f..3b3c235 100644
--- a/rtc_base/rate_tracker.h
+++ b/rtc_base/rate_tracker.h
@@ -47,6 +47,9 @@
   // these samples, and increments the count for that bucket by sample_count.
   void AddSamples(int64_t sample_count);
 
+  // Increment count for bucket at |current_time_ms|.
+  void AddSamplesAtTime(int64_t current_time_ms, int64_t sample_count);
+
  protected:
   // overrideable for tests
   virtual int64_t Time() const;
diff --git a/rtc_base/rtc_certificate_generator.cc b/rtc_base/rtc_certificate_generator.cc
index d95b645..5e1fdca 100644
--- a/rtc_base/rtc_certificate_generator.cc
+++ b/rtc_base/rtc_certificate_generator.cc
@@ -51,7 +51,7 @@
     expires_s = std::min(expires_s, kYearInSeconds);
     // TODO(torbjorng): Stop using |time_t|, its type is unspecified. It it safe
     // to assume it can hold up to a year's worth of seconds (and more), but
-    // |SSLIdentity::Generate| should stop relying on |time_t|.
+    // |SSLIdentity::Create| should stop relying on |time_t|.
     // See bugs.webrtc.org/5720.
     time_t cert_lifetime_s = static_cast<time_t>(expires_s);
     identity = SSLIdentity::Create(kIdentityName, key_params, cert_lifetime_s);
diff --git a/rtc_base/socket_address.h b/rtc_base/socket_address.h
index 6ee3d37..f459407 100644
--- a/rtc_base/socket_address.h
+++ b/rtc_base/socket_address.h
@@ -12,9 +12,9 @@
 #define RTC_BASE_SOCKET_ADDRESS_H_
 
 #include <string>
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
 #include <ostream>  // no-presubmit-check TODO(webrtc:8982)
-#endif              // UNIT_TEST
+#endif              // WEBRTC_UNIT_TEST
 #include "rtc_base/ip_address.h"
 #include "rtc_base/system/rtc_export.h"
 
@@ -127,12 +127,12 @@
   // Parses hostname:port and [hostname]:port.
   bool FromString(const std::string& str);
 
-#ifdef UNIT_TEST
+#ifdef WEBRTC_UNIT_TEST
   inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
       std::ostream& os) {           // no-presubmit-check TODO(webrtc:8982)
     return os << HostAsURIString() << ":" << port();
   }
-#endif  // UNIT_TEST
+#endif  // WEBRTC_UNIT_TEST
 
   // Determines whether this represents a missing / any IP address.
   // That is, 0.0.0.0 or ::.
diff --git a/rtc_base/ssl_certificate.cc b/rtc_base/ssl_certificate.cc
index db9097b..3f7013e 100644
--- a/rtc_base/ssl_certificate.cc
+++ b/rtc_base/ssl_certificate.cc
@@ -16,7 +16,12 @@
 
 #include "absl/algorithm/container.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/openssl_certificate.h"
+#include "rtc_base/openssl.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include "rtc_base/boringssl_identity.h"
+#else
+#include "rtc_base/openssl_identity.h"
+#endif
 #include "rtc_base/ssl_fingerprint.h"
 #include "rtc_base/third_party/base64/base64.h"
 
@@ -117,7 +122,11 @@
 // static
 std::unique_ptr<SSLCertificate> SSLCertificate::FromPEMString(
     const std::string& pem_string) {
+#ifdef OPENSSL_IS_BORINGSSL
+  return BoringSSLCertificate::FromPEMString(pem_string);
+#else
   return OpenSSLCertificate::FromPEMString(pem_string);
+#endif
 }
 
 }  // namespace rtc
diff --git a/rtc_base/ssl_identity.cc b/rtc_base/ssl_identity.cc
index 09d25d2..8d93ecf 100644
--- a/rtc_base/ssl_identity.cc
+++ b/rtc_base/ssl_identity.cc
@@ -11,12 +11,16 @@
 // Handling of certificates and keypairs for SSLStreamAdapter's peer mode.
 #include "rtc_base/ssl_identity.h"
 
+#include <openssl/ossl_typ.h>
 #include <string.h>
 #include <time.h>
-#include <string>
 
 #include "rtc_base/checks.h"
+#ifdef OPENSSL_IS_BORINGSSL
+#include "rtc_base/boringssl_identity.h"
+#else
 #include "rtc_base/openssl_identity.h"
+#endif
 #include "rtc_base/ssl_certificate.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/third_party/base64/base64.h"
@@ -213,28 +217,36 @@
 std::unique_ptr<SSLIdentity> SSLIdentity::Create(const std::string& common_name,
                                                  const KeyParams& key_param,
                                                  time_t certificate_lifetime) {
+#ifdef OPENSSL_IS_BORINGSSL
+  return BoringSSLIdentity::CreateWithExpiration(common_name, key_param,
+                                                 certificate_lifetime);
+#else
   return OpenSSLIdentity::CreateWithExpiration(common_name, key_param,
                                                certificate_lifetime);
+#endif
 }
 
 // static
 std::unique_ptr<SSLIdentity> SSLIdentity::Create(const std::string& common_name,
                                                  const KeyParams& key_param) {
-  return OpenSSLIdentity::CreateWithExpiration(
-      common_name, key_param, kDefaultCertificateLifetimeInSeconds);
+  return Create(common_name, key_param, kDefaultCertificateLifetimeInSeconds);
 }
 
 // static
 std::unique_ptr<SSLIdentity> SSLIdentity::Create(const std::string& common_name,
                                                  KeyType key_type) {
-  return OpenSSLIdentity::CreateWithExpiration(
-      common_name, KeyParams(key_type), kDefaultCertificateLifetimeInSeconds);
+  return Create(common_name, KeyParams(key_type),
+                kDefaultCertificateLifetimeInSeconds);
 }
 
 //  static
 std::unique_ptr<SSLIdentity> SSLIdentity::CreateForTest(
     const SSLIdentityParams& params) {
+#ifdef OPENSSL_IS_BORINGSSL
+  return BoringSSLIdentity::CreateForTest(params);
+#else
   return OpenSSLIdentity::CreateForTest(params);
+#endif
 }
 
 // Construct an identity from a private key and a certificate.
@@ -242,7 +254,11 @@
 std::unique_ptr<SSLIdentity> SSLIdentity::CreateFromPEMStrings(
     const std::string& private_key,
     const std::string& certificate) {
+#ifdef OPENSSL_IS_BORINGSSL
+  return BoringSSLIdentity::CreateFromPEMStrings(private_key, certificate);
+#else
   return OpenSSLIdentity::CreateFromPEMStrings(private_key, certificate);
+#endif
 }
 
 // Construct an identity from a private key and a certificate chain.
@@ -250,13 +266,23 @@
 std::unique_ptr<SSLIdentity> SSLIdentity::CreateFromPEMChainStrings(
     const std::string& private_key,
     const std::string& certificate_chain) {
+#ifdef OPENSSL_IS_BORINGSSL
+  return BoringSSLIdentity::CreateFromPEMChainStrings(private_key,
+                                                      certificate_chain);
+#else
   return OpenSSLIdentity::CreateFromPEMChainStrings(private_key,
                                                     certificate_chain);
+#endif
 }
 
 bool operator==(const SSLIdentity& a, const SSLIdentity& b) {
+#ifdef OPENSSL_IS_BORINGSSL
+  return static_cast<const BoringSSLIdentity&>(a) ==
+         static_cast<const BoringSSLIdentity&>(b);
+#else
   return static_cast<const OpenSSLIdentity&>(a) ==
          static_cast<const OpenSSLIdentity&>(b);
+#endif
 }
 bool operator!=(const SSLIdentity& a, const SSLIdentity& b) {
   return !(a == b);
diff --git a/rtc_base/ssl_identity_unittest.cc b/rtc_base/ssl_identity_unittest.cc
index 0d9d0fd..a907bfc 100644
--- a/rtc_base/ssl_identity_unittest.cc
+++ b/rtc_base/ssl_identity_unittest.cc
@@ -65,7 +65,7 @@
     0x35, 0xce, 0x26, 0x58, 0x4a, 0x33, 0x6d, 0xbc, 0xb6};
 
 // These PEM strings were created by generating an identity with
-// |SSLIdentity::Generate| and invoking |identity->PrivateKeyToPEMString()|,
+// |SSLIdentity::Create| and invoking |identity->PrivateKeyToPEMString()|,
 // |identity->PublicKeyToPEMString()| and
 // |identity->certificate().ToPEMString()|. If the crypto library is updated,
 // and the update changes the string form of the keys, these will have to be
@@ -406,6 +406,21 @@
   EXPECT_EQ(kECDSA_CERT_PEM, identity->certificate().ToPEMString());
 }
 
+TEST_F(SSLIdentityTest, FromPEMChainStrings) {
+  // This doesn't form a valid certificate chain, but that doesn't matter for
+  // the purposes of the test
+  std::string chain(kRSA_CERT_PEM);
+  chain.append(kTestCertificate);
+  std::unique_ptr<SSLIdentity> identity(
+      SSLIdentity::CreateFromPEMChainStrings(kRSA_PRIVATE_KEY_PEM, chain));
+  EXPECT_TRUE(identity);
+  EXPECT_EQ(kRSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString());
+  EXPECT_EQ(kRSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString());
+  ASSERT_EQ(2u, identity->cert_chain().GetSize());
+  EXPECT_EQ(kRSA_CERT_PEM, identity->cert_chain().Get(0).ToPEMString());
+  EXPECT_EQ(kTestCertificate, identity->cert_chain().Get(1).ToPEMString());
+}
+
 TEST_F(SSLIdentityTest, CloneIdentityRSA) {
   TestCloningIdentity(*identity_rsa1_);
   TestCloningIdentity(*identity_rsa2_);
diff --git a/rtc_base/ssl_stream_adapter_unittest.cc b/rtc_base/ssl_stream_adapter_unittest.cc
index 379acac..c580d83 100644
--- a/rtc_base/ssl_stream_adapter_unittest.cc
+++ b/rtc_base/ssl_stream_adapter_unittest.cc
@@ -508,8 +508,9 @@
     }
   }
 
-  // This tests that the handshake can complete before the identity is
-  // verified, and the identity will be verified after the fact.
+  // This tests that the handshake can complete before the identity is verified,
+  // and the identity will be verified after the fact. It also verifies that
+  // packets can't be read or written before the identity has been verified.
   void TestHandshakeWithDelayedIdentity(bool valid_identity) {
     server_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS);
     client_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS);
@@ -524,14 +525,9 @@
     }
 
     // Start the handshake
-    int rv;
-
     server_ssl_->SetServerRole();
-    rv = server_ssl_->StartSSL();
-    ASSERT_EQ(0, rv);
-
-    rv = client_ssl_->StartSSL();
-    ASSERT_EQ(0, rv);
+    ASSERT_EQ(0, server_ssl_->StartSSL());
+    ASSERT_EQ(0, client_ssl_->StartSSL());
 
     // Now run the handshake.
     EXPECT_TRUE_WAIT(
@@ -547,16 +543,57 @@
     EXPECT_EQ(rtc::SR_BLOCK, client_ssl_->Write(&packet, 1, &sent, 0));
     EXPECT_EQ(rtc::SR_BLOCK, server_ssl_->Write(&packet, 1, &sent, 0));
 
-    // If we set an invalid identity at this point, SetPeerCertificateDigest
-    // should return false.
-    SetPeerIdentitiesByDigest(valid_identity, valid_identity);
+    // Collect both of the certificate digests; needs to be done before calling
+    // SetPeerCertificateDigest as that may reset the identity.
+    unsigned char server_digest[20];
+    size_t server_digest_len;
+    unsigned char client_digest[20];
+    size_t client_digest_len;
+    bool rv;
+
+    rv = server_identity()->certificate().ComputeDigest(
+        rtc::DIGEST_SHA_1, server_digest, 20, &server_digest_len);
+    ASSERT_TRUE(rv);
+    rv = client_identity()->certificate().ComputeDigest(
+        rtc::DIGEST_SHA_1, client_digest, 20, &client_digest_len);
+    ASSERT_TRUE(rv);
+
+    if (!valid_identity) {
+      RTC_LOG(LS_INFO) << "Setting bogus digest for client/server certs";
+      client_digest[0]++;
+      server_digest[0]++;
+    }
+
+    // Set the peer certificate digest for the client.
+    rtc::SSLPeerCertificateDigestError err;
+    rtc::SSLPeerCertificateDigestError expected_err =
+        valid_identity
+            ? rtc::SSLPeerCertificateDigestError::NONE
+            : rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED;
+    rv = client_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, server_digest,
+                                               server_digest_len, &err);
+    EXPECT_EQ(expected_err, err);
+    EXPECT_EQ(valid_identity, rv);
     // State should then transition to SS_OPEN or SS_CLOSED based on validation
     // of the identity.
     if (valid_identity) {
       EXPECT_EQ(rtc::SS_OPEN, client_ssl_->GetState());
-      EXPECT_EQ(rtc::SS_OPEN, server_ssl_->GetState());
+      // If the client sends a packet while the server still hasn't verified the
+      // client identity, the server should continue to return SR_BLOCK.
+      EXPECT_EQ(rtc::SR_SUCCESS, client_ssl_->Write(&packet, 1, &sent, 0));
+      EXPECT_EQ(rtc::SR_BLOCK, server_ssl_->Read(&packet, 1, 0, 0));
     } else {
       EXPECT_EQ(rtc::SS_CLOSED, client_ssl_->GetState());
+    }
+
+    // Set the peer certificate digest for the server.
+    rv = server_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, client_digest,
+                                               client_digest_len, &err);
+    EXPECT_EQ(expected_err, err);
+    EXPECT_EQ(valid_identity, rv);
+    if (valid_identity) {
+      EXPECT_EQ(rtc::SS_OPEN, server_ssl_->GetState());
+    } else {
       EXPECT_EQ(rtc::SS_CLOSED, server_ssl_->GetState());
     }
   }
diff --git a/rtc_base/system/BUILD.gn b/rtc_base/system/BUILD.gn
index bf8cf94..385f2e1 100644
--- a/rtc_base/system/BUILD.gn
+++ b/rtc_base/system/BUILD.gn
@@ -55,6 +55,11 @@
   ]
 }
 
+rtc_source_set("no_unique_address") {
+  sources = [ "no_unique_address.h" ]
+  deps = [ "..:sanitizer" ]
+}
+
 if (is_mac || is_ios) {
   rtc_library("cocoa_threading") {
     sources = [
diff --git a/rtc_base/system/arch.h b/rtc_base/system/arch.h
index ed216e6..be2367b 100644
--- a/rtc_base/system/arch.h
+++ b/rtc_base/system/arch.h
@@ -15,8 +15,9 @@
 #define RTC_BASE_SYSTEM_ARCH_H_
 
 // Processor architecture detection.  For more info on what's defined, see:
-//   http://msdn.microsoft.com/en-us/library/b0084kay.aspx
-//   http://www.agner.org/optimize/calling_conventions.pdf
+//   https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+//   https://www.agner.org/optimize/calling_conventions.pdf
+//   https://sourceforge.net/p/predef/wiki/Architectures/
 //   or with gcc, run: "echo | gcc -E -dM -"
 #if defined(_M_X64) || defined(__x86_64__)
 #define WEBRTC_ARCH_X86_FAMILY
@@ -32,17 +33,45 @@
 #define WEBRTC_ARCH_X86
 #define WEBRTC_ARCH_32_BITS
 #define WEBRTC_ARCH_LITTLE_ENDIAN
-#elif defined(__ARMEL__)
+#elif defined(_M_ARM) || defined(__ARMEL__)
 #define WEBRTC_ARCH_ARM_FAMILY
 #define WEBRTC_ARCH_32_BITS
 #define WEBRTC_ARCH_LITTLE_ENDIAN
-#elif defined(__MIPSEL__)
+#elif defined(__MIPSEL__) || defined(__MIPSEB__)
 #define WEBRTC_ARCH_MIPS_FAMILY
 #if defined(__LP64__)
 #define WEBRTC_ARCH_64_BITS
 #else
 #define WEBRTC_ARCH_32_BITS
 #endif
+#if defined(__MIPSEL__)
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#else
+#define WEBRTC_ARCH_BIG_ENDIAN
+#endif
+#elif defined(__PPC__)
+#if defined(__PPC64__)
+#define WEBRTC_ARCH_64_BITS
+#else
+#define WEBRTC_ARCH_32_BITS
+#endif
+#if defined(__LITTLE_ENDIAN__)
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#else
+#define WEBRTC_ARCH_BIG_ENDIAN
+#endif
+#elif defined(__sparc) || defined(__sparc__)
+#if __SIZEOF_LONG__ == 8
+#define WEBRTC_ARCH_64_BITS
+#else
+#define WEBRTC_ARCH_32_BITS
+#endif
+#define WEBRTC_ARCH_BIG_ENDIAN
+#elif defined(__riscv) && __riscv_xlen == 64
+#define WEBRTC_ARCH_64_BITS
+#define WEBRTC_ARCH_LITTLE_ENDIAN
+#elif defined(__riscv) && __riscv_xlen == 32
+#define WEBRTC_ARCH_32_BITS
 #define WEBRTC_ARCH_LITTLE_ENDIAN
 #elif defined(__pnacl__)
 #define WEBRTC_ARCH_32_BITS
diff --git a/rtc_base/system/no_unique_address.h b/rtc_base/system/no_unique_address.h
new file mode 100644
index 0000000..eca349c
--- /dev/null
+++ b/rtc_base/system/no_unique_address.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_SYSTEM_NO_UNIQUE_ADDRESS_H_
+#define RTC_BASE_SYSTEM_NO_UNIQUE_ADDRESS_H_
+
+#include "rtc_base/sanitizer.h"
+
+// RTC_NO_UNIQUE_ADDRESS is a portable annotation to tell the compiler that
+// a data member need not have an address distinct from all other non-static
+// data members of its class.
+// It allows empty types to actually occupy zero bytes as class members,
+// instead of occupying at least one byte just so that they get their own
+// address. There is almost never any reason not to use it on class members
+// that could possibly be empty.
+// The macro expands to [[no_unique_address]] if the compiler supports the
+// attribute, it expands to nothing otherwise.
+// Clang should supports this attribute since C++11, while other compilers
+// should add support for it starting from C++20. Among clang compilers,
+// clang-cl doesn't support it yet and support is unclear also when the target
+// platform is iOS.
+//
+// TODO(bugs.webrtc.org/12218): Re-enable on MSan builds.
+#if !RTC_HAS_MSAN &&                                                       \
+    ((defined(__clang__) && !defined(_MSC_VER) && !defined(WEBRTC_IOS)) || \
+     __cplusplus > 201703L)
+// NOLINTNEXTLINE(whitespace/braces)
+#define RTC_NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+#define RTC_NO_UNIQUE_ADDRESS
+#endif
+
+#endif  // RTC_BASE_SYSTEM_NO_UNIQUE_ADDRESS_H_
diff --git a/rtc_base/task_utils/BUILD.gn b/rtc_base/task_utils/BUILD.gn
index 54f9a04..018844f 100644
--- a/rtc_base/task_utils/BUILD.gn
+++ b/rtc_base/task_utils/BUILD.gn
@@ -38,6 +38,7 @@
     "..:thread_checker",
     "../../api:scoped_refptr",
     "../synchronization:sequence_checker",
+    "../system:no_unique_address",
   ]
 }
 
diff --git a/rtc_base/task_utils/pending_task_safety_flag.h b/rtc_base/task_utils/pending_task_safety_flag.h
index 580fb3f..182db2c 100644
--- a/rtc_base/task_utils/pending_task_safety_flag.h
+++ b/rtc_base/task_utils/pending_task_safety_flag.h
@@ -15,6 +15,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/ref_count.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 
 namespace webrtc {
 
@@ -58,7 +59,7 @@
 
  private:
   bool alive_ = true;
-  SequenceChecker main_sequence_;
+  RTC_NO_UNIQUE_ADDRESS SequenceChecker main_sequence_;
 };
 
 // Makes using PendingTaskSafetyFlag very simple. Automatic PTSF creation
diff --git a/rtc_base/virtual_socket_server.cc b/rtc_base/virtual_socket_server.cc
index 3d412d6..804dc75 100644
--- a/rtc_base/virtual_socket_server.cc
+++ b/rtc_base/virtual_socket_server.cc
@@ -221,10 +221,11 @@
       }
       delete data;
     }
-    // Clear incoming packets and disconnect messages
-    if (server_->msg_queue_) {
-      server_->msg_queue_->Clear(this);
-    }
+  }
+
+  // Clear incoming packets and disconnect messages
+  if (server_->msg_queue_) {
+    server_->msg_queue_->Clear(this);
   }
 
   state_ = CS_CLOSED;
diff --git a/rtc_base/virtual_socket_server.h b/rtc_base/virtual_socket_server.h
index f33ebcc..84f8fb1 100644
--- a/rtc_base/virtual_socket_server.h
+++ b/rtc_base/virtual_socket_server.h
@@ -305,7 +305,7 @@
 // Implements the socket interface using the virtual network.  Packets are
 // passed as messages using the message queue of the socket server.
 class VirtualSocket : public AsyncSocket,
-                      public MessageHandlerAutoCleanup,
+                      public MessageHandler,
                       public sigslot::has_slots<> {
  public:
   VirtualSocket(VirtualSocketServer* server, int family, int type, bool async);
diff --git a/rtc_base/weak_ptr.h b/rtc_base/weak_ptr.h
index 8b2ba09..68d57fc 100644
--- a/rtc_base/weak_ptr.h
+++ b/rtc_base/weak_ptr.h
@@ -18,6 +18,7 @@
 #include "rtc_base/ref_count.h"
 #include "rtc_base/ref_counted_object.h"
 #include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
 
 // The implementation is borrowed from chromium except that it does not
 // implement SupportsWeakPtr.
@@ -103,7 +104,7 @@
 
     ~Flag() override;
 
-    ::webrtc::SequenceChecker checker_;
+    RTC_NO_UNIQUE_ADDRESS ::webrtc::SequenceChecker checker_;
     bool is_valid_;
   };
 
diff --git a/rtc_base/win/create_direct3d_device.cc b/rtc_base/win/create_direct3d_device.cc
new file mode 100644
index 0000000..02fe340
--- /dev/null
+++ b/rtc_base/win/create_direct3d_device.cc
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/win/create_direct3d_device.h"
+
+#include <libloaderapi.h>
+#include <utility>
+
+namespace {
+
+FARPROC LoadD3D11Function(const char* function_name) {
+  static HMODULE const handle =
+      ::LoadLibraryExW(L"d3d11.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+  return handle ? ::GetProcAddress(handle, function_name) : nullptr;
+}
+
+decltype(&::CreateDirect3D11DeviceFromDXGIDevice)
+GetCreateDirect3D11DeviceFromDXGIDevice() {
+  static decltype(&::CreateDirect3D11DeviceFromDXGIDevice) const function =
+      reinterpret_cast<decltype(&::CreateDirect3D11DeviceFromDXGIDevice)>(
+          LoadD3D11Function("CreateDirect3D11DeviceFromDXGIDevice"));
+  return function;
+}
+
+}  // namespace
+
+namespace webrtc {
+
+bool ResolveCoreWinRTDirect3DDelayload() {
+  return GetCreateDirect3D11DeviceFromDXGIDevice();
+}
+
+HRESULT CreateDirect3DDeviceFromDXGIDevice(
+    IDXGIDevice* dxgi_device,
+    ABI::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice**
+        out_d3d11_device) {
+  decltype(&::CreateDirect3D11DeviceFromDXGIDevice) create_d3d11_device_func =
+      GetCreateDirect3D11DeviceFromDXGIDevice();
+  if (!create_d3d11_device_func)
+    return E_FAIL;
+
+  Microsoft::WRL::ComPtr<IInspectable> inspectableSurface;
+  HRESULT hr = create_d3d11_device_func(dxgi_device, &inspectableSurface);
+  if (FAILED(hr))
+    return hr;
+
+  return inspectableSurface->QueryInterface(IID_PPV_ARGS(out_d3d11_device));
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/win/create_direct3d_device.h b/rtc_base/win/create_direct3d_device.h
new file mode 100644
index 0000000..102f741
--- /dev/null
+++ b/rtc_base/win/create_direct3d_device.h
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef RTC_BASE_WIN_CREATE_DIRECT3D_DEVICE_H_
+#define RTC_BASE_WIN_CREATE_DIRECT3D_DEVICE_H_
+
+#include <windows.graphics.capture.interop.h>
+#include <windows.graphics.directX.direct3d11.interop.h>
+#include <winerror.h>
+#include <wrl/client.h>
+
+namespace webrtc {
+
+// Callers must check the return value of ResolveCoreWinRTDirect3DDelayload()
+// before using CreateDirect3DDeviceFromDXGIDevice().
+bool ResolveCoreWinRTDirect3DDelayload();
+
+// Allows for the creating of Direct3D Devices from a DXGI device on versions
+// of Windows greater than Win7.
+HRESULT CreateDirect3DDeviceFromDXGIDevice(
+    IDXGIDevice* dxgi_device,
+    ABI::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice**
+        out_d3d11_device);
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_WIN_CREATE_DIRECT3D_DEVICE_H_
diff --git a/rtc_base/win/get_activation_factory.h b/rtc_base/win/get_activation_factory.h
index 801f39d..08f602f 100644
--- a/rtc_base/win/get_activation_factory.h
+++ b/rtc_base/win/get_activation_factory.h
@@ -40,8 +40,10 @@
     return hr;
 
   hr = RoGetActivationFactoryProxy(class_id_hstring, IID_PPV_ARGS(factory));
-  if (FAILED(hr))
+  if (FAILED(hr)) {
+    DeleteHstring(class_id_hstring);
     return hr;
+  }
 
   return DeleteHstring(class_id_hstring);
 }
diff --git a/rtc_base/win/scoped_com_initializer.cc b/rtc_base/win/scoped_com_initializer.cc
index b83ad32..81079fb 100644
--- a/rtc_base/win/scoped_com_initializer.cc
+++ b/rtc_base/win/scoped_com_initializer.cc
@@ -10,6 +10,9 @@
 
 #include "rtc_base/win/scoped_com_initializer.h"
 
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
 namespace webrtc {
 
 ScopedCOMInitializer::ScopedCOMInitializer() {
diff --git a/rtc_base/win/scoped_com_initializer.h b/rtc_base/win/scoped_com_initializer.h
index 918812f..2427097 100644
--- a/rtc_base/win/scoped_com_initializer.h
+++ b/rtc_base/win/scoped_com_initializer.h
@@ -13,8 +13,6 @@
 
 #include <comdef.h>
 
-#include "rtc_base/logging.h"
-
 namespace webrtc {
 
 // Initializes COM in the constructor (STA or MTA), and uninitializes COM in the