Uprev to branch-heads/74

To commit
'Merge to M74: Revert "Remove rtc::TimeMillis() call from ALR detector."'

https://webrtc.googlesource.com/src/+/303fc7963064a46a27e8287e531ded8cec21ff77

Existing aec.ini config files should be modified base on the parameters
change as below:

Added:

AEC_DELAY_DELAY_HEADROOM_SAMPLES "delay:delay_headroom_samples"
AEC_DELAY_HYSTERESIS_LIMIT_BLOCKS "delay:hysteresis_limit_blocks"
AEC_EP_STRENGTH_DEFAULT_GAIN "ep_strength:default_gain"

Removed:

AEC_BUFFERING_USE_NEW_RENDER_BUFFERING "buffering:use_new_render_buffering"
AEC_DELAY_API_CALL_JITTER_BLOCKS "delay:api_call_jitter_blocks"
AEC_DELAY_MIN_ECHO_PATH_DELAY_BLOCKS "delay:min_echo_path_delay_blocks"
AEC_DELAY_DELAY_HEADROOM_BLOCKS "delay:delay_headroom_blocks"
AEC_DELAY_HYSTERESIS_LIMIT_1_BLOCKS "delay:hysteresis_limit_1_blocks"
AEC_DELAY_HYSTERESIS_LIMIT_2_BLOCKS "delay:hysteresis_limit_2_blocks"
AEC_DELAY_SKEW_HYSTERESIS_BLOCKS "delay:skew_hysteresis_blocks"
AEC_EP_STRENGTH_LF "ep_strength:lf"
AEC_EP_STRENGTH_MF "ep_strength:mf"
AEC_EP_STRENGTH_HF "ep_strength:hf"
AEC_ECHO_REMOVAL_CTL_INITIAL_GAIN "echo_removal_control:initial_gain"
AEC_ECHO_REMOVAL_CTL_FIRST_NON_ZERO_GAIN "echo_removal_control:first_non_zero_gain"
AEC_ECHO_REMOVAL_CTL_NON_ZERO_GAIN_BLOCKS "echo_removal_control:non_zero_gain_blocks"
AEC_ECHO_REMOVAL_CTL_FULL_GAIN_BLOCKS "echo_removal_control:full_gain_blocks"

BUG=chromium:947914
TEST=emerge-atlas webrtc-apm
CQ-DEPEND=CL:1545342

Change-Id: Ifb701bfc14844c32b8d7561c4b48fd61be3f7157
Reviewed-on: https://chromium-review.googlesource.com/1545814
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Hsinyu Chao <hychao@chromium.org>
Reviewed-by: Per Ã…hgren <peah@chromium.org>
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index edd0274..8e3c177 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt
index 1d09b19..bba0f3e 100644
--- a/absl/CMakeLists.txt
+++ b/absl/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index d04dc71..8d266db 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index fdf45c5..c51eb10 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,50 +14,50 @@
 # limitations under the License.
 #
 
-list(APPEND ALGORITHM_PUBLIC_HEADERS
-  "algorithm.h"
-  "container.h"
-)
-
-
-#
-## TESTS
-#
-
-# test algorithm_test
-list(APPEND ALGORITHM_TEST_SRC
-  "algorithm_test.cc"
-  ${ALGORITHM_PUBLIC_HEADERS}
-  ${ALGORITHM_INTERNAL_HEADERS}
-)
-
-absl_header_library(
-  TARGET
-    absl_algorithm
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     algorithm
+  HDRS
+    "algorithm.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
 )
 
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     algorithm_test
-  SOURCES
-    ${ALGORITHM_TEST_SRC}
-  PUBLIC_LIBRARIES
+  SRCS
+    "algorithm_test.cc"
+  DEPS
     absl::algorithm
+    gmock_main
 )
 
-
-
-
-# test container_test
-set(CONTAINER_TEST_SRC "container_test.cc")
-
-absl_test(
-  TARGET
-    container_test
-  SOURCES
-    ${CONTAINER_TEST_SRC}
-  PUBLIC_LIBRARIES
+absl_cc_library(
+  NAME
+    algorithm_container
+  HDRS
+    "container.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
     absl::algorithm
+    absl::core_headers
+    absl::meta
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    container_test
+  SRCS
+    "container_test.cc"
+  DEPS
+    absl::algorithm_container
+    absl::base
+    absl::core_headers
+    absl::memory
+    absl::span
+    gmock_main
 )
diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h
index 3d65864..bb90215 100644
--- a/absl/algorithm/algorithm.h
+++ b/absl/algorithm/algorithm.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -94,7 +94,7 @@
 // then the predicate is never invoked and the function returns false.
 //
 // This is a C++11-compatible implementation of C++14 `std::equal`.  See
-// http://en.cppreference.com/w/cpp/algorithm/equal for more information.
+// https://en.cppreference.com/w/cpp/algorithm/equal for more information.
 template <typename InputIter1, typename InputIter2, typename Pred>
 bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
            InputIter2 last2, Pred&& pred) {
diff --git a/absl/algorithm/algorithm_test.cc b/absl/algorithm/algorithm_test.cc
index e4322bc..81fccb6 100644
--- a/absl/algorithm/algorithm_test.cc
+++ b/absl/algorithm/algorithm_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 53ab156..752e47b 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -36,7 +36,6 @@
 // For template parameter and variable naming, `C` indicates the container type
 // to which the function is applied, `Pred` indicates the predicate object type
 // to be used by the function and `T` indicates the applicable element type.
-//
 
 #ifndef ABSL_ALGORITHM_CONTAINER_H_
 #define ABSL_ALGORITHM_CONTAINER_H_
@@ -46,6 +45,8 @@
 #include <iterator>
 #include <numeric>
 #include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -54,7 +55,6 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
-
 namespace container_algorithm_internal {
 
 // NOTE: it is important to defer to ADL lookup for building with C++ modules,
@@ -101,6 +101,17 @@
 template <typename C>
 ContainerIter<C> c_end(C& c) { return end(c); }
 
+template <typename T>
+struct IsUnorderedContainer : std::false_type {};
+
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+    std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
+    : std::true_type {};
+
 }  // namespace container_algorithm_internal
 
 // PUBLIC API
@@ -636,7 +647,6 @@
 // and `unique()` are omitted, because it's not clear whether or not such
 // functions should call erase on their supplied sequences afterwards. Either
 // behavior would be surprising for a different set of users.
-//
 
 // c_remove_copy()
 //
@@ -1154,7 +1164,13 @@
 // Container-based version of the <algorithm> `std::set_union()` function
 // to return an iterator containing the union of two containers; duplicate
 // values are not copied into the output.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
   return std::set_union(container_algorithm_internal::c_begin(c1),
                         container_algorithm_internal::c_end(c1),
@@ -1164,7 +1180,13 @@
 
 // Overload of c_set_union() for performing a merge using a `comp` other than
 // `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
                            Compare&& comp) {
   return std::set_union(container_algorithm_internal::c_begin(c1),
@@ -1178,7 +1200,13 @@
 //
 // Container-based version of the <algorithm> `std::set_intersection()` function
 // to return an iterator containing the intersection of two containers.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_intersection(const C1& c1, const C2& c2,
                                   OutputIterator output) {
   return std::set_intersection(container_algorithm_internal::c_begin(c1),
@@ -1189,7 +1217,13 @@
 
 // Overload of c_set_intersection() for performing a merge using a `comp` other
 // than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_intersection(const C1& c1, const C2& c2,
                                   OutputIterator output, Compare&& comp) {
   return std::set_intersection(container_algorithm_internal::c_begin(c1),
@@ -1204,7 +1238,13 @@
 // Container-based version of the <algorithm> `std::set_difference()` function
 // to return an iterator containing elements present in the first container but
 // not in the second.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_difference(const C1& c1, const C2& c2,
                                 OutputIterator output) {
   return std::set_difference(container_algorithm_internal::c_begin(c1),
@@ -1215,7 +1255,13 @@
 
 // Overload of c_set_difference() for performing a merge using a `comp` other
 // than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_difference(const C1& c1, const C2& c2,
                                 OutputIterator output, Compare&& comp) {
   return std::set_difference(container_algorithm_internal::c_begin(c1),
@@ -1230,7 +1276,13 @@
 // Container-based version of the <algorithm> `std::set_symmetric_difference()`
 // function to return an iterator containing elements present in either one
 // container or the other, but not both.
-template <typename C1, typename C2, typename OutputIterator>
+template <typename C1, typename C2, typename OutputIterator,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
                                           OutputIterator output) {
   return std::set_symmetric_difference(
@@ -1242,7 +1294,13 @@
 
 // Overload of c_set_symmetric_difference() for performing a merge using a
 // `comp` other than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename Compare>
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C1>::value,
+              void>::type,
+          typename = typename std::enable_if<
+              !container_algorithm_internal::IsUnorderedContainer<C2>::value,
+              void>::type>
 OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
                                           OutputIterator output,
                                           Compare&& comp) {
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 1502b17..04282b8 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/algorithm/equal_benchmark.cc b/absl/algorithm/equal_benchmark.cc
index 19c0780..7bf62c9 100644
--- a/absl/algorithm/equal_benchmark.cc
+++ b/absl/algorithm/equal_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index f7d8101..804f62a 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
@@ -67,6 +67,7 @@
     name = "core_headers",
     hdrs = [
         "attributes.h",
+        "const_init.h",
         "macros.h",
         "optimization.h",
         "port.h",
@@ -75,7 +76,6 @@
     copts = ABSL_DEFAULT_COPTS,
     deps = [
         ":config",
-        ":dynamic_annotations",
     ],
 )
 
@@ -89,6 +89,10 @@
         "internal/low_level_alloc.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
+    linkopts = select({
+        "//absl:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
     visibility = [
         "//absl:__subpackages__",
     ],
@@ -108,6 +112,7 @@
         "internal/identity.h",
         "internal/inline_variable.h",
         "internal/invoke.h",
+        "internal/scheduling_mode.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     visibility = [
@@ -141,6 +146,10 @@
         "log_severity.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
+    linkopts = select({
+        "//absl:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
     deps = [
         ":base_internal",
         ":config",
@@ -188,7 +197,6 @@
     deps = [
         ":base",
         ":config",
-        ":core_headers",
     ],
 )
 
@@ -231,13 +239,12 @@
     copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
     linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
     deps = [
-        ":base",
         ":config",
         ":pretty_function",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/strings",
-        "//absl/types:optional",
+        "//absl/utility",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -316,6 +323,33 @@
 )
 
 cc_library(
+    name = "spinlock_benchmark_common",
+    testonly = 1,
+    srcs = ["internal/spinlock_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = [
+        "//absl/base:__pkg__",
+    ],
+    deps = [
+        ":base",
+        ":base_internal",
+        "//absl/synchronization",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+    alwayslink = 1,
+)
+
+cc_binary(
+    name = "spinlock_benchmark",
+    testonly = 1,
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":spinlock_benchmark_common",
+    ],
+)
+
+cc_library(
     name = "endian",
     hdrs = [
         "internal/endian.h",
@@ -397,10 +431,6 @@
     size = "small",
     srcs = ["internal/low_level_alloc_test.cc"],
     copts = ABSL_TEST_COPTS,
-    linkopts = select({
-        "//absl:windows": [],
-        "//conditions:default": ["-pthread"],
-    }),
     tags = ["no_test_ios_x86_64"],
     deps = [":malloc_internal"],
 )
@@ -410,10 +440,6 @@
     size = "small",
     srcs = ["internal/thread_identity_test.cc"],
     copts = ABSL_TEST_COPTS,
-    linkopts = select({
-        "//absl:windows": [],
-        "//conditions:default": ["-pthread"],
-    }),
     tags = [
         "no_test_wasm",
     ],
@@ -457,3 +483,25 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "scoped_set_env",
+    testonly = 1,
+    srcs = ["internal/scoped_set_env.cc"],
+    hdrs = ["internal/scoped_set_env.h"],
+    visibility = [
+        "//absl:__subpackages__",
+    ],
+    deps = [":base"],
+)
+
+cc_test(
+    name = "scoped_set_env_test",
+    size = "small",
+    srcs = ["internal/scoped_set_env_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        ":scoped_set_env",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/base/BUILD.gn b/absl/base/BUILD.gn
index 6c540f3..c7fa3f3 100644
--- a/absl/base/BUILD.gn
+++ b/absl/base/BUILD.gn
@@ -88,6 +88,7 @@
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   public = [
     "attributes.h",
+    "const_init.h",
     "macros.h",
     "optimization.h",
     "port.h",
@@ -95,7 +96,6 @@
   ]
   deps = [
     ":config",
-    ":dynamic_annotations",
   ]
 }
 
@@ -136,6 +136,7 @@
     "internal/identity.h",
     "internal/inline_variable.h",
     "internal/invoke.h",
+    "internal/scheduling_mode.h",
   ]
   visibility = []
   visibility += [ "../*" ]
@@ -196,7 +197,6 @@
   deps = [
     ":base",
     ":config",
-    ":core_headers",
   ]
   visibility = []
   visibility += [ "../*" ]
@@ -251,13 +251,12 @@
 #     "internal/exception_safety_testing.h",
 #   ]
 #   deps = [
-#     ":base",
 #     ":config",
 #     ":pretty_function",
 #     "../memory",
 #     "../meta:type_traits",
 #     "../strings",
-#     "../types:optional",
+#     "../utility",
 #     "//testing/gtest",
 #   ]
 # }
@@ -314,3 +313,23 @@
   visibility = []
   visibility += [ "../*" ]
 }
+
+source_set("scoped_set_env") {
+  testonly = true
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public = [
+    "internal/scoped_set_env.h",
+  ]
+  sources = [
+    "internal/scoped_set_env.cc",
+  ]
+  deps = [
+    ":base",
+  ]
+  visibility = []
+  visibility += [ "../*" ]
+}
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 04a6eb3..d8a311c 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#    http://www.apache.org/licenses/LICENSE-2.0
+#    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,
@@ -14,374 +14,427 @@
 # limitations under the License.
 #
 
-list(APPEND BASE_PUBLIC_HEADERS
-  "attributes.h"
-  "call_once.h"
-  "casts.h"
-  "config.h"
-  "dynamic_annotations.h"
-  "log_severity.h"
-  "macros.h"
-  "optimization.h"
-  "policy_checks.h"
-  "port.h"
-  "thread_annotations.h"
+absl_cc_library(
+  NAME
+    spinlock_wait
+  HDRS
+    "internal/scheduling_mode.h"
+    "internal/spinlock_wait.h"
+  SRCS
+    "internal/spinlock_akaros.inc"
+    "internal/spinlock_linux.inc"
+    "internal/spinlock_posix.inc"
+    "internal/spinlock_wait.cc"
+    "internal/spinlock_win32.inc"
+  DEPS
+    absl::core_headers
 )
 
-
-list(APPEND BASE_INTERNAL_HEADERS
-  "internal/atomic_hook.h"
-  "internal/bits.h"
-  "internal/cycleclock.h"
-  "internal/direct_mmap.h"
-  "internal/endian.h"
-  "internal/exception_testing.h"
-  "internal/exception_safety_testing.h"
-  "internal/hide_ptr.h"
-  "internal/identity.h"
-  "internal/invoke.h"
-  "internal/inline_variable.h"
-  "internal/low_level_alloc.h"
-  "internal/low_level_scheduling.h"
-  "internal/per_thread_tls.h"
-  "internal/pretty_function.h"
-  "internal/raw_logging.h"
-  "internal/scheduling_mode.h"
-  "internal/spinlock.h"
-  "internal/spinlock_wait.h"
-  "internal/sysinfo.h"
-  "internal/thread_identity.h"
-  "internal/throw_delegate.h"
-  "internal/tsan_mutex_interface.h"
-  "internal/unaligned_access.h"
-  "internal/unscaledcycleclock.h"
+absl_cc_library(
+  NAME
+    config
+  HDRS
+    "config.h"
+    "policy_checks.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
 )
 
-
-# absl_base main library
-list(APPEND BASE_SRC
-  "internal/cycleclock.cc"
-  "internal/raw_logging.cc"
-  "internal/spinlock.cc"
-  "internal/sysinfo.cc"
-  "internal/thread_identity.cc"
-  "internal/unscaledcycleclock.cc"
-  "internal/low_level_alloc.cc"
-  ${BASE_PUBLIC_HEADERS}
-  ${BASE_INTERNAL_HEADERS}
+absl_cc_library(
+  NAME
+    dynamic_annotations
+  HDRS
+    "dynamic_annotations.h"
+  SRCS
+    "dynamic_annotations.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEFINES
+    "__CLANG_SUPPORT_DYN_ANNOTATION__"
+  PUBLIC
 )
 
-absl_library(
-  TARGET
-    absl_base
-  SOURCES
-    ${BASE_SRC}
-  PUBLIC_LIBRARIES
-    absl_dynamic_annotations
-    absl_spinlock_wait
-  EXPORT_NAME
-    base
+absl_cc_library(
+  NAME
+    core_headers
+  HDRS
+    "attributes.h"
+    "const_init.h"
+    "macros.h"
+    "optimization.h"
+    "port.h"
+    "thread_annotations.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
 )
 
-# throw delegate library
-set(THROW_DELEGATE_SRC "internal/throw_delegate.cc")
-
-absl_library(
-  TARGET
-    absl_throw_delegate
-  SOURCES
-    ${THROW_DELEGATE_SRC}
-  PUBLIC_LIBRARIES
-    ${THROW_DELEGATE_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-  EXPORT_NAME
-    throw_delegate
-)
-
-if(BUILD_TESTING)
-  # exception-safety testing library
-  set(EXCEPTION_SAFETY_TESTING_SRC
-    "internal/exception_safety_testing.h"
-    "internal/exception_safety_testing.cc"
-  )
-  set(EXCEPTION_SAFETY_TESTING_PUBLIC_LIBRARIES
-    ${ABSL_TEST_COMMON_LIBRARIES}
+absl_cc_library(
+  NAME
+    malloc_internal
+  HDRS
+    "internal/direct_mmap.h"
+    "internal/low_level_alloc.h"
+  SRCS
+    "internal/low_level_alloc.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
     absl::base
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::spinlock_wait
+)
+
+absl_cc_library(
+  NAME
+    base_internal
+  HDRS
+    "internal/hide_ptr.h"
+    "internal/identity.h"
+    "internal/inline_variable.h"
+    "internal/invoke.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    base
+  HDRS
+    "call_once.h"
+    "casts.h"
+    "internal/atomic_hook.h"
+    "internal/cycleclock.h"
+    "internal/low_level_scheduling.h"
+    "internal/per_thread_tls.h"
+    "internal/raw_logging.h"
+    "internal/spinlock.h"
+    "internal/sysinfo.h"
+    "internal/thread_identity.h"
+    "internal/tsan_mutex_interface.h"
+    "internal/unscaledcycleclock.h"
+    "log_severity.h"
+  SRCS
+    "internal/cycleclock.cc"
+    "internal/raw_logging.cc"
+    "internal/spinlock.cc"
+    "internal/sysinfo.cc"
+    "internal/thread_identity.cc"
+    "internal/unscaledcycleclock.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base_internal
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::spinlock_wait
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    throw_delegate
+  HDRS
+    "internal/throw_delegate.h"
+  SRCS
+    "internal/throw_delegate.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  DEPS
+    absl::base
+)
+
+absl_cc_library(
+  NAME
+    exception_testing
+  HDRS
+    "internal/exception_testing.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    gtest
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    pretty_function
+  HDRS
+    "internal/pretty_function.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    exception_safety_testing
+  HDRS
+    "internal/exception_safety_testing.h"
+  SRCS
+    "internal/exception_safety_testing.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::config
+    absl::pretty_function
     absl::memory
     absl::meta
     absl::strings
-    absl::optional
+    absl::utility
     gtest
-  )
-
-absl_library(
-  TARGET
-    absl_base_internal_exception_safety_testing
-  SOURCES
-    ${EXCEPTION_SAFETY_TESTING_SRC}
-  PUBLIC_LIBRARIES
-    ${EXCEPTION_SAFETY_TESTING_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-)
-endif()
-
-
-# dynamic_annotations library
-set(DYNAMIC_ANNOTATIONS_SRC "dynamic_annotations.cc")
-
-absl_library(
-  TARGET
-    absl_dynamic_annotations
-  SOURCES
-    ${DYNAMIC_ANNOTATIONS_SRC}
+  TESTONLY
 )
 
-
-# spinlock_wait library
-set(SPINLOCK_WAIT_SRC "internal/spinlock_wait.cc")
-
-absl_library(
-  TARGET
-    absl_spinlock_wait
-  SOURCES
-    ${SPINLOCK_WAIT_SRC}
-)
-
-
-# malloc_internal library
-list(APPEND MALLOC_INTERNAL_SRC
-  "internal/low_level_alloc.cc"
-)
-
-absl_library(
-  TARGET
-    absl_malloc_internal
-  SOURCES
-    ${MALLOC_INTERNAL_SRC}
-  PUBLIC_LIBRARIES
-    absl_dynamic_annotations
-)
-
-
-
-#
-## TESTS
-#
-
-# call once test
-set(ATOMIC_HOOK_TEST_SRC "internal/atomic_hook_test.cc")
-set(ATOMIC_HOOK_TEST_PUBLIC_LIBRARIES absl::base)
-
-absl_test(
-  TARGET
-    atomic_hook_test
-  SOURCES
-    ${ATOMIC_HOOK_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ATOMIC_HOOK_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# call once test
-set(CALL_ONCE_TEST_SRC "call_once_test.cc")
-set(CALL_ONCE_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    call_once_test
-  SOURCES
-    ${CALL_ONCE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CALL_ONCE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test bit_cast_test
-set(BIT_CAST_TEST_SRC "bit_cast_test.cc")
-
-absl_test(
-  TARGET
-    bit_cast_test
-  SOURCES
-    ${BIT_CAST_TEST_SRC}
-)
-
-
-# test absl_throw_delegate_test
-set(THROW_DELEGATE_TEST_SRC "throw_delegate_test.cc")
-set(THROW_DELEGATE_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate)
-
-absl_test(
-  TARGET
-    throw_delegate_test
-  SOURCES
-    ${THROW_DELEGATE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${THROW_DELEGATE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test invoke_test
-set(INVOKE_TEST_SRC "invoke_test.cc")
-set(INVOKE_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    invoke_test
-  SOURCES
-    ${INVOKE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INVOKE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test inline_variable_test
-list(APPEND INLINE_VARIABLE_TEST_SRC
-  "internal/inline_variable_testing.h"
-  "inline_variable_test.cc"
-  "inline_variable_test_a.cc"
-  "inline_variable_test_b.cc"
-)
-
-set(INLINE_VARIABLE_TEST_PUBLIC_LIBRARIES absl::base)
-
-absl_test(
-  TARGET
-    inline_variable_test
-  SOURCES
-    ${INLINE_VARIABLE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INLINE_VARIABLE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test spinlock_test_common
-set(SPINLOCK_TEST_COMMON_SRC "spinlock_test_common.cc")
-set(SPINLOCK_TEST_COMMON_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    spinlock_test_common
-  SOURCES
-    ${SPINLOCK_TEST_COMMON_SRC}
-  PUBLIC_LIBRARIES
-    ${SPINLOCK_TEST_COMMON_PUBLIC_LIBRARIES}
-)
-
-
-# test spinlock_test
-set(SPINLOCK_TEST_SRC "spinlock_test_common.cc")
-set(SPINLOCK_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    spinlock_test
-  SOURCES
-    ${SPINLOCK_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SPINLOCK_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test endian_test
-set(ENDIAN_TEST_SRC "internal/endian_test.cc")
-
-absl_test(
-  TARGET
-    endian_test
-  SOURCES
-    ${ENDIAN_TEST_SRC}
-)
-
-
-# test config_test
-set(CONFIG_TEST_SRC "config_test.cc")
-set(CONFIG_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-absl_test(
-  TARGET
-    config_test
-  SOURCES
-    ${CONFIG_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CONFIG_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test raw_logging_test
-set(RAW_LOGGING_TEST_SRC "raw_logging_test.cc")
-set(RAW_LOGGING_TEST_PUBLIC_LIBRARIES absl::base absl::strings)
-
-absl_test(
-  TARGET
-    raw_logging_test
-  SOURCES
-    ${RAW_LOGGING_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${RAW_LOGGING_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test sysinfo_test
-set(SYSINFO_TEST_SRC "internal/sysinfo_test.cc")
-set(SYSINFO_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    sysinfo_test
-  SOURCES
-    ${SYSINFO_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SYSINFO_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test low_level_alloc_test
-set(LOW_LEVEL_ALLOC_TEST_SRC "internal/low_level_alloc_test.cc")
-set(LOW_LEVEL_ALLOC_TEST_PUBLIC_LIBRARIES absl::base)
-
-absl_test(
-  TARGET
-    low_level_alloc_test
-  SOURCES
-    ${LOW_LEVEL_ALLOC_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${LOW_LEVEL_ALLOC_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test thread_identity_test
-set(THREAD_IDENTITY_TEST_SRC "internal/thread_identity_test.cc")
-set(THREAD_IDENTITY_TEST_PUBLIC_LIBRARIES absl::base absl::synchronization)
-
-absl_test(
-  TARGET
-    thread_identity_test
-  SOURCES
-    ${THREAD_IDENTITY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${THREAD_IDENTITY_TEST_PUBLIC_LIBRARIES}
-)
-
-#test exceptions_safety_testing_test
-set(EXCEPTION_SAFETY_TESTING_TEST_SRC "exception_safety_testing_test.cc")
-set(EXCEPTION_SAFETY_TESTING_TEST_PUBLIC_LIBRARIES
-  absl::base
-  absl_base_internal_exception_safety_testing
-  absl::memory
-  absl::meta
-  absl::strings
-  absl::optional
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     absl_exception_safety_testing_test
-  SOURCES
-    ${EXCEPTION_SAFETY_TESTING_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${EXCEPTION_SAFETY_TESTING_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "exception_safety_testing_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::exception_safety_testing
+    absl::memory
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    atomic_hook_test
+  SRCS
+    "internal/atomic_hook_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    bit_cast_test
+  SRCS
+    "bit_cast_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    throw_delegate_test
+  SRCS
+    "throw_delegate_test.cc"
+  DEPS
+    absl::base
+    absl::throw_delegate
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    inline_variable_test
+  SRCS
+    "internal/inline_variable_testing.h"
+    "inline_variable_test.cc"
+    "inline_variable_test_a.cc"
+    "inline_variable_test_b.cc"
+  DEPS
+    absl::base_internal
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    invoke_test
+  SRCS
+    "invoke_test.cc"
+  DEPS
+    absl::base_internal
+    absl::memory
+    absl::strings
+    gmock
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    spinlock_test_common
+  SRCS
+    "spinlock_test_common.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::spinlock_wait
+    absl::synchronization
+    gtest
+  TESTONLY
+)
+
+# On bazel BUILD this target use "alwayslink = 1" which is not implemented here
+absl_cc_test(
+  NAME
+    spinlock_test
+  SRCS
+    "spinlock_test_common.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::spinlock_wait
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    endian
+  HDRS
+    "internal/endian.h"
+    "internal/unaligned_access.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    endian_test
+  SRCS
+    "internal/endian_test.cc"
+  DEPS
+    absl::base
+    absl::config
+    absl::endian
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    config_test
+  SRCS
+    "config_test.cc"
+  DEPS
+    absl::config
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    call_once_test
+  SRCS
+    "call_once_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    raw_logging_test
+  SRCS
+    "raw_logging_test.cc"
+  DEPS
+    absl::base
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    sysinfo_test
+  SRCS
+    "internal/sysinfo_test.cc"
+  DEPS
+    absl::base
+    absl::synchronization
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    low_level_alloc_test
+  SRCS
+    "internal/low_level_alloc_test.cc"
+  DEPS
+    absl::malloc_internal
+    Threads::Threads
+)
+
+absl_cc_test(
+  NAME
+    thread_identity_test
+  SRCS
+    "internal/thread_identity_test.cc"
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::synchronization
+    Threads::Threads
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    bits
+  HDRS
+    "internal/bits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+)
+
+absl_cc_test(
+  NAME
+    bits_test
+  SRCS
+    "internal/bits_test.cc"
+  DEPS
+    absl::bits
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    scoped_set_env
+  SRCS
+    "internal/scoped_set_env.cc"
+  HDRS
+    "internal/scoped_set_env.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+)
+
+absl_cc_test(
+  NAME
+    scoped_set_env_test
+  SRCS
+    "internal/scoped_set_env_test.cc"
+  DEPS
+    absl::scoped_set_env
+    gtest_main
 )
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index e850022..48195d6 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -80,7 +80,7 @@
 //
 // A function-like feature checking macro that accepts C++11 style attributes.
 // It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
-// (http://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
 // find `__has_cpp_attribute`, will evaluate to 0.
 #if defined(__cplusplus) && defined(__has_cpp_attribute)
 // NOTE: requiring __cplusplus above should not be necessary, but
@@ -102,7 +102,7 @@
 //
 // Tells the compiler to perform `printf` format string checking if the
 // compiler supports it; see the 'format' attribute in
-// <http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
+// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
 //
 // Note: As the GCC manual states, "[s]ince non-static C++ methods
 // have an implicit 'this' argument, the arguments of such methods
@@ -155,7 +155,12 @@
 // ABSL_ATTRIBUTE_WEAK
 //
 // Tags a function as weak for the purposes of compilation and linking.
-#if ABSL_HAVE_ATTRIBUTE(weak) || (defined(__GNUC__) && !defined(__clang__))
+// Weak attributes currently do not work properly in LLVM's Windows backend,
+// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
+// for futher information.
+#if (ABSL_HAVE_ATTRIBUTE(weak) || \
+     (defined(__GNUC__) && !defined(__clang__))) && \
+    !(defined(__llvm__) && defined(_WIN32))
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
 #define ABSL_HAVE_ATTRIBUTE_WEAK 1
@@ -282,6 +287,17 @@
 #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
 #endif
 
+// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+//
+// Tells the SafeStack to not instrument a given function.
+// See https://clang.llvm.org/docs/SafeStack.html for details.
+#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
+#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
+  __attribute__((no_sanitize("safe-stack")))
+#else
+#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+#endif
+
 // ABSL_ATTRIBUTE_RETURNS_NONNULL
 //
 // Tells the compiler that a particular function never returns a null pointer.
@@ -296,13 +312,13 @@
 
 // ABSL_HAVE_ATTRIBUTE_SECTION
 //
-// Indicates whether labeled sections are supported. Labeled sections are not
-// supported on Darwin/iOS.
+// Indicates whether labeled sections are supported. Weak symbol support is
+// a prerequisite. Labeled sections are not supported on Darwin/iOS.
 #ifdef ABSL_HAVE_ATTRIBUTE_SECTION
 #error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set
 #elif (ABSL_HAVE_ATTRIBUTE(section) ||                \
        (defined(__GNUC__) && !defined(__clang__))) && \
-    !defined(__APPLE__)
+    !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK
 #define ABSL_HAVE_ATTRIBUTE_SECTION 1
 
 // ABSL_ATTRIBUTE_SECTION
@@ -397,17 +413,28 @@
 
 // ABSL_MUST_USE_RESULT
 //
-// Tells the compiler to warn about unused return values for functions declared
-// with this macro. The macro must appear as the very first part of a function
-// declaration or definition:
+// Tells the compiler to warn about unused results.
 //
-// Example:
+// When annotating a function, it must appear as the first part of the
+// declaration or definition. The compiler will warn if the return value from
+// such a function is unused:
 //
 //   ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket();
+//   AllocateSprocket();  // Triggers a warning.
 //
-// This placement has the broadest compatibility with GCC, Clang, and MSVC, with
-// both defs and decls, and with GCC-style attributes, MSVC declspec, C++11
-// and C++17 attributes.
+// When annotating a class, it is equivalent to annotating every function which
+// returns an instance.
+//
+//   class ABSL_MUST_USE_RESULT Sprocket {};
+//   Sprocket();  // Triggers a warning.
+//
+//   Sprocket MakeSprocket();
+//   MakeSprocket();  // Triggers a warning.
+//
+// Note that references and pointers are not instances:
+//
+//   Sprocket* SprocketPointer();
+//   SprocketPointer();  // Does *not* trigger a warning.
 //
 // ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result
 // warning. For that, warn_unused_result is used only for clang but not for gcc.
diff --git a/absl/base/bit_cast_test.cc b/absl/base/bit_cast_test.cc
index 8cd878d..4846add 100644
--- a/absl/base/bit_cast_test.cc
+++ b/absl/base/bit_cast_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/call_once.h b/absl/base/call_once.h
index 532ee2e..8c4f297 100644
--- a/absl/base/call_once.h
+++ b/absl/base/call_once.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -150,12 +150,8 @@
         old_control != kOnceRunning &&
         old_control != kOnceWaiter &&
         old_control != kOnceDone) {
-      ABSL_RAW_LOG(
-          FATAL,
-          "Unexpected value for control word: %lx. Either the control word "
-          "has non-static storage duration (where GoogleOnceDynamic might "
-          "be appropriate), or there's been a memory corruption.",
-          static_cast<unsigned long>(old_control)); // NOLINT
+      ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx",
+                   static_cast<unsigned long>(old_control));  // NOLINT
     }
   }
 #endif  // NDEBUG
diff --git a/absl/base/call_once_test.cc b/absl/base/call_once_test.cc
index cd58ee1..9c2a0c4 100644
--- a/absl/base/call_once_test.cc
+++ b/absl/base/call_once_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -18,6 +18,8 @@
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/mutex.h"
 
@@ -25,7 +27,8 @@
 namespace {
 
 absl::once_flag once;
-Mutex counters_mu;
+
+ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
 
 int running_thread_count GUARDED_BY(counters_mu) = 0;
 int call_once_invoke_count GUARDED_BY(counters_mu) = 0;
diff --git a/absl/base/casts.h b/absl/base/casts.h
index 20fd34d..00196d2 100644
--- a/absl/base/casts.h
+++ b/absl/base/casts.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -105,7 +105,7 @@
 //
 // Such implicit cast chaining may be useful within template logic.
 template <typename To>
-inline To implicit_cast(typename absl::internal::identity_t<To> to) {
+constexpr To implicit_cast(typename absl::internal::identity_t<To> to) {
   return to;
 }
 
diff --git a/absl/base/config.h b/absl/base/config.h
index d4eb7d0..3b81e26 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -118,7 +118,7 @@
 // Checks whether `std::is_trivially_copy_assignable<T>` is supported.
 
 // Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with
-// either libc++ or libstdc++, and Visual Studio.
+// either libc++ or libstdc++, and Visual Studio (but not NVCC).
 #if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
 #error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
 #elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
@@ -127,7 +127,7 @@
     (!defined(__clang__) && defined(__GNUC__) &&                 \
      (__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)) && \
      (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) ||      \
-    defined(_MSC_VER)
+    (defined(_MSC_VER) && !defined(__NVCC__))
 #define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
 #define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
 #endif
@@ -139,12 +139,18 @@
 #ifdef ABSL_HAVE_THREAD_LOCAL
 #error ABSL_HAVE_THREAD_LOCAL cannot be directly set
 #elif defined(__APPLE__)
-// Notes: Xcode's clang did not support `thread_local` until version
-// 8, and even then not for all iOS < 9.0. Also, Xcode 9.3 started disallowing
-// `thread_local` for 32-bit iOS simulator targeting iOS 9.x.
-// `__has_feature` is only supported by Clang so it has be inside
+// Notes:
+// * Xcode's clang did not support `thread_local` until version 8, and
+//   even then not for all iOS < 9.0.
+// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
+//   targeting iOS 9.x.
+// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
+//   making __has_feature unreliable there.
+//
+// Otherwise, `__has_feature` is only supported by Clang so it has be inside
 // `defined(__APPLE__)` check.
-#if __has_feature(cxx_thread_local)
+#if __has_feature(cxx_thread_local) && \
+    !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
 #define ABSL_HAVE_THREAD_LOCAL 1
 #endif
 #else  // !defined(__APPLE__)
@@ -268,7 +274,8 @@
 #error ABSL_HAVE_MMAP cannot be directly set
 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||   \
     defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
-    defined(__wasm__) || defined(__Fuchsia__) || defined(__sun)
+    defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
+    defined(__ASYLO__)
 #define ABSL_HAVE_MMAP 1
 #endif
 
@@ -322,6 +329,8 @@
 #define ABSL_HAVE_ALARM 1
 #elif defined(_MSC_VER)
 // feature tests for Microsoft's library
+#elif defined(__EMSCRIPTEN__)
+// emscripten doesn't support signals
 #elif defined(__native_client__)
 #else
 // other standard libraries
@@ -356,6 +365,18 @@
 #error "absl endian detection needs to be set up for your compiler"
 #endif
 
+// MacOS 10.13 doesn't let you use <any>, <optional>, or <variant> even though
+// the headers exist and are publicly noted to work.  See
+// https://github.com/abseil/abseil-cpp/issues/207 and
+// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
+#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
+    defined(__MAC_OS_X_VERSION_MIN_REQUIRED__) &&     \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400
+#define ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 1
+#else
+#define ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE 0
+#endif
+
 // ABSL_HAVE_STD_ANY
 //
 // Checks whether C++17 std::any is available by checking whether <any> exists.
@@ -364,7 +385,8 @@
 #endif
 
 #ifdef __has_include
-#if __has_include(<any>) && __cplusplus >= 201703L
+#if __has_include(<any>) && __cplusplus >= 201703L && \
+    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_ANY 1
 #endif
 #endif
@@ -377,7 +399,8 @@
 #endif
 
 #ifdef __has_include
-#if __has_include(<optional>) && __cplusplus >= 201703L
+#if __has_include(<optional>) && __cplusplus >= 201703L && \
+    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_OPTIONAL 1
 #endif
 #endif
@@ -390,7 +413,8 @@
 #endif
 
 #ifdef __has_include
-#if __has_include(<variant>) && __cplusplus >= 201703L
+#if __has_include(<variant>) && __cplusplus >= 201703L && \
+    !ABSL_INTERNAL_MACOS_CXX17_TYPES_UNAVAILABLE
 #define ABSL_HAVE_STD_VARIANT 1
 #endif
 #endif
@@ -423,4 +447,12 @@
 #define ABSL_HAVE_STD_STRING_VIEW 1
 #endif
 
+// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
+// SEH exception from emplace for variant<SomeStruct> when constructing the
+// struct can throw. This defeats some of variant_test and
+// variant_exception_safety_test.
+#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
+#define ABSL_INTERNAL_MSVC_2017_DBG_MODE
+#endif
+
 #endif  // ABSL_BASE_CONFIG_H_
diff --git a/absl/base/config_test.cc b/absl/base/config_test.cc
index c839712..7e0c033 100644
--- a/absl/base/config_test.cc
+++ b/absl/base/config_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/const_init.h b/absl/base/const_init.h
new file mode 100644
index 0000000..17858a7
--- /dev/null
+++ b/absl/base/const_init.h
@@ -0,0 +1,72 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// kConstInit
+// -----------------------------------------------------------------------------
+//
+// A constructor tag used to mark an object as safe for use as a global
+// variable, avoiding the usual lifetime issues that can affect globals.
+
+#ifndef ABSL_BASE_CONST_INIT_H_
+#define ABSL_BASE_CONST_INIT_H_
+
+// In general, objects with static storage duration (such as global variables)
+// can trigger tricky object lifetime situations.  Attempting to access them
+// from the constructors or destructors of other global objects can result in
+// undefined behavior, unless their constructors and destructors are designed
+// with this issue in mind.
+//
+// The normal way to deal with this issue in C++11 is to use constant
+// initialization and trivial destructors.
+//
+// Constant initialization is guaranteed to occur before any other code
+// executes.  Constructors that are declared 'constexpr' are eligible for
+// constant initialization.  You can annotate a variable declaration with the
+// ABSL_CONST_INIT macro to express this intent.  For compilers that support
+// it, this annotation will cause a compilation error for declarations that
+// aren't subject to constant initialization (perhaps because a runtime value
+// was passed as a constructor argument).
+//
+// On program shutdown, lifetime issues can be avoided on global objects by
+// ensuring that they contain  trivial destructors.  A class has a trivial
+// destructor unless it has a user-defined destructor, a virtual method or base
+// class, or a data member or base class with a non-trivial destructor of its
+// own.  Objects with static storage duration and a trivial destructor are not
+// cleaned up on program shutdown, and are thus safe to access from other code
+// running during shutdown.
+//
+// For a few core Abseil classes, we make a best effort to allow for safe global
+// instances, even though these classes have non-trivial destructors.  These
+// objects can be created with the absl::kConstInit tag.  For example:
+//   ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit);
+//
+// The line above declares a global variable of type absl::Mutex which can be
+// accessed at any point during startup or shutdown.  global_mutex's destructor
+// will still run, but will not invalidate the object.  Note that C++ specifies
+// that accessing an object after its destructor has run results in undefined
+// behavior, but this pattern works on the toolchains we support.
+//
+// The absl::kConstInit tag should only be used to define objects with static
+// or thread_local storage duration.
+
+namespace absl {
+
+enum ConstInitType {
+  kConstInit,
+};
+
+}  // namespace absl
+
+#endif  // ABSL_BASE_CONST_INIT_H_
diff --git a/absl/base/dynamic_annotations.cc b/absl/base/dynamic_annotations.cc
index b97fa3a..1411093 100644
--- a/absl/base/dynamic_annotations.cc
+++ b/absl/base/dynamic_annotations.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 88048b0..8ac7498 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *      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,
@@ -139,6 +139,7 @@
   #define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
   #define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
 #endif  /* ABSL_DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
+
 /* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the
    appropriate feature ID. */
 #if defined(__clang__) && (!defined(SWIG)) \
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index 106bc34..2ed3860 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -770,6 +770,18 @@
                   .Test(invoker));
 }
 
+TEST(ExceptionSafetyTesterTest, ResetsCountdown) {
+  auto test =
+      testing::MakeExceptionSafetyTester()
+          .WithInitialValue(ThrowingValue<>())
+          .WithContracts([](ThrowingValue<>*) { return AssertionSuccess(); })
+          .WithOperation([](ThrowingValue<>*) {});
+  ASSERT_TRUE(test.Test());
+  // If the countdown isn't reset because there were no exceptions thrown, then
+  // this will fail with a termination from an unhandled exception
+  EXPECT_TRUE(test.Test());
+}
+
 struct NonCopyable : public NonNegative {
   NonCopyable(const NonCopyable&) = delete;
   NonCopyable() : NonNegative{0} {}
diff --git a/absl/base/inline_variable_test.cc b/absl/base/inline_variable_test.cc
index 5499189..471f706 100644
--- a/absl/base/inline_variable_test.cc
+++ b/absl/base/inline_variable_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/inline_variable_test_a.cc b/absl/base/inline_variable_test_a.cc
index a3bf3b6..d0b8e7d 100644
--- a/absl/base/inline_variable_test_a.cc
+++ b/absl/base/inline_variable_test_a.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/inline_variable_test_b.cc b/absl/base/inline_variable_test_b.cc
index b4b9393..931d56d 100644
--- a/absl/base/inline_variable_test_b.cc
+++ b/absl/base/inline_variable_test_b.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/atomic_hook.h b/absl/base/internal/atomic_hook.h
index b458511..803e905 100644
--- a/absl/base/internal/atomic_hook.h
+++ b/absl/base/internal/atomic_hook.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/atomic_hook_test.cc b/absl/base/internal/atomic_hook_test.cc
index cf74075..ecc8040 100644
--- a/absl/base/internal/atomic_hook_test.cc
+++ b/absl/base/internal/atomic_hook_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/bits.h b/absl/base/internal/bits.h
index bc7faae..b0780f2 100644
--- a/absl/base/internal/bits.h
+++ b/absl/base/internal/bits.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/bits_test.cc b/absl/base/internal/bits_test.cc
index e5d991d..7855fa6 100644
--- a/absl/base/internal/bits_test.cc
+++ b/absl/base/internal/bits_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc
index a742df0..4b553c2 100644
--- a/absl/base/internal/cycleclock.cc
+++ b/absl/base/internal/cycleclock.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -22,6 +22,7 @@
 
 #include "absl/base/internal/cycleclock.h"
 
+#include <atomic>
 #include <chrono>  // NOLINT(build/c++11)
 
 #include "absl/base/internal/unscaledcycleclock.h"
@@ -52,17 +53,26 @@
 #endif
 
 static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
+static std::atomic<CycleClockSourceFunc> cycle_clock_source;
 
 }  // namespace
 
 int64_t CycleClock::Now() {
-  return base_internal::UnscaledCycleClock::Now() >> kShift;
+  auto fn = cycle_clock_source.load(std::memory_order_relaxed);
+  if (fn == nullptr) {
+    return base_internal::UnscaledCycleClock::Now() >> kShift;
+  }
+  return fn() >> kShift;
 }
 
 double CycleClock::Frequency() {
   return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
 }
 
+void CycleClockSource::Register(CycleClockSourceFunc source) {
+  cycle_clock_source.store(source, std::memory_order_relaxed);
+}
+
 #else
 
 int64_t CycleClock::Now() {
diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h
index 60e9715..794564e 100644
--- a/absl/base/internal/cycleclock.h
+++ b/absl/base/internal/cycleclock.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -28,7 +28,6 @@
 // not necessarily "CPU cycles" and code should not rely on that behavior, even
 // if experimentally observed.
 //
-//
 // An arbitrary offset may have been added to the counter at power on.
 //
 // On some platforms, the rate and offset of the counter may differ
@@ -71,6 +70,20 @@
   CycleClock& operator=(const CycleClock&) = delete;
 };
 
+using CycleClockSourceFunc = int64_t (*)();
+
+class CycleClockSource {
+ private:
+  // CycleClockSource::Register()
+  //
+  // Register a function that provides an alternate source for the unscaled CPU
+  // cycle count value. The source function must be async signal safe, must not
+  // call CycleClock::Now(), and must have a frequency that matches that of the
+  // unscaled clock used by CycleClock. A nullptr value resets CycleClock to use
+  // the default source.
+  static void Register(CycleClockSourceFunc source);
+};
+
 }  // namespace base_internal
 }  // namespace absl
 
diff --git a/absl/base/internal/direct_mmap.h b/absl/base/internal/direct_mmap.h
index 0426e11..0401ddf 100644
--- a/absl/base/internal/direct_mmap.h
+++ b/absl/base/internal/direct_mmap.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -75,7 +75,11 @@
   // On these architectures, implement mmap with mmap2.
   static int pagesize = 0;
   if (pagesize == 0) {
+#if defined(__wasm__) || defined(__asmjs__)
     pagesize = getpagesize();
+#else
+    pagesize = sysconf(_SC_PAGESIZE);
+#endif
   }
   if (offset < 0 || offset % pagesize != 0) {
     errno = EINVAL;
diff --git a/absl/base/internal/endian.h b/absl/base/internal/endian.h
index edc10f1..6b828b6 100644
--- a/absl/base/internal/endian.h
+++ b/absl/base/internal/endian.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -75,21 +75,21 @@
   if (__builtin_constant_p(host_int)) {
     return __bswap_constant_64(host_int);
   } else {
-    register uint64_t result;
+    uint64_t result;
     __asm__("bswap %0" : "=r"(result) : "0"(host_int));
     return result;
   }
 #elif defined(__GLIBC__)
   return bswap_64(host_int);
 #else
-  return (((x & uint64_t{(0xFF}) << 56) |
-          ((x & uint64_t{(0xFF00}) << 40) |
-          ((x & uint64_t{(0xFF0000}) << 24) |
-          ((x & uint64_t{(0xFF000000}) << 8) |
-          ((x & uint64_t{(0xFF00000000}) >> 8) |
-          ((x & uint64_t{(0xFF0000000000}) >> 24) |
-          ((x & uint64_t{(0xFF000000000000}) >> 40) |
-          ((x & uint64_t{(0xFF00000000000000}) >> 56));
+  return (((host_int & uint64_t{0xFF}) << 56) |
+          ((host_int & uint64_t{0xFF00}) << 40) |
+          ((host_int & uint64_t{0xFF0000}) << 24) |
+          ((host_int & uint64_t{0xFF000000}) << 8) |
+          ((host_int & uint64_t{0xFF00000000}) >> 8) |
+          ((host_int & uint64_t{0xFF0000000000}) >> 24) |
+          ((host_int & uint64_t{0xFF000000000000}) >> 40) |
+          ((host_int & uint64_t{0xFF00000000000000}) >> 56));
 #endif  // bswap_64
 }
 
@@ -97,8 +97,10 @@
 #if defined(__GLIBC__)
   return bswap_32(host_int);
 #else
-  return (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) |
-          ((x & 0xFF000000) >> 24));
+  return (((host_int & uint32_t{0xFF}) << 24) |
+          ((host_int & uint32_t{0xFF00}) << 8) |
+          ((host_int & uint32_t{0xFF0000}) >> 8) |
+          ((host_int & uint32_t{0xFF000000}) >> 24));
 #endif
 }
 
@@ -106,7 +108,8 @@
 #if defined(__GLIBC__)
   return bswap_16(host_int);
 #else
-  return uint16_t{((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)};
+  return (((host_int & uint16_t{0xFF}) << 8) |
+          ((host_int & uint16_t{0xFF00}) >> 8));
 #endif
 }
 
diff --git a/absl/base/internal/endian_test.cc b/absl/base/internal/endian_test.cc
index e276915..98a099e 100644
--- a/absl/base/internal/endian_test.cc
+++ b/absl/base/internal/endian_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/exception_safety_testing.cc b/absl/base/internal/exception_safety_testing.cc
index f1d081f..6ef4325 100644
--- a/absl/base/internal/exception_safety_testing.cc
+++ b/absl/base/internal/exception_safety_testing.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -23,6 +23,10 @@
 
 exceptions_internal::StrongGuaranteeTagType strong_guarantee;
 
+exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester() {
+  return {};
+}
+
 namespace exceptions_internal {
 
 int countdown = -1;
diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h
index 5665a1b..be38ba5 100644
--- a/absl/base/internal/exception_safety_testing.h
+++ b/absl/base/internal/exception_safety_testing.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -33,7 +33,7 @@
 #include "absl/meta/type_traits.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/substitute.h"
-#include "absl/types/optional.h"
+#include "absl/utility/utility.h"
 
 namespace testing {
 
@@ -127,10 +127,8 @@
       void* address = it.first;
       TrackedAddress& tracked_address = it.second;
       if (tracked_address.is_alive) {
-        ADD_FAILURE() << "Object at address " << address
-                      << " with countdown of " << countdown_
-                      << " was not destroyed [" << tracked_address.description
-                      << "]";
+        ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
+                                      countdown_, "Object was not destroyed.");
       }
     }
   }
@@ -141,11 +139,11 @@
     TrackedAddress& tracked_address =
         current_tracker_instance_->address_map_[address];
     if (tracked_address.is_alive) {
-      ADD_FAILURE() << "Object at address " << address << " with countdown of "
-                    << current_tracker_instance_->countdown_
-                    << " was re-constructed. Previously: ["
-                    << tracked_address.description << "] Now: [" << description
-                    << "]";
+      ADD_FAILURE() << ErrorMessage(
+          address, tracked_address.description,
+          current_tracker_instance_->countdown_,
+          "Object was re-constructed. Current object was constructed by " +
+              description);
     }
     tracked_address = {true, std::move(description)};
   }
@@ -159,10 +157,9 @@
 
     TrackedAddress& tracked_address = it->second;
     if (!tracked_address.is_alive) {
-      ADD_FAILURE() << "Object at address " << address << " with countdown of "
-                    << current_tracker_instance_->countdown_
-                    << " was re-destroyed or created prior to construction "
-                    << "tracking [" << tracked_address.description << "]";
+      ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
+                                    current_tracker_instance_->countdown_,
+                                    "Object was re-destroyed.");
     }
     tracked_address.is_alive = false;
   }
@@ -172,6 +169,18 @@
     return current_tracker_instance_ != nullptr;
   }
 
+  static std::string ErrorMessage(void* address,
+                                  const std::string& address_description,
+                                  int countdown,
+                                  const std::string& error_description) {
+    return absl::Substitute(
+        "With coundtown at $0:\n"
+        "  $1\n"
+        "  Object originally constructed by $2\n"
+        "  Object address: $3\n",
+        countdown, error_description, address_description, address);
+  }
+
   std::unordered_map<void*, TrackedAddress> address_map_;
   int countdown_;
 
@@ -190,70 +199,6 @@
 
   ~TrackedObject() noexcept { ConstructorTracker::ObjectDestructed(this); }
 };
-
-template <typename Factory, typename Operation, typename Contract>
-absl::optional<testing::AssertionResult> TestSingleContractAtCountdownImpl(
-    const Factory& factory, const Operation& operation, int count,
-    const Contract& contract) {
-  auto t_ptr = factory();
-  absl::optional<testing::AssertionResult> current_res;
-  SetCountdown(count);
-  try {
-    operation(t_ptr.get());
-  } catch (const exceptions_internal::TestException& e) {
-    current_res.emplace(contract(t_ptr.get()));
-    if (!current_res.value()) {
-      *current_res << e.what() << " failed contract check";
-    }
-  }
-  UnsetCountdown();
-  return current_res;
-}
-
-template <typename Factory, typename Operation>
-absl::optional<testing::AssertionResult> TestSingleContractAtCountdownImpl(
-    const Factory& factory, const Operation& operation, int count,
-    StrongGuaranteeTagType) {
-  using TPtr = typename decltype(factory())::pointer;
-  auto t_is_strong = [&](TPtr t) { return *t == *factory(); };
-  return TestSingleContractAtCountdownImpl(factory, operation, count,
-                                           t_is_strong);
-}
-
-template <typename Factory, typename Operation, typename Contract>
-int TestSingleContractAtCountdown(
-    const Factory& factory, const Operation& operation, int count,
-    const Contract& contract,
-    absl::optional<testing::AssertionResult>* reduced_res) {
-  // If reduced_res is empty, it means the current call to
-  // TestSingleContractAtCountdown(...) is the first test being run so we do
-  // want to run it. Alternatively, if it's not empty (meaning a previous test
-  // has run) we want to check if it passed. If the previous test did pass, we
-  // want to contine running tests so we do want to run the current one. If it
-  // failed, we want to short circuit so as not to overwrite the AssertionResult
-  // output. If that's the case, we do not run the current test and instead we
-  // simply return.
-  if (!reduced_res->has_value() || reduced_res->value()) {
-    *reduced_res =
-        TestSingleContractAtCountdownImpl(factory, operation, count, contract);
-  }
-  return 0;
-}
-
-template <typename Factory, typename Operation, typename... Contracts>
-inline absl::optional<testing::AssertionResult> TestAllContractsAtCountdown(
-    const Factory& factory, const Operation& operation, int count,
-    const Contracts&... contracts) {
-  absl::optional<testing::AssertionResult> reduced_res;
-
-  // Run each checker, short circuiting after the first failure
-  int dummy[] = {
-      0, (TestSingleContractAtCountdown(factory, operation, count, contracts,
-                                        &reduced_res))...};
-  static_cast<void>(dummy);
-  return reduced_res;
-}
-
 }  // namespace exceptions_internal
 
 extern exceptions_internal::NoThrowTag nothrow_ctor;
@@ -613,8 +558,8 @@
   // We provide both regular and templated operator delete because if only the
   // templated version is provided as we did with operator new, the compiler has
   // no way of knowing which overload of operator delete to call. See
-  // http://en.cppreference.com/w/cpp/memory/new/operator_delete and
-  // http://en.cppreference.com/w/cpp/language/delete for the gory details.
+  // https://en.cppreference.com/w/cpp/memory/new/operator_delete and
+  // https://en.cppreference.com/w/cpp/language/delete for the gory details.
   void operator delete(void* p) noexcept { ::operator delete(p); }
 
   template <typename... Args>
@@ -773,7 +718,7 @@
   }
 
   size_type max_size() const noexcept {
-    return std::numeric_limits<difference_type>::max() / sizeof(value_type);
+    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
   }
 
   ThrowingAllocator select_on_container_copy_construction() noexcept(
@@ -871,7 +816,7 @@
 
 namespace exceptions_internal {
 
-// Dummy struct for ExceptionSafetyTester<> partial state.
+// Dummy struct for ExceptionSafetyTestBuilder<> partial state.
 struct UninitializedT {};
 
 template <typename T>
@@ -893,20 +838,97 @@
 
 template <typename Factory = UninitializedT,
           typename Operation = UninitializedT, typename... Contracts>
-class ExceptionSafetyTester;
+class ExceptionSafetyTestBuilder;
 
 }  // namespace exceptions_internal
 
-exceptions_internal::ExceptionSafetyTester<> MakeExceptionSafetyTester();
+/*
+ * Constructs an empty ExceptionSafetyTestBuilder. All
+ * ExceptionSafetyTestBuilder objects are immutable and all With[thing] mutation
+ * methods return new instances of ExceptionSafetyTestBuilder.
+ *
+ * In order to test a T for exception safety, a factory for that T, a testable
+ * operation, and at least one contract callback returning an assertion
+ * result must be applied using the respective methods.
+ */
+exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester();
 
 namespace exceptions_internal {
+template <typename T>
+struct IsUniquePtr : std::false_type {};
+
+template <typename T, typename D>
+struct IsUniquePtr<std::unique_ptr<T, D>> : std::true_type {};
+
+template <typename Factory>
+struct FactoryPtrTypeHelper {
+  using type = decltype(std::declval<const Factory&>()());
+
+  static_assert(IsUniquePtr<type>::value, "Factories must return a unique_ptr");
+};
+
+template <typename Factory>
+using FactoryPtrType = typename FactoryPtrTypeHelper<Factory>::type;
+
+template <typename Factory>
+using FactoryElementType = typename FactoryPtrType<Factory>::element_type;
+
+template <typename T>
+class ExceptionSafetyTest {
+  using Factory = std::function<std::unique_ptr<T>()>;
+  using Operation = std::function<void(T*)>;
+  using Contract = std::function<AssertionResult(T*)>;
+
+ public:
+  template <typename... Contracts>
+  explicit ExceptionSafetyTest(const Factory& f, const Operation& op,
+                               const Contracts&... contracts)
+      : factory_(f), operation_(op), contracts_{WrapContract(contracts)...} {}
+
+  AssertionResult Test() const {
+    for (int count = 0;; ++count) {
+      exceptions_internal::ConstructorTracker ct(count);
+
+      for (const auto& contract : contracts_) {
+        auto t_ptr = factory_();
+        try {
+          SetCountdown(count);
+          operation_(t_ptr.get());
+          // Unset for the case that the operation throws no exceptions, which
+          // would leave the countdown set and break the *next* exception safety
+          // test after this one.
+          UnsetCountdown();
+          return AssertionSuccess();
+        } catch (const exceptions_internal::TestException& e) {
+          if (!contract(t_ptr.get())) {
+            return AssertionFailure() << e.what() << " failed contract check";
+          }
+        }
+      }
+    }
+  }
+
+ private:
+  template <typename ContractFn>
+  Contract WrapContract(const ContractFn& contract) {
+    return [contract](T* t_ptr) { return AssertionResult(contract(t_ptr)); };
+  }
+
+  Contract WrapContract(StrongGuaranteeTagType) {
+    return [this](T* t_ptr) { return AssertionResult(*factory_() == *t_ptr); };
+  }
+
+  Factory factory_;
+  Operation operation_;
+  std::vector<Contract> contracts_;
+};
 
 /*
  * Builds a tester object that tests if performing a operation on a T follows
  * exception safety guarantees. Verification is done via contract assertion
  * callbacks applied to T instances post-throw.
  *
- * Template parameters for ExceptionSafetyTester:
+ * Template parameters for ExceptionSafetyTestBuilder:
  *
  * - Factory: The factory object (passed in via tester.WithFactory(...) or
  *   tester.WithInitialValue(...)) must be invocable with the signature
@@ -933,13 +955,13 @@
  *   please.
  */
 template <typename Factory, typename Operation, typename... Contracts>
-class ExceptionSafetyTester {
+class ExceptionSafetyTestBuilder {
  public:
   /*
-   * Returns a new ExceptionSafetyTester with an included T factory based on the
-   * provided T instance. The existing factory will not be included in the newly
-   * created tester instance. The created factory returns a new T instance by
-   * copy-constructing the provided const T& t.
+   * Returns a new ExceptionSafetyTestBuilder with an included T factory based
+   * on the provided T instance. The existing factory will not be included in
+   * the newly created tester instance. The created factory returns a new T
+   * instance by copy-constructing the provided const T& t.
    *
    * Preconditions for tester.WithInitialValue(const T& t):
    *
@@ -948,41 +970,41 @@
    *   tester.WithFactory(...).
    */
   template <typename T>
-  ExceptionSafetyTester<DefaultFactory<T>, Operation, Contracts...>
+  ExceptionSafetyTestBuilder<DefaultFactory<T>, Operation, Contracts...>
   WithInitialValue(const T& t) const {
     return WithFactory(DefaultFactory<T>(t));
   }
 
   /*
-   * Returns a new ExceptionSafetyTester with the provided T factory included.
-   * The existing factory will not be included in the newly-created tester
-   * instance. This method is intended for use with types lacking a copy
+   * Returns a new ExceptionSafetyTestBuilder with the provided T factory
+   * included. The existing factory will not be included in the newly-created
+   * tester instance. This method is intended for use with types lacking a copy
    * constructor. Types that can be copy-constructed should instead use the
    * method tester.WithInitialValue(...).
    */
   template <typename NewFactory>
-  ExceptionSafetyTester<absl::decay_t<NewFactory>, Operation, Contracts...>
+  ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...>
   WithFactory(const NewFactory& new_factory) const {
     return {new_factory, operation_, contracts_};
   }
 
   /*
-   * Returns a new ExceptionSafetyTester with the provided testable operation
-   * included. The existing operation will not be included in the newly created
-   * tester.
+   * Returns a new ExceptionSafetyTestBuilder with the provided testable
+   * operation included. The existing operation will not be included in the
+   * newly created tester.
    */
   template <typename NewOperation>
-  ExceptionSafetyTester<Factory, absl::decay_t<NewOperation>, Contracts...>
+  ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...>
   WithOperation(const NewOperation& new_operation) const {
     return {factory_, new_operation, contracts_};
   }
 
   /*
-   * Returns a new ExceptionSafetyTester with the provided MoreContracts...
+   * Returns a new ExceptionSafetyTestBuilder with the provided MoreContracts...
    * combined with the Contracts... that were already included in the instance
    * on which the method was called. Contracts... cannot be removed or replaced
-   * once added to an ExceptionSafetyTester instance. A fresh object must be
-   * created in order to get an empty Contracts... list.
+   * once added to an ExceptionSafetyTestBuilder instance. A fresh object must
+   * be created in order to get an empty Contracts... list.
    *
    * In addition to passing in custom contract assertion callbacks, this method
    * accepts `testing::strong_guarantee` as an argument which checks T instances
@@ -991,8 +1013,8 @@
    * properly rolled back.
    */
   template <typename... MoreContracts>
-  ExceptionSafetyTester<Factory, Operation, Contracts...,
-                        absl::decay_t<MoreContracts>...>
+  ExceptionSafetyTestBuilder<Factory, Operation, Contracts...,
+                             absl::decay_t<MoreContracts>...>
   WithContracts(const MoreContracts&... more_contracts) const {
     return {
         factory_, operation_,
@@ -1039,48 +1061,27 @@
       typename LazyOperation = Operation,
       typename = EnableIfTestable<sizeof...(Contracts), Factory, LazyOperation>>
   testing::AssertionResult Test() const {
-    return TestImpl(operation_, absl::index_sequence_for<Contracts...>());
+    return Test(operation_);
   }
 
  private:
   template <typename, typename, typename...>
-  friend class ExceptionSafetyTester;
+  friend class ExceptionSafetyTestBuilder;
 
-  friend ExceptionSafetyTester<> testing::MakeExceptionSafetyTester();
+  friend ExceptionSafetyTestBuilder<> testing::MakeExceptionSafetyTester();
 
-  ExceptionSafetyTester() {}
+  ExceptionSafetyTestBuilder() {}
 
-  ExceptionSafetyTester(const Factory& f, const Operation& o,
-                        const std::tuple<Contracts...>& i)
+  ExceptionSafetyTestBuilder(const Factory& f, const Operation& o,
+                             const std::tuple<Contracts...>& i)
       : factory_(f), operation_(o), contracts_(i) {}
 
   template <typename SelectedOperation, size_t... Indices>
-  testing::AssertionResult TestImpl(const SelectedOperation& selected_operation,
+  testing::AssertionResult TestImpl(SelectedOperation selected_operation,
                                     absl::index_sequence<Indices...>) const {
-    // Starting from 0 and counting upwards until one of the exit conditions is
-    // hit...
-    for (int count = 0;; ++count) {
-      exceptions_internal::ConstructorTracker ct(count);
-
-      // Run the full exception safety test algorithm for the current countdown
-      auto reduced_res =
-          TestAllContractsAtCountdown(factory_, selected_operation, count,
-                                      std::get<Indices>(contracts_)...);
-      // If there is no value in the optional, no contracts were run because no
-      // exception was thrown. This means that the test is complete and the loop
-      // can exit successfully.
-      if (!reduced_res.has_value()) {
-        return testing::AssertionSuccess();
-      }
-      // If the optional is not empty and the value is falsy, an contract check
-      // failed so the test must exit to propegate the failure.
-      if (!reduced_res.value()) {
-        return reduced_res.value();
-      }
-      // If the optional is not empty and the value is not falsy, it means
-      // exceptions were thrown but the contracts passed so the test must
-      // continue to run.
-    }
+    return ExceptionSafetyTest<FactoryElementType<Factory>>(
+               factory_, selected_operation, std::get<Indices>(contracts_)...)
+        .Test();
   }
 
   Factory factory_;
@@ -1090,20 +1091,6 @@
 
 }  // namespace exceptions_internal
 
-/*
- * Constructs an empty ExceptionSafetyTester. All ExceptionSafetyTester
- * objects are immutable and all With[thing] mutation methods return new
- * instances of ExceptionSafetyTester.
- *
- * In order to test a T for exception safety, a factory for that T, a testable
- * operation, and at least one contract callback returning an assertion
- * result must be applied using the respective methods.
- */
-inline exceptions_internal::ExceptionSafetyTester<>
-MakeExceptionSafetyTester() {
-  return {};
-}
-
 }  // namespace testing
 
 #endif  // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
diff --git a/absl/base/internal/exception_testing.h b/absl/base/internal/exception_testing.h
index 0cf7918..01b5465 100644
--- a/absl/base/internal/exception_testing.h
+++ b/absl/base/internal/exception_testing.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/hide_ptr.h b/absl/base/internal/hide_ptr.h
index 45cf438..cf8f408 100644
--- a/absl/base/internal/hide_ptr.h
+++ b/absl/base/internal/hide_ptr.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/identity.h b/absl/base/internal/identity.h
index a1a5d70..086447c 100644
--- a/absl/base/internal/identity.h
+++ b/absl/base/internal/identity.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/inline_variable.h b/absl/base/internal/inline_variable.h
index f7bb8c5..130d8c2 100644
--- a/absl/base/internal/inline_variable.h
+++ b/absl/base/internal/inline_variable.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/inline_variable_testing.h b/absl/base/internal/inline_variable_testing.h
index a0dd2bb..15dc481 100644
--- a/absl/base/internal/inline_variable_testing.h
+++ b/absl/base/internal/inline_variable_testing.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/invoke.h b/absl/base/internal/invoke.h
index 8c3f4f6..8da2869 100644
--- a/absl/base/internal/invoke.h
+++ b/absl/base/internal/invoke.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc
index 159f945..e4030ed 100644
--- a/absl/base/internal/low_level_alloc.cc
+++ b/absl/base/internal/low_level_alloc.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -208,7 +208,7 @@
   int32_t allocation_count GUARDED_BY(mu);
   // flags passed to NewArena
   const uint32_t flags;
-  // Result of getpagesize()
+  // Result of sysconf(_SC_PAGESIZE)
   const size_t pagesize;
   // Lowest power of two >= max(16, sizeof(AllocList))
   const size_t roundup;
@@ -324,8 +324,10 @@
   SYSTEM_INFO system_info;
   GetSystemInfo(&system_info);
   return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity);
-#else
+#elif defined(__wasm__) || defined(__asmjs__)
   return getpagesize();
+#else
+  return sysconf(_SC_PAGESIZE);
 #endif
 }
 
diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h
index fba9466..b35673d 100644
--- a/absl/base/internal/low_level_alloc.h
+++ b/absl/base/internal/low_level_alloc.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -119,4 +119,5 @@
 
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc
index cf2b363..34a080c 100644
--- a/absl/base/internal/low_level_alloc_test.cc
+++ b/absl/base/internal/low_level_alloc_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -137,6 +137,7 @@
     TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));
   }
 }
+
 // LowLevelAlloc is designed to be safe to call before main().
 static struct BeforeMain {
   BeforeMain() {
diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h
index e716f2b..0fcc8d3 100644
--- a/absl/base/internal/low_level_scheduling.h
+++ b/absl/base/internal/low_level_scheduling.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -86,6 +86,7 @@
 //------------------------------------------------------------------------------
 // End of public interfaces.
 //------------------------------------------------------------------------------
+
 inline bool SchedulingGuard::ReschedulingIsAllowed() {
   return false;
 }
@@ -98,7 +99,7 @@
   return;
 }
 
-
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
diff --git a/absl/base/internal/per_thread_tls.h b/absl/base/internal/per_thread_tls.h
index 2428bdc..cf5e97a 100644
--- a/absl/base/internal/per_thread_tls.h
+++ b/absl/base/internal/per_thread_tls.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -16,13 +16,17 @@
 #define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
 
 // This header defines two macros:
+//
 // If the platform supports thread-local storage:
-//   ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
-//   thread-local variable ABSL_PER_THREAD_TLS is 1
+//
+// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
+//   thread-local variable
+// * ABSL_PER_THREAD_TLS is 1
 //
 // Otherwise:
-//   ABSL_PER_THREAD_TLS_KEYWORD is empty
-//   ABSL_PER_THREAD_TLS is 0
+//
+// * ABSL_PER_THREAD_TLS_KEYWORD is empty
+// * ABSL_PER_THREAD_TLS is 0
 //
 // Microsoft C supports thread-local storage.
 // GCC supports it if the appropriate version of glibc is available,
diff --git a/absl/base/internal/pretty_function.h b/absl/base/internal/pretty_function.h
index 01b0547..35d5167 100644
--- a/absl/base/internal/pretty_function.h
+++ b/absl/base/internal/pretty_function.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index d9485a6..b5a05e8 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index 79a7bb9..6a4c093 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -38,6 +38,7 @@
 //   ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
 // This will print an almost standard log line like this to stderr only:
 //   E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+
 #define ABSL_RAW_LOG(severity, ...)                                            \
   do {                                                                         \
     constexpr const char* absl_raw_logging_internal_basename =                 \
@@ -79,13 +80,13 @@
         absl_raw_logging_internal_basename, __LINE__, message);       \
   } while (0)
 
-#define ABSL_INTERNAL_CHECK(condition, message)               \
-  do {                                                        \
-    if (ABSL_PREDICT_FALSE(!(condition))) {                   \
+#define ABSL_INTERNAL_CHECK(condition, message)                    \
+  do {                                                             \
+    if (ABSL_PREDICT_FALSE(!(condition))) {                        \
       std::string death_message = "Check " #condition " failed: "; \
       death_message += std::string(message);                       \
-      ABSL_INTERNAL_LOG(FATAL, death_message);                \
-    }                                                         \
+      ABSL_INTERNAL_LOG(FATAL, death_message);                     \
+    }                                                              \
   } while (0)
 
 #define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
diff --git a/absl/base/internal/scheduling_mode.h b/absl/base/internal/scheduling_mode.h
index 1b6497a..d5b4b7f 100644
--- a/absl/base/internal/scheduling_mode.h
+++ b/absl/base/internal/scheduling_mode.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc
new file mode 100644
index 0000000..3ac3f68
--- /dev/null
+++ b/absl/base/internal/scoped_set_env.cc
@@ -0,0 +1,79 @@
+// 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.
+
+#include "absl/base/internal/scoped_set_env.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <cstdlib>
+
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+namespace base_internal {
+
+namespace {
+
+#ifdef _WIN32
+const int kMaxEnvVarValueSize = 1024;
+#endif
+
+void SetEnvVar(const char* name, const char* value) {
+#ifdef _WIN32
+  SetEnvironmentVariableA(name, value);
+#else
+  if (value == nullptr) {
+    ::unsetenv(name);
+  } else {
+    ::setenv(name, value, 1);
+  }
+#endif
+}
+
+}  // namespace
+
+ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
+    : var_name_(var_name), was_unset_(false) {
+#ifdef _WIN32
+  char buf[kMaxEnvVarValueSize];
+  auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));
+  ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
+
+  if (get_res == 0) {
+    was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+  } else {
+    old_value_.assign(buf, get_res);
+  }
+
+  SetEnvironmentVariableA(var_name_.c_str(), new_value);
+#else
+  const char* val = ::getenv(var_name_.c_str());
+  if (val == nullptr) {
+    was_unset_ = true;
+  } else {
+    old_value_ = val;
+  }
+#endif
+
+  SetEnvVar(var_name_.c_str(), new_value);
+}
+
+ScopedSetEnv::~ScopedSetEnv() {
+  SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());
+}
+
+}  // namespace base_internal
+}  // namespace absl
diff --git a/absl/base/internal/scoped_set_env.h b/absl/base/internal/scoped_set_env.h
new file mode 100644
index 0000000..855b22f
--- /dev/null
+++ b/absl/base/internal/scoped_set_env.h
@@ -0,0 +1,41 @@
+//
+// 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_BASE_INTERNAL_SCOPED_SET_ENV_H_
+#define ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
+
+#include <string>
+
+namespace absl {
+namespace base_internal {
+
+class ScopedSetEnv {
+ public:
+  ScopedSetEnv(const char* var_name, const char* new_value);
+  ~ScopedSetEnv();
+
+ private:
+  std::string var_name_;
+  std::string old_value_;
+
+  // True if the environment variable was initially not set.
+  bool was_unset_;
+};
+
+}  // namespace base_internal
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
diff --git a/absl/base/internal/scoped_set_env_test.cc b/absl/base/internal/scoped_set_env_test.cc
new file mode 100644
index 0000000..5cbad24
--- /dev/null
+++ b/absl/base/internal/scoped_set_env_test.cc
@@ -0,0 +1,99 @@
+// 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.
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/scoped_set_env.h"
+
+namespace {
+
+using absl::base_internal::ScopedSetEnv;
+
+std::string GetEnvVar(const char* name) {
+#ifdef _WIN32
+  char buf[1024];
+  auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf));
+  if (get_res >= sizeof(buf)) {
+    return "TOO_BIG";
+  }
+
+  if (get_res == 0) {
+    return "UNSET";
+  }
+
+  return std::string(buf, get_res);
+#else
+  const char* val = ::getenv(name);
+  if (val == nullptr) {
+    return "UNSET";
+  }
+
+  return val;
+#endif
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToString) {
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToNull) {
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToString) {
+  ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "new_value");
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "new_value");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToNull) {
+  ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+  {
+    ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+    EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+  }
+
+  EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+}  // namespace
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc
index 1b97efb..7354438 100644
--- a/absl/base/internal/spinlock.cc
+++ b/absl/base/internal/spinlock.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -95,13 +95,9 @@
 }
 
 // Monitor the lock to see if its value changes within some time period
-// (adaptive_spin_count loop iterations).  A timestamp indicating
-// when the thread initially started waiting for the lock is passed in via
-// the initial_wait_timestamp value.  The total wait time in cycles for the
-// lock is returned in the wait_cycles parameter.  The last value read
-// from the lock is returned from the method.
-uint32_t SpinLock::SpinLoop(int64_t initial_wait_timestamp,
-                            uint32_t *wait_cycles) {
+// (adaptive_spin_count loop iterations). The last value read from the lock
+// is returned from the method.
+uint32_t SpinLock::SpinLoop() {
   // We are already in the slow path of SpinLock, initialize the
   // adaptive_spin_count here.
   ABSL_CONST_INIT static absl::once_flag init_adaptive_spin_count;
@@ -115,22 +111,21 @@
   do {
     lock_value = lockword_.load(std::memory_order_relaxed);
   } while ((lock_value & kSpinLockHeld) != 0 && --c > 0);
-  uint32_t spin_loop_wait_cycles =
-      EncodeWaitCycles(initial_wait_timestamp, CycleClock::Now());
-  *wait_cycles = spin_loop_wait_cycles;
-
-  return TryLockInternal(lock_value, spin_loop_wait_cycles);
+  return lock_value;
 }
 
 void SpinLock::SlowLock() {
+  uint32_t lock_value = SpinLoop();
+  lock_value = TryLockInternal(lock_value, 0);
+  if ((lock_value & kSpinLockHeld) == 0) {
+    return;
+  }
   // The lock was not obtained initially, so this thread needs to wait for
   // it.  Record the current timestamp in the local variable wait_start_time
   // so the total wait time can be stored in the lockword once this thread
   // obtains the lock.
   int64_t wait_start_time = CycleClock::Now();
-  uint32_t wait_cycles;
-  uint32_t lock_value = SpinLoop(wait_start_time, &wait_cycles);
-
+  uint32_t wait_cycles = 0;
   int lock_wait_call_count = 0;
   while ((lock_value & kSpinLockHeld) != 0) {
     // If the lock is currently held, but not marked as having a sleeper, mark
@@ -141,7 +136,7 @@
       // owner to think it experienced contention.
       if (lockword_.compare_exchange_strong(
               lock_value, lock_value | kSpinLockSleeper,
-              std::memory_order_acquire, std::memory_order_relaxed)) {
+              std::memory_order_relaxed, std::memory_order_relaxed)) {
         // Successfully transitioned to kSpinLockSleeper.  Pass
         // kSpinLockSleeper to the SpinLockWait routine to properly indicate
         // the last lock_value observed.
@@ -170,7 +165,9 @@
     ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
     // Spin again after returning from the wait routine to give this thread
     // some chance of obtaining the lock.
-    lock_value = SpinLoop(wait_start_time, &wait_cycles);
+    lock_value = SpinLoop();
+    wait_cycles = EncodeWaitCycles(wait_start_time, CycleClock::Now());
+    lock_value = TryLockInternal(lock_value, wait_cycles);
   }
 }
 
@@ -206,14 +203,20 @@
       (wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
 
   // Return a representation of the time spent waiting that can be stored in
-  // the lock word's upper bits.  bit_cast is required as Atomic32 is signed.
-  const uint32_t clamped = static_cast<uint32_t>(
+  // the lock word's upper bits.
+  uint32_t clamped = static_cast<uint32_t>(
       std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
 
-  // bump up value if necessary to avoid returning kSpinLockSleeper.
-  const uint32_t after_spinlock_sleeper =
-     kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
-  return clamped == kSpinLockSleeper ? after_spinlock_sleeper : clamped;
+  if (clamped == 0) {
+    return kSpinLockSleeper;  // Just wake waiters, but don't record contention.
+  }
+  // Bump up value if necessary to avoid returning kSpinLockSleeper.
+  const uint32_t kMinWaitTime =
+      kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
+  if (clamped == kSpinLockSleeper) {
+    return kMinWaitTime;
+  }
+  return clamped;
 }
 
 uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h
index 212abc6..4a31639 100644
--- a/absl/base/internal/spinlock.h
+++ b/absl/base/internal/spinlock.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -101,8 +101,8 @@
   inline void Unlock() UNLOCK_FUNCTION() {
     ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
     uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
-    lockword_.store(lock_value & kSpinLockCooperative,
-                    std::memory_order_release);
+    lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
+                                    std::memory_order_release);
 
     if ((lock_value & kSpinLockDisabledScheduling) != 0) {
       base_internal::SchedulingGuard::EnableRescheduling(true);
@@ -161,7 +161,7 @@
   void InitLinkerInitializedAndCooperative();
   void SlowLock() ABSL_ATTRIBUTE_COLD;
   void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
-  uint32_t SpinLoop(int64_t initial_wait_timestamp, uint32_t* wait_cycles);
+  uint32_t SpinLoop();
 
   inline bool TryLockImpl() {
     uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
diff --git a/absl/base/internal/spinlock_akaros.inc b/absl/base/internal/spinlock_akaros.inc
index 051c8cf..bc46894 100644
--- a/absl/base/internal/spinlock_akaros.inc
+++ b/absl/base/internal/spinlock_akaros.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/spinlock_benchmark.cc b/absl/base/internal/spinlock_benchmark.cc
new file mode 100644
index 0000000..0451c65
--- /dev/null
+++ b/absl/base/internal/spinlock_benchmark.cc
@@ -0,0 +1,52 @@
+// 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.
+
+// See also //absl/synchronization:mutex_benchmark for a comparison of SpinLock
+// and Mutex performance under varying levels of contention.
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/scheduling_mode.h"
+#include "absl/base/internal/spinlock.h"
+#include "absl/synchronization/internal/create_thread_identity.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+template <absl::base_internal::SchedulingMode scheduling_mode>
+static void BM_SpinLock(benchmark::State& state) {
+  // Ensure a ThreadIdentity is installed.
+  ABSL_INTERNAL_CHECK(
+      absl::synchronization_internal::GetOrCreateCurrentThreadIdentity() !=
+          nullptr,
+      "GetOrCreateCurrentThreadIdentity() failed");
+
+  static auto* spinlock = new absl::base_internal::SpinLock(scheduling_mode);
+  for (auto _ : state) {
+    absl::base_internal::SpinLockHolder holder(spinlock);
+  }
+}
+
+BENCHMARK_TEMPLATE(BM_SpinLock,
+                   absl::base_internal::SCHEDULE_KERNEL_ONLY)
+    ->UseRealTime()
+    ->Threads(1)
+    ->ThreadPerCpu();
+
+BENCHMARK_TEMPLATE(BM_SpinLock,
+                   absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL)
+    ->UseRealTime()
+    ->Threads(1)
+    ->ThreadPerCpu();
+
+}  // namespace
diff --git a/absl/base/internal/spinlock_linux.inc b/absl/base/internal/spinlock_linux.inc
index 94c861d..28e29d1 100644
--- a/absl/base/internal/spinlock_linux.inc
+++ b/absl/base/internal/spinlock_linux.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -51,17 +51,12 @@
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
     std::atomic<uint32_t> *w, uint32_t value, int loop,
     absl::base_internal::SchedulingMode) {
-  if (loop != 0) {
-    int save_errno = errno;
-    struct timespec tm;
-    tm.tv_sec = 0;
-    // Increase the delay; we expect (but do not rely on) explicit wakeups.
-    // We don't rely on explicit wakeups because we intentionally allow for
-    // a race on the kSpinLockSleeper bit.
-    tm.tv_nsec = 16 * absl::base_internal::SpinLockSuggestedDelayNS(loop);
-    syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
-    errno = save_errno;
-  }
+  int save_errno = errno;
+  struct timespec tm;
+  tm.tv_sec = 0;
+  tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
+  syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
+  errno = save_errno;
 }
 
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,
diff --git a/absl/base/internal/spinlock_posix.inc b/absl/base/internal/spinlock_posix.inc
index 0098c1c..f025b5f 100644
--- a/absl/base/internal/spinlock_posix.inc
+++ b/absl/base/internal/spinlock_posix.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/spinlock_wait.cc b/absl/base/internal/spinlock_wait.cc
index 0fde9c0..fac8a21 100644
--- a/absl/base/internal/spinlock_wait.cc
+++ b/absl/base/internal/spinlock_wait.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -38,14 +38,15 @@
 uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
                       const SpinLockWaitTransition trans[],
                       base_internal::SchedulingMode scheduling_mode) {
-  for (int loop = 0; ; loop++) {
+  int loop = 0;
+  for (;;) {
     uint32_t v = w->load(std::memory_order_acquire);
     int i;
     for (i = 0; i != n && v != trans[i].from; i++) {
     }
     if (i == n) {
-      SpinLockDelay(w, v, loop, scheduling_mode);  // no matching transition
-    } else if (trans[i].to == v ||                 // null transition
+      SpinLockDelay(w, v, ++loop, scheduling_mode);  // no matching transition
+    } else if (trans[i].to == v ||                   // null transition
                w->compare_exchange_strong(v, trans[i].to,
                                           std::memory_order_acquire,
                                           std::memory_order_relaxed)) {
@@ -64,17 +65,14 @@
   r = 0x5deece66dLL * r + 0xb;   // numbers from nrand48()
   delay_rand.store(r, std::memory_order_relaxed);
 
-  r <<= 16;   // 48-bit random number now in top 48-bits.
   if (loop < 0 || loop > 32) {   // limit loop to 0..32
     loop = 32;
   }
-  // loop>>3 cannot exceed 4 because loop cannot exceed 32.
-  // Select top 20..24 bits of lower 48 bits,
-  // giving approximately 0ms to 16ms.
-  // Mean is exponential in loop for first 32 iterations, then 8ms.
-  // The futex path multiplies this by 16, since we expect explicit wakeups
-  // almost always on that path.
-  return static_cast<int>(r >> (44 - (loop >> 3)));
+  const int kMinDelay = 128 << 10;  // 128us
+  // Double delay every 8 iterations, up to 16x (2ms).
+  int delay = kMinDelay << (loop / 8);
+  // Randomize in delay..2*delay range, for resulting 128us..4ms range.
+  return delay | ((delay - 1) & static_cast<int>(r));
 }
 
 }  // namespace base_internal
diff --git a/absl/base/internal/spinlock_wait.h b/absl/base/internal/spinlock_wait.h
index 5c6cc7f..6642ce1 100644
--- a/absl/base/internal/spinlock_wait.h
+++ b/absl/base/internal/spinlock_wait.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/spinlock_win32.inc b/absl/base/internal/spinlock_win32.inc
index 32c8fc0..78654b5 100644
--- a/absl/base/internal/spinlock_win32.inc
+++ b/absl/base/internal/spinlock_win32.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index db41bac..4dd3add 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/sysinfo.h b/absl/base/internal/sysinfo.h
index 5bd1c50..b864a59 100644
--- a/absl/base/internal/sysinfo.h
+++ b/absl/base/internal/sysinfo.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc
index e0d9aab..247f3d8 100644
--- a/absl/base/internal/sysinfo_test.cc
+++ b/absl/base/internal/sysinfo_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index cff9c1b..91273a6 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index a51722f..b34674a 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -42,9 +42,9 @@
 class SpinLock;
 struct ThreadIdentity;
 
-// Used by the implementation of base::Mutex and base::CondVar.
+// Used by the implementation of absl::Mutex and absl::CondVar.
 struct PerThreadSynch {
-  // The internal representation of base::Mutex and base::CondVar rely
+  // The internal representation of absl::Mutex and absl::CondVar rely
   // on the alignment of PerThreadSynch. Both store the address of the
   // PerThreadSynch in the high-order bits of their internal state,
   // which means the low kLowZeroBits of the address of PerThreadSynch
@@ -237,4 +237,5 @@
 
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
diff --git a/absl/base/internal/thread_identity_benchmark.cc b/absl/base/internal/thread_identity_benchmark.cc
index 242522b..0ae10f2 100644
--- a/absl/base/internal/thread_identity_benchmark.cc
+++ b/absl/base/internal/thread_identity_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/thread_identity_test.cc b/absl/base/internal/thread_identity_test.cc
index ecb8af6..13bfbe3 100644
--- a/absl/base/internal/thread_identity_test.cc
+++ b/absl/base/internal/thread_identity_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc
index 46dc573..8e928b8 100644
--- a/absl/base/internal/throw_delegate.cc
+++ b/absl/base/internal/throw_delegate.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -30,8 +30,8 @@
 #ifdef ABSL_HAVE_EXCEPTIONS
   throw error;
 #else
-  ABSL_RAW_LOG(ERROR, "%s", error.what());
-  abort();
+  ABSL_RAW_LOG(FATAL, "%s", error.what());
+  std::abort();
 #endif
 }
 }  // namespace
diff --git a/absl/base/internal/throw_delegate.h b/absl/base/internal/throw_delegate.h
index 70e2d77..03c700b 100644
--- a/absl/base/internal/throw_delegate.h
+++ b/absl/base/internal/throw_delegate.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/tsan_mutex_interface.h b/absl/base/internal/tsan_mutex_interface.h
index 6bb4fae..2a51060 100644
--- a/absl/base/internal/tsan_mutex_interface.h
+++ b/absl/base/internal/tsan_mutex_interface.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index f9df3b7..2d66737 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc
index a12d68b..593762b 100644
--- a/absl/base/internal/unscaledcycleclock.cc
+++ b/absl/base/internal/unscaledcycleclock.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h
index 049f1ca..58950cc 100644
--- a/absl/base/internal/unscaledcycleclock.h
+++ b/absl/base/internal/unscaledcycleclock.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -83,6 +83,7 @@
       defined(_M_IX86) || defined(_M_X64))
 #define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
 #endif
+
 namespace absl {
 namespace time_internal {
 class UnscaledCycleClockWrapperForGetCurrentTime;
@@ -114,6 +115,7 @@
 
 }  // namespace base_internal
 }  // namespace absl
+
 #endif  // ABSL_USE_UNSCALED_CYCLECLOCK
 
 #endif  // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
diff --git a/absl/base/invoke_test.cc b/absl/base/invoke_test.cc
index 466bf11..691f553 100644
--- a/absl/base/invoke_test.cc
+++ b/absl/base/invoke_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index 5770d36..b19a7ff 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -4,14 +4,13 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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_BASE_INTERNAL_LOG_SEVERITY_H_
 #define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
diff --git a/absl/base/macros.h b/absl/base/macros.h
index ca3d5ed..5b43d7c 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -24,7 +24,6 @@
 // This code is compiled directly on many platforms, including client
 // platforms like Windows, Mac, and embedded systems.  Before making
 // any changes here, make sure that you're not breaking any platforms.
-//
 
 #ifndef ABSL_BASE_MACROS_H_
 #define ABSL_BASE_MACROS_H_
@@ -199,4 +198,14 @@
                              : [] { assert(false && #expr); }())  // NOLINT
 #endif
 
+#ifdef ABSL_HAVE_EXCEPTIONS
+#define ABSL_INTERNAL_TRY try
+#define ABSL_INTERNAL_CATCH_ANY catch (...)
+#define ABSL_INTERNAL_RETHROW do { throw; } while (false)
+#else  // ABSL_HAVE_EXCEPTIONS
+#define ABSL_INTERNAL_TRY if (true)
+#define ABSL_INTERNAL_CATCH_ANY else if (false)
+#define ABSL_INTERNAL_RETHROW do {} while (false)
+#endif  // ABSL_HAVE_EXCEPTIONS
+
 #endif  // ABSL_BASE_MACROS_H_
diff --git a/absl/base/optimization.h b/absl/base/optimization.h
index 2fddfc8..6974f1f 100644
--- a/absl/base/optimization.h
+++ b/absl/base/optimization.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -111,9 +111,9 @@
 // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
 // for more information.
 //
-// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to
-// `__attribute__((aligned(ABSL_CACHELINE_SIZE)))`. For compilers where this is
-// not known to work, the macro expands to nothing.
+// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__`
+// or `__declspec` attribute. For compilers where this is not known to work,
+// the macro expands to nothing.
 //
 // No further guarantees are made here. The result of applying the macro
 // to variables and types is always implementation-defined.
@@ -122,6 +122,14 @@
 // of causing bugs that are difficult to diagnose, crash, etc. It does not
 // of itself guarantee that objects are aligned to a cache line.
 //
+// NOTE: Some compilers are picky about the locations of annotations such as
+// this attribute, so prefer to put it at the beginning of your declaration.
+// For example,
+//
+//   ABSL_CACHELINE_ALIGNED static Foo* foo = ...
+//
+//   class ABSL_CACHELINE_ALIGNED Bar { ...
+//
 // Recommendations:
 //
 // 1) Consult compiler documentation; this comment is not kept in sync as
@@ -131,8 +139,10 @@
 // 3) Prefer applying this attribute to individual variables. Avoid
 //    applying it to types. This tends to localize the effect.
 #define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
-
-#else  // not GCC
+#elif defined(_MSC_VER)
+#define ABSL_CACHELINE_SIZE 64
+#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
+#else
 #define ABSL_CACHELINE_SIZE 64
 #define ABSL_CACHELINE_ALIGNED
 #endif
diff --git a/absl/base/policy_checks.h b/absl/base/policy_checks.h
index 0a07fc0..699fb1a 100644
--- a/absl/base/policy_checks.h
+++ b/absl/base/policy_checks.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/port.h b/absl/base/port.h
index 1c67257..6c28068 100644
--- a/absl/base/port.h
+++ b/absl/base/port.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/raw_logging_test.cc b/absl/base/raw_logging_test.cc
index b21cf65..3d30bd3 100644
--- a/absl/base/raw_logging_test.cc
+++ b/absl/base/raw_logging_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc
index 1b50884..e62b2ea 100644
--- a/absl/base/spinlock_test_common.cc
+++ b/absl/base/spinlock_test_common.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -54,6 +54,7 @@
 
 static constexpr int kArrayLength = 10;
 static uint32_t values[kArrayLength];
+
 static SpinLock static_spinlock(base_internal::kLinkerInitialized);
 static SpinLock static_cooperative_spinlock(
     base_internal::kLinkerInitialized,
@@ -155,7 +156,8 @@
 
   // Test corner cases
   int64_t start_time = time_distribution(generator);
-  EXPECT_EQ(0, SpinLockTest::EncodeWaitCycles(start_time, start_time));
+  EXPECT_EQ(kSpinLockSleeper,
+            SpinLockTest::EncodeWaitCycles(start_time, start_time));
   EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(0));
   EXPECT_EQ(0, SpinLockTest::DecodeWaitCycles(kLockwordReservedMask));
   EXPECT_EQ(kMaxCycles & ~kProfileTimestampMask,
@@ -188,6 +190,7 @@
     SpinLockTest::DecodeWaitCycles(before_max_value);
   EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
 }
+
 TEST(SpinLockWithThreads, StaticSpinLock) {
   ThreadedTest(&static_spinlock);
 }
diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h
index fbb2797..0b2c306 100644
--- a/absl/base/thread_annotations.h
+++ b/absl/base/thread_annotations.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -21,7 +21,6 @@
 // code. The annotations can also help program analysis tools to identify
 // potential thread safety issues.
 //
-//
 // These annotations are implemented using compiler attributes. Using the macros
 // defined here instead of raw attributes allow for portability and future
 // compatibility.
@@ -34,6 +33,7 @@
 
 #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
 #define ABSL_BASE_THREAD_ANNOTATIONS_H_
+
 #if defined(__clang__)
 #define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
 #else
@@ -108,13 +108,23 @@
 // The mutex is expected to be held both on entry to, and exit from, the
 // function.
 //
+// An exclusive lock allows read-write access to the guarded data member(s), and
+// only one thread can acquire a lock exclusively at any one time. A shared lock
+// allows read-only access, and any number of threads can acquire a shared lock
+// concurrently.
+//
+// Generally, non-const methods should be annotated with
+// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
+// SHARED_LOCKS_REQUIRED.
+//
 // Example:
 //
 //   Mutex mu1, mu2;
 //   int a GUARDED_BY(mu1);
 //   int b GUARDED_BY(mu2);
 //
-//   void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... };
+//   void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
+//   void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
 #define EXCLUSIVE_LOCKS_REQUIRED(...) \
   THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
 
diff --git a/absl/base/throw_delegate_test.cc b/absl/base/throw_delegate_test.cc
index 0f15df0..a74dd3c 100644
--- a/absl/base/throw_delegate_test.cc
+++ b/absl/base/throw_delegate_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
index b77c4f5..6696229 100644
--- a/absl/compiler_config_setting.bzl
+++ b/absl/compiler_config_setting.bzl
@@ -5,35 +5,34 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
-    )
+    # 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 f2210e3..cd914ba 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,11 +15,11 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
-    "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
     "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
+    "ABSL_TEST_COPTS",
 )
 
 package(default_visibility = ["//visibility:public"])
@@ -41,6 +41,8 @@
     copts = ABSL_TEST_COPTS,
     deps = [
         ":compressed_tuple",
+        "//absl/memory",
+        "//absl/utility",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -110,10 +112,20 @@
 )
 
 cc_library(
+    name = "inlined_vector_internal",
+    hdrs = ["internal/inlined_vector.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_library(
     name = "inlined_vector",
     hdrs = ["inlined_vector.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
+        ":inlined_vector_internal",
         "//absl/algorithm",
         "//absl/base:core_headers",
         "//absl/base:throw_delegate",
@@ -121,12 +133,21 @@
     ],
 )
 
+cc_library(
+    name = "counting_allocator",
+    testonly = 1,
+    hdrs = ["internal/counting_allocator.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+)
+
 cc_test(
     name = "inlined_vector_test",
     srcs = ["inlined_vector_test.cc"],
     copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
     linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
     deps = [
+        ":counting_allocator",
         ":inlined_vector",
         ":test_instance_tracker",
         "//absl/base",
@@ -144,6 +165,7 @@
     srcs = ["inlined_vector_test.cc"],
     copts = ABSL_TEST_COPTS,
     deps = [
+        ":counting_allocator",
         ":inlined_vector",
         ":test_instance_tracker",
         "//absl/base",
@@ -212,6 +234,7 @@
         ":container_memory",
         ":hash_function_defaults",
         ":raw_hash_map",
+        "//absl/algorithm:container",
         "//absl/memory",
     ],
 )
@@ -219,13 +242,14 @@
 cc_test(
     name = "flat_hash_map_test",
     srcs = ["flat_hash_map_test.cc"],
-    copts = ABSL_TEST_COPTS + ["-DUNORDERED_MAP_CXX17"],
+    copts = ABSL_TEST_COPTS,
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
         ":flat_hash_map",
         ":hash_generator_testing",
         ":unordered_map_constructor_test",
         ":unordered_map_lookup_test",
+        ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "//absl/types:any",
         "@com_google_googletest//:gtest_main",
@@ -240,6 +264,7 @@
         ":container_memory",
         ":hash_function_defaults",
         ":raw_hash_set",
+        "//absl/algorithm:container",
         "//absl/base:core_headers",
         "//absl/memory",
     ],
@@ -255,6 +280,7 @@
         ":hash_generator_testing",
         ":unordered_set_constructor_test",
         ":unordered_set_lookup_test",
+        ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "//absl/memory",
         "//absl/strings",
@@ -271,6 +297,7 @@
         ":hash_function_defaults",
         ":node_hash_policy",
         ":raw_hash_map",
+        "//absl/algorithm:container",
         "//absl/memory",
     ],
 )
@@ -278,7 +305,7 @@
 cc_test(
     name = "node_hash_map_test",
     srcs = ["node_hash_map_test.cc"],
-    copts = ABSL_TEST_COPTS + ["-DUNORDERED_MAP_CXX17"],
+    copts = ABSL_TEST_COPTS,
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
         ":hash_generator_testing",
@@ -286,6 +313,7 @@
         ":tracked",
         ":unordered_map_constructor_test",
         ":unordered_map_lookup_test",
+        ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
@@ -296,10 +324,10 @@
     hdrs = ["node_hash_set.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
-        ":container_memory",
         ":hash_function_defaults",
         ":node_hash_policy",
         ":raw_hash_set",
+        "//absl/algorithm:container",
         "//absl/memory",
     ],
 )
@@ -310,10 +338,10 @@
     copts = ABSL_TEST_COPTS + ["-DUNORDERED_SET_CXX17"],
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
-        ":hash_generator_testing",
         ":node_hash_set",
         ":unordered_set_constructor_test",
         ":unordered_set_lookup_test",
+        ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
@@ -432,6 +460,39 @@
 )
 
 cc_library(
+    name = "hashtablez_sampler",
+    srcs = [
+        "internal/hashtablez_sampler.cc",
+        "internal/hashtablez_sampler_force_weak_definition.cc",
+    ],
+    hdrs = ["internal/hashtablez_sampler.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":have_sse",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/debugging:stacktrace",
+        "//absl/memory",
+        "//absl/synchronization",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "hashtablez_sampler_test",
+    srcs = ["internal/hashtablez_sampler_test.cc"],
+    deps = [
+        ":hashtablez_sampler",
+        ":have_sse",
+        "//absl/base:core_headers",
+        "//absl/synchronization",
+        "//absl/synchronization:thread_pool",
+        "//absl/time",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "node_hash_policy",
     hdrs = ["internal/node_hash_policy.h"],
     copts = ABSL_DEFAULT_COPTS,
@@ -459,15 +520,35 @@
 )
 
 cc_library(
+    name = "have_sse",
+    hdrs = ["internal/have_sse.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+)
+
+cc_library(
+    name = "common",
+    hdrs = ["internal/common.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
+        "//absl/types:optional",
+    ],
+)
+
+cc_library(
     name = "raw_hash_set",
     srcs = ["internal/raw_hash_set.cc"],
     hdrs = ["internal/raw_hash_set.h"],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
+        ":common",
         ":compressed_tuple",
         ":container_memory",
         ":hash_policy_traits",
         ":hashtable_debug_hooks",
+        ":hashtablez_sampler",
+        ":have_sse",
         ":layout",
         "//absl/base:bits",
         "//absl/base:config",
@@ -475,7 +556,6 @@
         "//absl/base:endian",
         "//absl/memory",
         "//absl/meta:type_traits",
-        "//absl/types:optional",
         "//absl/utility",
     ],
 )
@@ -592,6 +672,29 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "unordered_set_members_test",
+    testonly = 1,
+    hdrs = ["internal/unordered_set_members_test.h"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "unordered_map_members_test",
+    testonly = 1,
+    hdrs = ["internal/unordered_map_members_test.h"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        "//absl/meta:type_traits",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -628,6 +731,7 @@
     deps = [
         ":unordered_set_constructor_test",
         ":unordered_set_lookup_test",
+        ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
@@ -641,6 +745,7 @@
     deps = [
         ":unordered_map_constructor_test",
         ":unordered_map_lookup_test",
+        ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "@com_google_googletest//:gtest_main",
     ],
diff --git a/absl/container/BUILD.gn b/absl/container/BUILD.gn
index a2fbd54..3b8ece7 100644
--- a/absl/container/BUILD.gn
+++ b/absl/container/BUILD.gn
@@ -49,6 +49,21 @@
   ]
 }
 
+source_set("inlined_vector_internal") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/inlined_vector.h",
+  ]
+  deps = [
+    "../meta:type_traits",
+  ]
+}
+
 source_set("inlined_vector") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -60,6 +75,7 @@
     "inlined_vector.h",
   ]
   deps = [
+    ":inlined_vector_internal",
     "../algorithm",
     "../base:core_headers",
     "../base:throw_delegate",
@@ -67,6 +83,21 @@
   ]
 }
 
+source_set("counting_allocator") {
+  testonly = true
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/counting_allocator.h",
+  ]
+  visibility = []
+  visibility += [ ":*" ]
+}
+
 source_set("test_instance_tracker") {
   testonly = true
   configs -= [ "//build/config/compiler:chromium_code" ]
@@ -99,6 +130,7 @@
     ":container_memory",
     ":hash_function_defaults",
     ":raw_hash_map",
+    "../algorithm:container",
     "../memory",
   ]
 }
@@ -117,6 +149,7 @@
     ":container_memory",
     ":hash_function_defaults",
     ":raw_hash_set",
+    "../algorithm:container",
     "../base:core_headers",
     "../memory",
   ]
@@ -137,6 +170,7 @@
     ":hash_function_defaults",
     ":node_hash_policy",
     ":raw_hash_map",
+    "../algorithm:container",
     "../memory",
   ]
 }
@@ -156,6 +190,7 @@
     ":hash_function_defaults",
     ":node_hash_policy",
     ":raw_hash_set",
+    "../algorithm:container",
     "../memory",
   ]
 }
@@ -273,6 +308,31 @@
   ]
 }
 
+source_set("hashtablez_sampler") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/hashtablez_sampler.h",
+  ]
+  sources = [
+    "internal/hashtablez_sampler.cc",
+    "internal/hashtablez_sampler_force_weak_definition.cc",
+  ]
+  deps = [
+    ":have_sse",
+    "../base",
+    "../base:core_headers",
+    "../debugging:stacktrace",
+    "../memory",
+    "../synchronization",
+    "../utility",
+  ]
+}
+
 source_set("node_hash_policy") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -301,6 +361,36 @@
   ]
 }
 
+source_set("have_sse") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/have_sse.h",
+  ]
+  visibility = []
+  visibility += [ ":*" ]
+}
+
+source_set("common") {
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/common.h",
+  ]
+  deps = [
+    "../meta:type_traits",
+    "../types:optional",
+  ]
+}
+
 source_set("raw_hash_set") {
   configs -= [ "//build/config/compiler:chromium_code" ]
   configs += [
@@ -315,10 +405,13 @@
     "internal/raw_hash_set.h",
   ]
   deps = [
+    ":common",
     ":compressed_tuple",
     ":container_memory",
     ":hash_policy_traits",
     ":hashtable_debug_hooks",
+    ":hashtablez_sampler",
+    ":have_sse",
     ":layout",
     "../base:bits",
     "../base:config",
@@ -326,7 +419,6 @@
     "../base:endian",
     "../memory",
     "../meta:type_traits",
-    "../types:optional",
     "../utility",
   ]
 }
@@ -431,6 +523,41 @@
   deps = [
     ":hash_generator_testing",
     ":hash_policy_testing",
+    "../meta:type_traits",
+    "//testing/gtest",
+  ]
+}
+
+source_set("unordered_set_members_test") {
+  testonly = true
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/unordered_set_members_test.h",
+  ]
+  deps = [
+    "../meta:type_traits",
+    "//testing/gtest",
+  ]
+}
+
+source_set("unordered_map_members_test") {
+  testonly = true
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  public = [
+    "internal/unordered_map_members_test.h",
+  ]
+  deps = [
+    "../meta:type_traits",
     "//testing/gtest",
   ]
 }
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 9e40690..292fea2 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,163 +14,772 @@
 # limitations under the License.
 #
 
-
-list(APPEND CONTAINER_PUBLIC_HEADERS
-  "fixed_array.h"
-  "flat_hash_map.h"
-  "flat_hash_set.h"
-  "inlined_vector.h"
-  "node_hash_map.h"
-  "node_hash_set.h"
-)
-
-
-list(APPEND CONTAINER_INTERNAL_HEADERS
-  "internal/compressed_tuple.h"
-  "internal/container_memory.h"
-  "internal/hash_function_defaults.h"
-  "internal/hash_generator_testing.h"
-  "internal/hash_policy_testing.h"
-  "internal/hash_policy_traits.h"
-  "internal/hashtable_debug.h"
-  "internal/layout.h"
-  "internal/node_hash_policy.h"
-  "internal/raw_hash_map.h"
-  "internal/raw_hash_set.h"
-  "internal/test_instance_tracker.h"
-  "internal/tracked.h"
-  "internal/unordered_map_constructor_test.h"
-  "internal/unordered_map_lookup_test.h"
-  "internal/unordered_map_modifiers_test.h"
-  "internal/unordered_set_constructor_test.h"
-  "internal/unordered_set_lookup_test.h"
-  "internal/unordered_set_modifiers_test.h"
-)
-
-
-absl_library(
-  TARGET
-    absl_container
-  SOURCES
-    "internal/raw_hash_set.cc"
-  EXPORT_NAME
+# This is deprecated and will be removed in the future.  It also doesn't do
+# anything anyways.  Prefer to use the library associated with the API you are
+# using.
+absl_cc_library(
+  NAME
     container
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-list(APPEND TEST_INSTANCE_TRACKER_LIB_SRC
-  "internal/test_instance_tracker.cc"
-  ${CONTAINER_PUBLIC_HEADERS}
-  ${CONTAINER_INTERNAL_HEADERS}
+absl_cc_library(
+  NAME
+    compressed_tuple
+  HDRS
+   "internal/compressed_tuple.h"
+  DEPS
+    absl::utility
+  PUBLIC
 )
 
-
-absl_library(
-  TARGET
-    test_instance_tracker_lib
-  SOURCES
-    ${TEST_INSTANCE_TRACKER_LIB_SRC}
-  PUBLIC_LIBRARIES
-    absl::container
+absl_cc_test(
+  NAME
+    compressed_tuple_test
+  SRCS
+    "internal/compressed_tuple_test.cc"
+  DEPS
+    absl::compressed_tuple
+    absl::memory
+    absl::utility
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    fixed_array
+  HDRS
+   "fixed_array.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::compressed_tuple
+    absl::algorithm
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::throw_delegate
+    absl::memory
+  PUBLIC
+)
 
-
-# test fixed_array_test
-set(FIXED_ARRAY_TEST_SRC "fixed_array_test.cc")
-set(FIXED_ARRAY_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     fixed_array_test
-  SOURCES
-    ${FIXED_ARRAY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${FIXED_ARRAY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "fixed_array_test.cc"
+  COPTS
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::fixed_array
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    gmock_main
 )
 
-
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     fixed_array_test_noexceptions
-  SOURCES
-    ${FIXED_ARRAY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${FIXED_ARRAY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "fixed_array_test.cc"
+  DEPS
+    absl::fixed_array
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    gmock_main
 )
 
-
-# test fixed_array_exception_safety_test
-set(FIXED_ARRAY_EXCEPTION_SAFETY_TEST_SRC "fixed_array_exception_safety_test.cc")
-set(FIXED_ARRAY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::container
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     fixed_array_exception_safety_test
-  SOURCES
-    ${FIXED_ARRAY_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${FIXED_ARRAY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "fixed_array_exception_safety_test.cc"
+  COPTS
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::fixed_array
+    absl::exception_safety_testing
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    inlined_vector_internal
+  HDRS
+   "internal/inlined_vector.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::type_traits
+  PUBLIC
+)
 
-# test inlined_vector_test
-set(INLINED_VECTOR_TEST_SRC "inlined_vector_test.cc")
-set(INLINED_VECTOR_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
+absl_cc_library(
+  NAME
+    inlined_vector
+  HDRS
+   "inlined_vector.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::algorithm
+    absl::core_headers
+    absl::throw_delegate
+    absl::memory
+  PUBLIC
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    counting_allocator
+  HDRS
+    "internal/counting_allocator.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_test(
+  NAME
     inlined_vector_test
-  SOURCES
-    ${INLINED_VECTOR_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INLINED_VECTOR_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "inlined_vector_test.cc"
+  COPTS
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::counting_allocator
+    absl::inlined_vector
+    absl::test_instance_tracker
+    absl::base
+    absl::core_headers
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    absl::strings
+    gmock_main
 )
 
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     inlined_vector_test_noexceptions
-  SOURCES
-    ${INLINED_VECTOR_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INLINED_VECTOR_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_NOEXCEPTION_CXXFLAGS}
+  SRCS
+    "inlined_vector_test.cc"
+  DEPS
+    absl::inlined_vector
+    absl::test_instance_tracker
+    absl::base
+    absl::core_headers
+    absl::exception_testing
+    absl::hash_testing
+    absl::memory
+    absl::strings
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    test_instance_tracker
+  HDRS
+    "internal/test_instance_tracker.h"
+  SRCS
+    "internal/test_instance_tracker.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  TESTONLY
+)
 
-# test test_instance_tracker_test
-set(TEST_INSTANCE_TRACKER_TEST_SRC "internal/test_instance_tracker_test.cc")
-set(TEST_INSTANCE_TRACKER_TEST_PUBLIC_LIBRARIES absl::base absl_throw_delegate test_instance_tracker_lib)
-
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     test_instance_tracker_test
-  SOURCES
-    ${TEST_INSTANCE_TRACKER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${TEST_INSTANCE_TRACKER_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/test_instance_tracker_test.cc"
+  DEPS
+    absl::test_instance_tracker
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    flat_hash_map
+  HDRS
+    "flat_hash_map.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::raw_hash_map
+    absl::algorithm_container
+    absl::memory
+  PUBLIC
+)
 
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
+    flat_hash_map_test
+  SRCS
+    "flat_hash_map_test.cc"
+  DEPS
+    absl::flat_hash_map
+    absl::hash_generator_testing
+    absl::unordered_map_constructor_test
+    absl::unordered_map_lookup_test
+    absl::unordered_map_members_test
+    absl::unordered_map_modifiers_test
+    absl::any
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    flat_hash_set
+  HDRS
+    "flat_hash_set.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::raw_hash_set
+    absl::algorithm_container
+    absl::core_headers
+    absl::memory
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    flat_hash_set_test
+  SRCS
+    "flat_hash_set_test.cc"
+  COPTS
+    "-DUNORDERED_SET_CXX17"
+  DEPS
+    absl::flat_hash_set
+    absl::hash_generator_testing
+    absl::unordered_set_constructor_test
+    absl::unordered_set_lookup_test
+    absl::unordered_set_members_test
+    absl::unordered_set_modifiers_test
+    absl::memory
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    node_hash_map
+  HDRS
+    "node_hash_map.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::node_hash_policy
+    absl::raw_hash_map
+    absl::algorithm_container
+    absl::memory
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    node_hash_map_test
+  SRCS
+    "node_hash_map_test.cc"
+  DEPS
+    absl::hash_generator_testing
+    absl::node_hash_map
+    absl::tracked
+    absl::unordered_map_constructor_test
+    absl::unordered_map_lookup_test
+    absl::unordered_map_members_test
+    absl::unordered_map_modifiers_test
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    node_hash_set
+  HDRS
+    "node_hash_set.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hash_function_defaults
+    absl::node_hash_policy
+    absl::raw_hash_set
+    absl::algorithm_container
+    absl::memory
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    node_hash_set_test
+  SRCS
+    "node_hash_set_test.cc"
+  COPTS
+    "-DUNORDERED_SET_CXX17"
+  DEPS
+    absl::hash_generator_testing
+    absl::node_hash_set
+    absl::unordered_set_constructor_test
+    absl::unordered_set_lookup_test
+    absl::unordered_set_members_test
+    absl::unordered_set_modifiers_test
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    container_memory
+  HDRS
+    "internal/container_memory.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::memory
+    absl::utility
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    container_memory_test
+  SRCS
+    "internal/container_memory_test.cc"
+  DEPS
+    absl::container_memory
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hash_function_defaults
+  HDRS
+    "internal/hash_function_defaults.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::hash
+    absl::strings
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    hash_function_defaults_test
+  SRCS
+    "internal/hash_function_defaults_test.cc"
+  DEPS
+    absl::hash_function_defaults
+    absl::hash
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hash_generator_testing
+  HDRS
+    "internal/hash_generator_testing.h"
+  SRCS
+    "internal/hash_generator_testing.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_policy_testing
+    absl::meta
+    absl::strings
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    hash_policy_testing
+  HDRS
+    "internal/hash_policy_testing.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash
+    absl::strings
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    hash_policy_testing_test
+  SRCS
+    "internal/hash_policy_testing_test.cc"
+  DEPS
+    absl::hash_policy_testing
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hash_policy_traits
+  HDRS
+    "internal/hash_policy_traits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::meta
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    hash_policy_traits_test
+  SRCS
+    "internal/hash_policy_traits_test.cc"
+  DEPS
+    absl::hash_policy_traits
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hashtablez_sampler
+  HDRS
+    "internal/hashtablez_sampler.h"
+  SRCS
+    "internal/hashtablez_sampler.cc"
+    "internal/hashtablez_sampler_force_weak_definition.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::have_sse
+    absl::synchronization
+)
+
+absl_cc_test(
+  NAME
+    hashtablez_sampler_test
+  SRCS
+    "internal/hashtablez_sampler_test.cc"
+  DEPS
+    absl::hashtablez_sampler
+    absl::have_sse
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    hashtable_debug
+  HDRS
+    "internal/hashtable_debug.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hashtable_debug_hooks
+)
+
+absl_cc_library(
+  NAME
+    hashtable_debug_hooks
+  HDRS
+    "internal/hashtable_debug_hooks.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    have_sse
+  HDRS
+    "internal/have_sse.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    node_hash_policy
+  HDRS
+    "internal/node_hash_policy.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    node_hash_policy_test
+  SRCS
+    "internal/node_hash_policy_test.cc"
+  DEPS
+    absl::hash_policy_traits
+    absl::node_hash_policy
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    raw_hash_map
+  HDRS
+    "internal/raw_hash_map.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::container_memory
+    absl::raw_hash_set
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    container_common
+  HDRS
+    "internal/commom.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::type_traits
+)
+
+absl_cc_library(
+  NAME
+    raw_hash_set
+  HDRS
+    "internal/raw_hash_set.h"
+  SRCS
+    "internal/raw_hash_set.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bits
+    absl::compressed_tuple
+    absl::config
+    absl::container_common
+    absl::container_memory
+    absl::core_headers
+    absl::endian
+    absl::hash_policy_traits
+    absl::hashtable_debug_hooks
+    absl::have_sse
+    absl::layout
+    absl::memory
+    absl::meta
+    absl::optional
+    absl::utility
+    absl::hashtablez_sampler
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
     raw_hash_set_test
-  SOURCES
+  SRCS
     "internal/raw_hash_set_test.cc"
-  PUBLIC_LIBRARIES
-    absl::base absl::hash absl_throw_delegate test_instance_tracker_lib
+  DEPS
+    absl::container_memory
+    absl::hash_function_defaults
+    absl::hash_policy_testing
+    absl::hashtable_debug
+    absl::raw_hash_set
+    absl::base
+    absl::core_headers
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    raw_hash_set_allocator_test
+  SRCS
+    "internal/raw_hash_set_allocator_test.cc"
+  DEPS
+    absl::raw_hash_set
+    absl::tracked
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    layout
+  HDRS
+    "internal/layout.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::meta
+    absl::strings
+    absl::span
+    absl::utility
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    layout_test
+  SRCS
+    "internal/layout_test.cc"
+  DEPS
+    absl::layout
+    absl::base
+    absl::core_headers
+    absl::span
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    tracked
+  HDRS
+    "internal/tracked.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_constructor_test
+  HDRS
+    "internal/unordered_map_constructor_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_lookup_test
+  HDRS
+    "internal/unordered_map_lookup_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_members_test
+  HDRS
+    "internal/unordered_map_members_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::type_traits
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_map_modifiers_test
+  HDRS
+    "internal/unordered_map_modifiers_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_constructor_test
+  HDRS
+    "internal/unordered_set_constructor_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_lookup_test
+  HDRS
+    "internal/unordered_set_lookup_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_members_test
+  HDRS
+    "internal/unordered_set_members_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::type_traits
+    gmock
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    unordered_set_modifiers_test
+  HDRS
+    "internal/unordered_set_modifiers_test.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::hash_generator_testing
+    absl::hash_policy_testing
+    gmock
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    unordered_set_test
+  SRCS
+    "internal/unordered_set_test.cc"
+  DEPS
+    absl::unordered_set_constructor_test
+    absl::unordered_set_lookup_test
+    absl::unordered_set_members_test
+    absl::unordered_set_modifiers_test
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    unordered_map_test
+  SRCS
+    "internal/unordered_map_test.cc"
+  DEPS
+    absl::unordered_map_constructor_test
+    absl::unordered_map_lookup_test
+    absl::unordered_map_members_test
+    absl::unordered_map_modifiers_test
+    gmock_main
 )
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 6d9fa5f..60da048 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -188,7 +188,7 @@
   // `FixedArray<T>`. This is equivalent to the most possible addressable bytes
   // over the number of bytes taken by T.
   constexpr size_type max_size() const {
-    return std::numeric_limits<difference_type>::max() / sizeof(value_type);
+    return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
   }
 
   // FixedArray::empty()
@@ -515,4 +515,5 @@
   static_cast<void>(n);  // Mark used when not in asan mode
 }
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_FIXED_ARRAY_H_
diff --git a/absl/container/fixed_array_benchmark.cc b/absl/container/fixed_array_benchmark.cc
index b4f0cf2..ff56f46 100644
--- a/absl/container/fixed_array_benchmark.cc
+++ b/absl/container/fixed_array_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc
index da63dbf..826eca6 100644
--- a/absl/container/fixed_array_exception_safety_test.cc
+++ b/absl/container/fixed_array_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc
index 205ff41..a4f2498 100644
--- a/absl/container/fixed_array_test.cc
+++ b/absl/container/fixed_array_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -150,7 +150,7 @@
   }
 
   {
-    // Arrays of > default size should be on the stack
+    // Arrays of > default size should be on the heap
     absl::FixedArray<int, 100> array(101);
     EXPECT_FALSE(IsOnStack(array));
   }
@@ -365,7 +365,8 @@
 TEST(IteratorConstructorTest, NonPod) {
   char const* kInput[] =
       { "red", "orange", "yellow", "green", "blue", "indigo", "violet" };
-  absl::FixedArray<std::string> const fixed(kInput, kInput + ABSL_ARRAYSIZE(kInput));
+  absl::FixedArray<std::string> const fixed(kInput,
+                                            kInput + ABSL_ARRAYSIZE(kInput));
   ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
   for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
     ASSERT_EQ(kInput[i], fixed[i]);
@@ -869,4 +870,21 @@
 }
 #endif  // ADDRESS_SANITIZER
 
+TEST(FixedArrayTest, AbslHashValueWorks) {
+  using V = absl::FixedArray<int>;
+  std::vector<V> cases;
+
+  // Generate a variety of vectors some of these are small enough for the inline
+  // space but are stored out of line.
+  for (int i = 0; i < 10; ++i) {
+    V v(i);
+    for (int j = 0; j < i; ++j) {
+      v[j] = j;
+    }
+    cases.push_back(v);
+  }
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
+}
+
 }  // namespace
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index e5570d1..00cc4dc 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -35,6 +35,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/algorithm/container.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
 #include "absl/container/internal/raw_hash_map.h"  // IWYU pragma: export
@@ -69,7 +70,7 @@
 // By default, `flat_hash_map` uses the `absl::Hash` hashing framework.
 // All fundamental and Abseil types that support the `absl::Hash` framework have
 // a compatible equality operator for comparing insertions into `flat_hash_map`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -109,6 +110,46 @@
   using Base = typename flat_hash_map::raw_hash_map;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A flat_hash_map supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::flat_hash_map<int, std::string> map1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::flat_hash_map<int, std::string> map2 =
+  //       {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::flat_hash_map<int, std::string> map3(map2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::flat_hash_map<int, std::string> map4;
+  //  map4 = map3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::flat_hash_map<int, std::string> map5(std::move(map4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::flat_hash_map<int, std::string> map6;
+  //   map6 = std::move(map5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+  //   absl::flat_hash_map<int, std::string> map7(v.begin(), v.end());
   flat_hash_map() {}
   using Base::Base;
 
@@ -178,8 +219,12 @@
   //   Erases the element at `position` of the `flat_hash_map`, returning
   //   `void`.
   //
-  //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_map` in particular.
+  //   NOTE: returning `void` in this case is different than that of STL
+  //   containers in general and `std::unordered_map` in particular (which
+  //   return an iterator to the element following the erased element). If that
+  //   iterator is needed, simply post increment the iterator:
+  //
+  //     map.erase(it++);
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -486,25 +531,26 @@
 
 template <class K, class V>
 struct FlatHashMapPolicy {
-  using slot_type = container_internal::slot_type<K, V>;
+  using slot_policy = container_internal::map_slot_policy<K, V>;
+  using slot_type = typename slot_policy::slot_type;
   using key_type = K;
   using mapped_type = V;
   using init_type = std::pair</*non const*/ key_type, mapped_type>;
 
   template <class Allocator, class... Args>
   static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
-    slot_type::construct(alloc, slot, std::forward<Args>(args)...);
+    slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
   }
 
   template <class Allocator>
   static void destroy(Allocator* alloc, slot_type* slot) {
-    slot_type::destroy(alloc, slot);
+    slot_policy::destroy(alloc, slot);
   }
 
   template <class Allocator>
   static void transfer(Allocator* alloc, slot_type* new_slot,
                        slot_type* old_slot) {
-    slot_type::transfer(alloc, new_slot, old_slot);
+    slot_policy::transfer(alloc, new_slot, old_slot);
   }
 
   template <class F, class... Args>
@@ -524,5 +570,16 @@
 };
 
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+    absl::flat_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+}  // namespace container_algorithm_internal
+
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_FLAT_HASH_MAP_H_
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 10a781f..ebcb560 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,6 +17,7 @@
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 #include "absl/types/any.h"
 
@@ -30,19 +31,20 @@
 using ::testing::UnorderedElementsAre;
 
 template <class K, class V>
-using Map =
-    flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual, Alloc<>>;
+using Map = flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual,
+                          Alloc<std::pair<const K, V>>>;
 
 static_assert(!std::is_standard_layout<NonStandardLayout>(), "");
 
 using MapTypes =
-    ::testing::Types<Map<int, int>, Map<std::string, int>, Map<Enum, std::string>,
-                     Map<EnumClass, int>, Map<int, NonStandardLayout>,
-                     Map<NonStandardLayout, int>>;
+    ::testing::Types<Map<int, int>, Map<std::string, int>,
+                     Map<Enum, std::string>, Map<EnumClass, int>,
+                     Map<int, NonStandardLayout>, Map<NonStandardLayout, int>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes);
 
 TEST(FlatHashMap, StandardLayout) {
   struct Int {
@@ -94,7 +96,7 @@
   }
 }
 
-// Demonstration of the "Lazy Key" pattern.  This uses heterogenous insert to
+// Demonstration of the "Lazy Key" pattern.  This uses heterogeneous insert to
 // avoid creating expensive key elements when the item is already present in the
 // map.
 struct LazyInt {
@@ -139,6 +141,7 @@
   int conversions = 0;
   int hashes = 0;
   flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes});
+  m.reserve(3);
 
   m[LazyInt(1, &conversions)] = 1;
   EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1)));
@@ -203,7 +206,9 @@
   m.insert(std::move(node));
   EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));
 }
-#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
+
+#if (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && \
+    !defined(__EMSCRIPTEN__)
 TEST(FlatHashMap, Any) {
   absl::flat_hash_map<int, absl::any> m;
   m.emplace(1, 7);
@@ -234,7 +239,8 @@
   ASSERT_NE(it2, m2.end());
   EXPECT_EQ(7, it2->second);
 }
-#endif  // __ANDROID__
+#endif  // (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) &&
+        // !defined(__EMSCRIPTEN__)
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 98aead1..6bf5183 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -32,6 +32,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/algorithm/container.h"
 #include "absl/base/macros.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
@@ -66,7 +67,7 @@
 // By default, `flat_hash_set` uses the `absl::Hash` hashing framework. All
 // fundamental and Abseil types that support the `absl::Hash` framework have a
 // compatible equality operator for comparing insertions into `flat_hash_map`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -84,7 +85,7 @@
 //     {"huey", "dewey", "louie"};
 //
 //  // Insert a new element into the flat hash set
-//  ducks.insert("donald"};
+//  ducks.insert("donald");
 //
 //  // Force a rehash of the flat hash set
 //  ducks.rehash(0);
@@ -102,6 +103,46 @@
   using Base = typename flat_hash_set::raw_hash_set;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A flat_hash_set supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::flat_hash_set<std::string> set1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::flat_hash_set<std::string> set2 =
+  //       {{"huey"}, {"dewey"}, {"louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::flat_hash_set<std::string> set3(set2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::flat_hash_set<std::string> set4;
+  //  set4 = set3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::flat_hash_set<std::string> set5(std::move(set4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::flat_hash_set<std::string> set6;
+  //   set6 = std::move(set5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::string> v = {"a", "b"};
+  //   absl::flat_hash_set<std::string> set7(v.begin(), v.end());
   flat_hash_set() {}
   using Base::Base;
 
@@ -171,8 +212,12 @@
   //   Erases the element at `position` of the `flat_hash_set`, returning
   //   `void`.
   //
-  //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_map` in particular.
+  //   NOTE: returning `void` in this case is different than that of STL
+  //   containers in general and `std::unordered_set` in particular (which
+  //   return an iterator to the element following the erased element). If that
+  //   iterator is needed, simply post increment the iterator:
+  //
+  //     set.erase(it++);
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -238,8 +283,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace;
@@ -253,8 +297,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace_hint;
@@ -435,5 +478,16 @@
   static size_t space_used(const T*) { return 0; }
 };
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>>
+    : std::true_type {};
+
+}  // namespace container_algorithm_internal
+
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_FLAT_HASH_SET_H_
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc
index e52fd53..b55be59 100644
--- a/absl/container/flat_hash_set_test.cc
+++ b/absl/container/flat_hash_set_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -19,6 +19,7 @@
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 #include "absl/memory/memory.h"
 #include "absl/strings/string_view.h"
@@ -40,9 +41,10 @@
 using SetTypes =
     ::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ModifiersTest, SetTypes);
 
 TEST(FlatHashSet, EmplaceString) {
   std::vector<std::string> v = {"a", "b"};
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 12756bb..7798805 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// 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
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -20,17 +20,17 @@
 // vector" which behaves in an equivalent fashion to a `std::vector`, except
 // that storage for small sequences of the vector are provided inline without
 // requiring any heap allocation.
-
-// An `absl::InlinedVector<T,N>` specifies the size N at which to inline as one
-// of its template parameters. Vectors of length <= N are provided inline.
-// Typically N is very small (e.g., 4) so that sequences that are expected to be
-// short do not require allocations.
-
-// An `absl::InlinedVector` does not usually require a specific allocator; if
+//
+// An `absl::InlinedVector<T, N>` specifies the default capacity `N` as one of
+// its template parameters. Instances where `size() <= N` hold contained
+// elements in inline space. Typically `N` is very small so that sequences that
+// are expected to be short do not require allocations.
+//
+// An `absl::InlinedVector` does not usually require a specific allocator. If
 // the inlined vector grows beyond its initial constraints, it will need to
-// allocate (as any normal `std::vector` would) and it will generally use the
-// default allocator in that case; optionally, a custom allocator may be
-// specified using an `absl::InlinedVector<T,N,A>` construction.
+// allocate (as any normal `std::vector` would). This is usually performed with
+// the default allocator (defined as `std::allocator<T>`). Optionally, a custom
+// allocator type may be specified as `A` in `absl::InlinedVector<T, N, A>`.
 
 #ifndef ABSL_CONTAINER_INLINED_VECTOR_H_
 #define ABSL_CONTAINER_INLINED_VECTOR_H_
@@ -50,10 +50,10 @@
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
+#include "absl/container/internal/inlined_vector.h"
 #include "absl/memory/memory.h"
 
 namespace absl {
-
 // -----------------------------------------------------------------------------
 // InlinedVector
 // -----------------------------------------------------------------------------
@@ -61,323 +61,633 @@
 // An `absl::InlinedVector` is designed to be a drop-in replacement for
 // `std::vector` for use cases where the vector's size is sufficiently small
 // that it can be inlined. If the inlined vector does grow beyond its estimated
-// size, it will trigger an initial allocation on the heap, and will behave as a
-// `std:vector`. The API of the `absl::InlinedVector` within this file is
+// capacity, it will trigger an initial allocation on the heap, and will behave
+// as a `std:vector`. The API of the `absl::InlinedVector` within this file is
 // designed to cover the same API footprint as covered by `std::vector`.
-template <typename T, size_t N, typename A = std::allocator<T> >
+template <typename T, size_t N, typename A = std::allocator<T>>
 class InlinedVector {
-  using AllocatorTraits = std::allocator_traits<A>;
+  static_assert(
+      N > 0, "InlinedVector cannot be instantiated with `0` inlined elements.");
+
+  using Storage = inlined_vector_internal::Storage<InlinedVector>;
+  using Tag = typename Storage::Tag;
+  using AllocatorAndTag = typename Storage::AllocatorAndTag;
+  using Allocation = typename Storage::Allocation;
+
+  template <typename Iterator>
+  using IsAtLeastForwardIterator = std::is_convertible<
+      typename std::iterator_traits<Iterator>::iterator_category,
+      std::forward_iterator_tag>;
+
+  template <typename Iterator>
+  using EnableIfAtLeastForwardIterator =
+      absl::enable_if_t<IsAtLeastForwardIterator<Iterator>::value>;
+
+  template <typename Iterator>
+  using DisableIfAtLeastForwardIterator =
+      absl::enable_if_t<!IsAtLeastForwardIterator<Iterator>::value>;
+
+  using rvalue_reference = typename Storage::rvalue_reference;
 
  public:
-  using allocator_type = A;
-  using value_type = typename allocator_type::value_type;
-  using pointer = typename allocator_type::pointer;
-  using const_pointer = typename allocator_type::const_pointer;
-  using reference = typename allocator_type::reference;
-  using const_reference = typename allocator_type::const_reference;
-  using size_type = typename allocator_type::size_type;
-  using difference_type = typename allocator_type::difference_type;
-  using iterator = pointer;
-  using const_iterator = const_pointer;
-  using reverse_iterator = std::reverse_iterator<iterator>;
-  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+  using allocator_type = typename Storage::allocator_type;
+  using value_type = typename Storage::value_type;
+  using pointer = typename Storage::pointer;
+  using const_pointer = typename Storage::const_pointer;
+  using reference = typename Storage::reference;
+  using const_reference = typename Storage::const_reference;
+  using size_type = typename Storage::size_type;
+  using difference_type = typename Storage::difference_type;
+  using iterator = typename Storage::iterator;
+  using const_iterator = typename Storage::const_iterator;
+  using reverse_iterator = typename Storage::reverse_iterator;
+  using const_reverse_iterator = typename Storage::const_reverse_iterator;
 
+  // ---------------------------------------------------------------------------
+  // InlinedVector Constructors and Destructor
+  // ---------------------------------------------------------------------------
+
+  // Creates an empty inlined vector with a default initialized allocator.
   InlinedVector() noexcept(noexcept(allocator_type()))
-      : allocator_and_tag_(allocator_type()) {}
+      : storage_(allocator_type()) {}
 
+  // Creates an empty inlined vector with a specified allocator.
   explicit InlinedVector(const allocator_type& alloc) noexcept
-      : allocator_and_tag_(alloc) {}
+      : storage_(alloc) {}
 
-  // Create a vector with n copies of value_type().
+  // Creates an inlined vector with `n` copies of `value_type()`.
   explicit InlinedVector(size_type n,
                          const allocator_type& alloc = allocator_type())
-      : allocator_and_tag_(alloc) {
+      : storage_(alloc) {
     InitAssign(n);
   }
 
-  // Create a vector with n copies of elem
-  InlinedVector(size_type n, const value_type& elem,
+  // Creates an inlined vector with `n` copies of `v`.
+  InlinedVector(size_type n, const_reference v,
                 const allocator_type& alloc = allocator_type())
-      : allocator_and_tag_(alloc) {
-    InitAssign(n, elem);
+      : storage_(alloc) {
+    InitAssign(n, v);
   }
 
-  // Create and initialize with the elements [first .. last).
-  // The unused enable_if argument restricts this constructor so that it is
-  // elided when value_type is an integral type.  This prevents ambiguous
-  // interpretation between a call to this constructor with two integral
-  // arguments and a call to the preceding (n, elem) constructor.
-  template <typename InputIterator>
-  InlinedVector(
-      InputIterator first, InputIterator last,
-      const allocator_type& alloc = allocator_type(),
-      typename std::enable_if<!std::is_integral<InputIterator>::value>::type* =
-          nullptr)
-      : allocator_and_tag_(alloc) {
-    AppendRange(first, last);
-  }
-
-  InlinedVector(std::initializer_list<value_type> init,
+  // Creates an inlined vector of copies of the values in `list`.
+  InlinedVector(std::initializer_list<value_type> list,
                 const allocator_type& alloc = allocator_type())
-      : allocator_and_tag_(alloc) {
-    AppendRange(init.begin(), init.end());
+      : storage_(alloc) {
+    AppendForwardRange(list.begin(), list.end());
   }
 
-  InlinedVector(const InlinedVector& v);
-  InlinedVector(const InlinedVector& v, const allocator_type& alloc);
+  // Creates an inlined vector with elements constructed from the provided
+  // forward iterator range [`first`, `last`).
+  //
+  // NOTE: The `enable_if` prevents ambiguous interpretation between a call to
+  // this constructor with two integral arguments and a call to the above
+  // `InlinedVector(size_type, const_reference)` constructor.
+  template <typename ForwardIterator,
+            EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+  InlinedVector(ForwardIterator first, ForwardIterator last,
+                const allocator_type& alloc = allocator_type())
+      : storage_(alloc) {
+    AppendForwardRange(first, last);
+  }
 
-  // This move constructor does not allocate and only moves the underlying
-  // objects, so its `noexcept` specification depends on whether moving the
-  // underlying objects can throw or not. We assume
-  //  a) move constructors should only throw due to allocation failure and
-  //  b) if `value_type`'s move constructor allocates, it uses the same
-  //     allocation function as the `InlinedVector`'s allocator, so the move
+  // Creates an inlined vector with elements constructed from the provided input
+  // iterator range [`first`, `last`).
+  template <typename InputIterator,
+            DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+  InlinedVector(InputIterator first, InputIterator last,
+                const allocator_type& alloc = allocator_type())
+      : storage_(alloc) {
+    std::copy(first, last, std::back_inserter(*this));
+  }
+
+  // Creates a copy of an `other` inlined vector using `other`'s allocator.
+  InlinedVector(const InlinedVector& other)
+      : InlinedVector(other, other.allocator()) {}
+
+  // Creates a copy of an `other` inlined vector using a specified allocator.
+  InlinedVector(const InlinedVector& other, const allocator_type& alloc)
+      : storage_(alloc) {
+    reserve(other.size());
+    if (allocated()) {
+      UninitializedCopy(other.begin(), other.end(), allocated_space());
+      tag().set_allocated_size(other.size());
+    } else {
+      UninitializedCopy(other.begin(), other.end(), inlined_space());
+      tag().set_inline_size(other.size());
+    }
+  }
+
+  // Creates an inlined vector by moving in the contents of an `other` inlined
+  // vector without performing any allocations. If `other` contains allocated
+  // memory, the newly-created instance will take ownership of that memory
+  // (leaving `other` itself empty). However, if `other` does not contain any
+  // allocated memory, the new inlined vector will  will perform element-wise
+  // move construction of `other`s elements.
+  //
+  // NOTE: since no allocation is performed for the inlined vector in either
+  // case, the `noexcept(...)` specification depends on whether moving the
+  // underlying objects can throw. We assume:
+  //  a) Move constructors should only throw due to allocation failure.
+  //  b) If `value_type`'s move constructor allocates, it uses the same
+  //     allocation function as the `InlinedVector`'s allocator. Thus, the move
   //     constructor is non-throwing if the allocator is non-throwing or
   //     `value_type`'s move constructor is specified as `noexcept`.
-  InlinedVector(InlinedVector&& v) noexcept(
+  InlinedVector(InlinedVector&& other) noexcept(
       absl::allocator_is_nothrow<allocator_type>::value ||
-      std::is_nothrow_move_constructible<value_type>::value);
+      std::is_nothrow_move_constructible<value_type>::value)
+      : storage_(other.allocator()) {
+    if (other.allocated()) {
+      // We can just steal the underlying buffer from the source.
+      // That leaves the source empty, so we clear its size.
+      init_allocation(other.allocation());
+      tag().set_allocated_size(other.size());
+      other.tag() = Tag();
+    } else {
+      UninitializedCopy(
+          std::make_move_iterator(other.inlined_space()),
+          std::make_move_iterator(other.inlined_space() + other.size()),
+          inlined_space());
+      tag().set_inline_size(other.size());
+    }
+  }
 
-  // This move constructor allocates and also moves the underlying objects, so
-  // its `noexcept` specification depends on whether the allocation can throw
-  // and whether moving the underlying objects can throw. Based on the same
-  // assumptions above, the `noexcept` specification is dominated by whether the
-  // allocation can throw regardless of whether `value_type`'s move constructor
-  // is specified as `noexcept`.
-  InlinedVector(InlinedVector&& v, const allocator_type& alloc) noexcept(
-      absl::allocator_is_nothrow<allocator_type>::value);
+  // Creates an inlined vector by moving in the contents of an `other` inlined
+  // vector, performing allocations with the specified `alloc` allocator. If
+  // `other`'s allocator is not equal to `alloc` and `other` contains allocated
+  // memory, this move constructor will create a new allocation.
+  //
+  // NOTE: since allocation is performed in this case, this constructor can
+  // only be `noexcept` if the specified allocator is also `noexcept`. If this
+  // is the case, or if `other` contains allocated memory, this constructor
+  // performs element-wise move construction of its contents.
+  //
+  // Only in the case where `other`'s allocator is equal to `alloc` and `other`
+  // contains allocated memory will the newly created inlined vector take
+  // ownership of `other`'s allocated memory.
+  InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
+      absl::allocator_is_nothrow<allocator_type>::value)
+      : storage_(alloc) {
+    if (other.allocated()) {
+      if (alloc == other.allocator()) {
+        // We can just steal the allocation from the source.
+        tag() = other.tag();
+        init_allocation(other.allocation());
+        other.tag() = Tag();
+      } else {
+        // We need to use our own allocator
+        reserve(other.size());
+        UninitializedCopy(std::make_move_iterator(other.begin()),
+                          std::make_move_iterator(other.end()),
+                          allocated_space());
+        tag().set_allocated_size(other.size());
+      }
+    } else {
+      UninitializedCopy(
+          std::make_move_iterator(other.inlined_space()),
+          std::make_move_iterator(other.inlined_space() + other.size()),
+          inlined_space());
+      tag().set_inline_size(other.size());
+    }
+  }
 
   ~InlinedVector() { clear(); }
 
-  InlinedVector& operator=(const InlinedVector& v) {
-    if (this == &v) {
-      return *this;
+  // ---------------------------------------------------------------------------
+  // InlinedVector Member Accessors
+  // ---------------------------------------------------------------------------
+
+  // `InlinedVector::empty()`
+  //
+  // Checks if the inlined vector has no elements.
+  bool empty() const noexcept { return !size(); }
+
+  // `InlinedVector::size()`
+  //
+  // Returns the number of elements in the inlined vector.
+  size_type size() const noexcept { return tag().size(); }
+
+  // `InlinedVector::max_size()`
+  //
+  // Returns the maximum number of elements the vector can hold.
+  size_type max_size() const noexcept {
+    // One bit of the size storage is used to indicate whether the inlined
+    // vector is allocated. As a result, the maximum size of the container that
+    // we can express is half of the max for `size_type`.
+    return (std::numeric_limits<size_type>::max)() / 2;
+  }
+
+  // `InlinedVector::capacity()`
+  //
+  // Returns the number of elements that can be stored in the inlined vector
+  // without requiring a reallocation of underlying memory.
+  //
+  // NOTE: For most inlined vectors, `capacity()` should equal the template
+  // parameter `N`. For inlined vectors which exceed this capacity, they
+  // will no longer be inlined and `capacity()` will equal its capacity on the
+  // allocated heap.
+  size_type capacity() const noexcept {
+    return allocated() ? allocation().capacity() : static_cast<size_type>(N);
+  }
+
+  // `InlinedVector::data()`
+  //
+  // Returns a `pointer` to elements of the inlined vector. This pointer can be
+  // used to access and modify the contained elements.
+  // Only results within the range [`0`, `size()`) are defined.
+  pointer data() noexcept {
+    return allocated() ? allocated_space() : inlined_space();
+  }
+
+  // Overload of `InlinedVector::data()` to return a `const_pointer` to elements
+  // of the inlined vector. This pointer can be used to access (but not modify)
+  // the contained elements.
+  const_pointer data() const noexcept {
+    return allocated() ? allocated_space() : inlined_space();
+  }
+
+  // `InlinedVector::operator[]()`
+  //
+  // Returns a `reference` to the `i`th element of the inlined vector using the
+  // array operator.
+  reference operator[](size_type i) {
+    assert(i < size());
+    return data()[i];
+  }
+
+  // Overload of `InlinedVector::operator[]()` to return a `const_reference` to
+  // the `i`th element of the inlined vector.
+  const_reference operator[](size_type i) const {
+    assert(i < size());
+    return data()[i];
+  }
+
+  // `InlinedVector::at()`
+  //
+  // Returns a `reference` to the `i`th element of the inlined vector.
+  reference at(size_type i) {
+    if (ABSL_PREDICT_FALSE(i >= size())) {
+      base_internal::ThrowStdOutOfRange(
+          "`InlinedVector::at(size_type)` failed bounds check");
     }
+    return data()[i];
+  }
+
+  // Overload of `InlinedVector::at()` to return a `const_reference` to the
+  // `i`th element of the inlined vector.
+  const_reference at(size_type i) const {
+    if (ABSL_PREDICT_FALSE(i >= size())) {
+      base_internal::ThrowStdOutOfRange(
+          "`InlinedVector::at(size_type) const` failed bounds check");
+    }
+    return data()[i];
+  }
+
+  // `InlinedVector::front()`
+  //
+  // Returns a `reference` to the first element of the inlined vector.
+  reference front() {
+    assert(!empty());
+    return at(0);
+  }
+
+  // Overload of `InlinedVector::front()` returns a `const_reference` to the
+  // first element of the inlined vector.
+  const_reference front() const {
+    assert(!empty());
+    return at(0);
+  }
+
+  // `InlinedVector::back()`
+  //
+  // Returns a `reference` to the last element of the inlined vector.
+  reference back() {
+    assert(!empty());
+    return at(size() - 1);
+  }
+
+  // Overload of `InlinedVector::back()` to return a `const_reference` to the
+  // last element of the inlined vector.
+  const_reference back() const {
+    assert(!empty());
+    return at(size() - 1);
+  }
+
+  // `InlinedVector::begin()`
+  //
+  // Returns an `iterator` to the beginning of the inlined vector.
+  iterator begin() noexcept { return data(); }
+
+  // Overload of `InlinedVector::begin()` to return a `const_iterator` to
+  // the beginning of the inlined vector.
+  const_iterator begin() const noexcept { return data(); }
+
+  // `InlinedVector::end()`
+  //
+  // Returns an `iterator` to the end of the inlined vector.
+  iterator end() noexcept { return data() + size(); }
+
+  // Overload of `InlinedVector::end()` to return a `const_iterator` to the
+  // end of the inlined vector.
+  const_iterator end() const noexcept { return data() + size(); }
+
+  // `InlinedVector::cbegin()`
+  //
+  // Returns a `const_iterator` to the beginning of the inlined vector.
+  const_iterator cbegin() const noexcept { return begin(); }
+
+  // `InlinedVector::cend()`
+  //
+  // Returns a `const_iterator` to the end of the inlined vector.
+  const_iterator cend() const noexcept { return end(); }
+
+  // `InlinedVector::rbegin()`
+  //
+  // Returns a `reverse_iterator` from the end of the inlined vector.
+  reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
+
+  // Overload of `InlinedVector::rbegin()` to return a
+  // `const_reverse_iterator` from the end of the inlined vector.
+  const_reverse_iterator rbegin() const noexcept {
+    return const_reverse_iterator(end());
+  }
+
+  // `InlinedVector::rend()`
+  //
+  // Returns a `reverse_iterator` from the beginning of the inlined vector.
+  reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
+
+  // Overload of `InlinedVector::rend()` to return a `const_reverse_iterator`
+  // from the beginning of the inlined vector.
+  const_reverse_iterator rend() const noexcept {
+    return const_reverse_iterator(begin());
+  }
+
+  // `InlinedVector::crbegin()`
+  //
+  // Returns a `const_reverse_iterator` from the end of the inlined vector.
+  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+
+  // `InlinedVector::crend()`
+  //
+  // Returns a `const_reverse_iterator` from the beginning of the inlined
+  // vector.
+  const_reverse_iterator crend() const noexcept { return rend(); }
+
+  // `InlinedVector::get_allocator()`
+  //
+  // Returns a copy of the allocator of the inlined vector.
+  allocator_type get_allocator() const { return allocator(); }
+
+  // ---------------------------------------------------------------------------
+  // InlinedVector Member Mutators
+  // ---------------------------------------------------------------------------
+
+  // `InlinedVector::operator=()`
+  //
+  // Replaces the contents of the inlined vector with copies of the elements in
+  // the provided `std::initializer_list`.
+  InlinedVector& operator=(std::initializer_list<value_type> list) {
+    AssignForwardRange(list.begin(), list.end());
+    return *this;
+  }
+
+  // Overload of `InlinedVector::operator=()` to replace the contents of the
+  // inlined vector with the contents of `other`.
+  InlinedVector& operator=(const InlinedVector& other) {
+    if (ABSL_PREDICT_FALSE(this == &other)) return *this;
+
     // Optimized to avoid reallocation.
     // Prefer reassignment to copy construction for elements.
-    if (size() < v.size()) {  // grow
-      reserve(v.size());
-      std::copy(v.begin(), v.begin() + size(), begin());
-      std::copy(v.begin() + size(), v.end(), std::back_inserter(*this));
+    if (size() < other.size()) {  // grow
+      reserve(other.size());
+      std::copy(other.begin(), other.begin() + size(), begin());
+      std::copy(other.begin() + size(), other.end(), std::back_inserter(*this));
     } else {  // maybe shrink
-      erase(begin() + v.size(), end());
-      std::copy(v.begin(), v.end(), begin());
+      erase(begin() + other.size(), end());
+      std::copy(other.begin(), other.end(), begin());
     }
     return *this;
   }
 
-  InlinedVector& operator=(InlinedVector&& v) {
-    if (this == &v) {
-      return *this;
-    }
-    if (v.allocated()) {
+  // Overload of `InlinedVector::operator=()` to replace the contents of the
+  // inlined vector with the contents of `other`.
+  //
+  // NOTE: As a result of calling this overload, `other` may be empty or it's
+  // contents may be left in a moved-from state.
+  InlinedVector& operator=(InlinedVector&& other) {
+    if (ABSL_PREDICT_FALSE(this == &other)) return *this;
+
+    if (other.allocated()) {
       clear();
-      tag().set_allocated_size(v.size());
-      init_allocation(v.allocation());
-      v.tag() = Tag();
+      tag().set_allocated_size(other.size());
+      init_allocation(other.allocation());
+      other.tag() = Tag();
     } else {
       if (allocated()) clear();
       // Both are inlined now.
-      if (size() < v.size()) {
-        auto mid = std::make_move_iterator(v.begin() + size());
-        std::copy(std::make_move_iterator(v.begin()), mid, begin());
-        UninitializedCopy(mid, std::make_move_iterator(v.end()), end());
+      if (size() < other.size()) {
+        auto mid = std::make_move_iterator(other.begin() + size());
+        std::copy(std::make_move_iterator(other.begin()), mid, begin());
+        UninitializedCopy(mid, std::make_move_iterator(other.end()), end());
       } else {
-        auto new_end = std::copy(std::make_move_iterator(v.begin()),
-                                 std::make_move_iterator(v.end()), begin());
+        auto new_end = std::copy(std::make_move_iterator(other.begin()),
+                                 std::make_move_iterator(other.end()), begin());
         Destroy(new_end, end());
       }
-      tag().set_inline_size(v.size());
+      tag().set_inline_size(other.size());
     }
     return *this;
   }
 
-  InlinedVector& operator=(std::initializer_list<value_type> init) {
-    AssignRange(init.begin(), init.end());
-    return *this;
-  }
-
-  // InlinedVector::assign()
+  // `InlinedVector::assign()`
   //
-  // Replaces the contents of the inlined vector with copies of those in the
-  // iterator range [first, last).
-  template <typename InputIterator>
-  void assign(
-      InputIterator first, InputIterator last,
-      typename std::enable_if<!std::is_integral<InputIterator>::value>::type* =
-          nullptr) {
-    AssignRange(first, last);
-  }
-
-  // Overload of `InlinedVector::assign()` to take values from elements of an
-  // initializer list
-  void assign(std::initializer_list<value_type> init) {
-    AssignRange(init.begin(), init.end());
-  }
-
-  // Overload of `InlinedVector::assign()` to replace the first `n` elements of
-  // the inlined vector with `elem` values.
-  void assign(size_type n, const value_type& elem) {
+  // Replaces the contents of the inlined vector with `n` copies of `v`.
+  void assign(size_type n, const_reference v) {
     if (n <= size()) {  // Possibly shrink
-      std::fill_n(begin(), n, elem);
+      std::fill_n(begin(), n, v);
       erase(begin() + n, end());
       return;
     }
     // Grow
     reserve(n);
-    std::fill_n(begin(), size(), elem);
+    std::fill_n(begin(), size(), v);
     if (allocated()) {
-      UninitializedFill(allocated_space() + size(), allocated_space() + n,
-                        elem);
+      UninitializedFill(allocated_space() + size(), allocated_space() + n, v);
       tag().set_allocated_size(n);
     } else {
-      UninitializedFill(inlined_space() + size(), inlined_space() + n, elem);
+      UninitializedFill(inlined_space() + size(), inlined_space() + n, v);
       tag().set_inline_size(n);
     }
   }
 
-  // InlinedVector::size()
-  //
-  // Returns the number of elements in the inlined vector.
-  size_type size() const noexcept { return tag().size(); }
-
-  // InlinedVector::empty()
-  //
-  // Checks if the inlined vector has no elements.
-  bool empty() const noexcept { return (size() == 0); }
-
-  // InlinedVector::capacity()
-  //
-  // Returns the number of elements that can be stored in an inlined vector
-  // without requiring a reallocation of underlying memory. Note that for
-  // most inlined vectors, `capacity()` should equal its initial size `N`; for
-  // inlined vectors which exceed this capacity, they will no longer be inlined,
-  // and `capacity()` will equal its capacity on the allocated heap.
-  size_type capacity() const noexcept {
-    return allocated() ? allocation().capacity() : N;
+  // Overload of `InlinedVector::assign()` to replace the contents of the
+  // inlined vector with copies of the values in the provided
+  // `std::initializer_list`.
+  void assign(std::initializer_list<value_type> list) {
+    AssignForwardRange(list.begin(), list.end());
   }
 
-  // InlinedVector::max_size()
-  //
-  // Returns the maximum number of elements the vector can hold.
-  size_type max_size() const noexcept {
-    // One bit of the size storage is used to indicate whether the inlined
-    // vector is allocated; as a result, the maximum size of the container that
-    // we can express is half of the max for our size type.
-    return std::numeric_limits<size_type>::max() / 2;
+  // Overload of `InlinedVector::assign()` to replace the contents of the
+  // inlined vector with the forward iterator range [`first`, `last`).
+  template <typename ForwardIterator,
+            EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+  void assign(ForwardIterator first, ForwardIterator last) {
+    AssignForwardRange(first, last);
   }
 
-  // InlinedVector::data()
-  //
-  // Returns a const T* pointer to elements of the inlined vector. This pointer
-  // can be used to access (but not modify) the contained elements.
-  // Only results within the range `[0,size())` are defined.
-  const_pointer data() const noexcept {
-    return allocated() ? allocated_space() : inlined_space();
+  // Overload of `InlinedVector::assign()` to replace the contents of the
+  // inlined vector with the input iterator range [`first`, `last`).
+  template <typename InputIterator,
+            DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+  void assign(InputIterator first, InputIterator last) {
+    size_type assign_index = 0;
+    for (; (assign_index < size()) && (first != last);
+         static_cast<void>(++assign_index), static_cast<void>(++first)) {
+      *(data() + assign_index) = *first;
+    }
+    erase(data() + assign_index, data() + size());
+    std::copy(first, last, std::back_inserter(*this));
   }
 
-  // Overload of InlinedVector::data() to return a T* pointer to elements of the
-  // inlined vector. This pointer can be used to access and modify the contained
-  // elements.
-  pointer data() noexcept {
-    return allocated() ? allocated_space() : inlined_space();
-  }
-
-  // InlinedVector::clear()
+  // `InlinedVector::resize()`
   //
-  // Removes all elements from the inlined vector.
-  void clear() noexcept {
+  // Resizes the inlined vector to contain `n` elements. If `n` is smaller than
+  // the inlined vector's current size, extra elements are destroyed. If `n` is
+  // larger than the initial size, new elements are value-initialized.
+  void resize(size_type n) {
     size_type s = size();
+    if (n < s) {
+      erase(begin() + n, end());
+      return;
+    }
+    reserve(n);
+    assert(capacity() >= n);
+
+    // Fill new space with elements constructed in-place.
     if (allocated()) {
-      Destroy(allocated_space(), allocated_space() + s);
-      allocation().Dealloc(allocator());
-    } else if (s != 0) {  // do nothing for empty vectors
-      Destroy(inlined_space(), inlined_space() + s);
+      UninitializedFill(allocated_space() + s, allocated_space() + n);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space() + s, inlined_space() + n);
+      tag().set_inline_size(n);
     }
-    tag() = Tag();
   }
 
-  // InlinedVector::at()
-  //
-  // Returns the ith element of an inlined vector.
-  const value_type& at(size_type i) const {
-    if (ABSL_PREDICT_FALSE(i >= size())) {
-      base_internal::ThrowStdOutOfRange(
-          "InlinedVector::at failed bounds check");
-    }
-    return data()[i];
-  }
-
-  // InlinedVector::operator[]
-  //
-  // Returns the ith element of an inlined vector using the array operator.
-  const value_type& operator[](size_type i) const {
-    assert(i < size());
-    return data()[i];
-  }
-
-  // Overload of InlinedVector::at() to return the ith element of an inlined
-  // vector.
-  value_type& at(size_type i) {
-    if (i >= size()) {
-      base_internal::ThrowStdOutOfRange(
-          "InlinedVector::at failed bounds check");
-    }
-    return data()[i];
-  }
-
-  // Overload of InlinedVector::operator[] to return the ith element of an
-  // inlined vector.
-  value_type& operator[](size_type i) {
-    assert(i < size());
-    return data()[i];
-  }
-
-  // InlinedVector::back()
-  //
-  // Returns a reference to the last element of an inlined vector.
-  value_type& back() {
-    assert(!empty());
-    return at(size() - 1);
-  }
-
-  // Overload of InlinedVector::back() returns a reference to the last element
-  // of an inlined vector of const values.
-  const value_type& back() const {
-    assert(!empty());
-    return at(size() - 1);
-  }
-
-  // InlinedVector::front()
-  //
-  // Returns a reference to the first element of an inlined vector.
-  value_type& front() {
-    assert(!empty());
-    return at(0);
-  }
-
-  // Overload of InlinedVector::front() returns a reference to the first element
-  // of an inlined vector of const values.
-  const value_type& front() const {
-    assert(!empty());
-    return at(0);
-  }
-
-  // InlinedVector::emplace_back()
-  //
-  // Constructs and appends an object to the inlined vector.
-  //
-  // Returns a reference to the inserted element.
-  template <typename... Args>
-  value_type& emplace_back(Args&&... args) {
+  // Overload of `InlinedVector::resize()` to resize the inlined vector to
+  // contain `n` elements where, if `n` is larger than `size()`, the new values
+  // will be copy-constructed from `v`.
+  void resize(size_type n, const_reference v) {
     size_type s = size();
-    assert(s <= capacity());
+    if (n < s) {
+      erase(begin() + n, end());
+      return;
+    }
+    reserve(n);
+    assert(capacity() >= n);
+
+    // Fill new space with copies of `v`.
+    if (allocated()) {
+      UninitializedFill(allocated_space() + s, allocated_space() + n, v);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space() + s, inlined_space() + n, v);
+      tag().set_inline_size(n);
+    }
+  }
+
+  // `InlinedVector::insert()`
+  //
+  // Copies `v` into `pos`, returning an `iterator` pointing to the newly
+  // inserted element.
+  iterator insert(const_iterator pos, const_reference v) {
+    return emplace(pos, v);
+  }
+
+  // Overload of `InlinedVector::insert()` for moving `v` into `pos`, returning
+  // an iterator pointing to the newly inserted element.
+  iterator insert(const_iterator pos, rvalue_reference v) {
+    return emplace(pos, std::move(v));
+  }
+
+  // Overload of `InlinedVector::insert()` for inserting `n` contiguous copies
+  // of `v` starting at `pos`. Returns an `iterator` pointing to the first of
+  // the newly inserted elements.
+  iterator insert(const_iterator pos, size_type n, const_reference v) {
+    return InsertWithCount(pos, n, v);
+  }
+
+  // Overload of `InlinedVector::insert()` for copying the contents of the
+  // `std::initializer_list` into the vector starting at `pos`. Returns an
+  // `iterator` pointing to the first of the newly inserted elements.
+  iterator insert(const_iterator pos, std::initializer_list<value_type> list) {
+    return insert(pos, list.begin(), list.end());
+  }
+
+  // Overload of `InlinedVector::insert()` for inserting elements constructed
+  // from the forward iterator range [`first`, `last`). Returns an `iterator`
+  // pointing to the first of the newly inserted elements.
+  //
+  // NOTE: The `enable_if` is intended to disambiguate the two three-argument
+  // overloads of `insert()`.
+  template <typename ForwardIterator,
+            EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+  iterator insert(const_iterator pos, ForwardIterator first,
+                  ForwardIterator last) {
+    return InsertWithForwardRange(pos, first, last);
+  }
+
+  // Overload of `InlinedVector::insert()` for inserting elements constructed
+  // from the input iterator range [`first`, `last`). Returns an `iterator`
+  // pointing to the first of the newly inserted elements.
+  template <typename InputIterator,
+            DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+  iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
+    size_type initial_insert_index = std::distance(cbegin(), pos);
+    for (size_type insert_index = initial_insert_index; first != last;
+         static_cast<void>(++insert_index), static_cast<void>(++first)) {
+      insert(data() + insert_index, *first);
+    }
+    return iterator(data() + initial_insert_index);
+  }
+
+  // `InlinedVector::emplace()`
+  //
+  // Constructs and inserts an object in the inlined vector at the given `pos`,
+  // returning an `iterator` pointing to the newly emplaced element.
+  template <typename... Args>
+  iterator emplace(const_iterator pos, Args&&... args) {
+    assert(pos >= begin());
+    assert(pos <= end());
+    if (ABSL_PREDICT_FALSE(pos == end())) {
+      emplace_back(std::forward<Args>(args)...);
+      return end() - 1;
+    }
+
+    T new_t = T(std::forward<Args>(args)...);
+
+    auto range = ShiftRight(pos, 1);
+    if (range.first == range.second) {
+      // constructing into uninitialized memory
+      Construct(range.first, std::move(new_t));
+    } else {
+      // assigning into moved-from object
+      *range.first = T(std::move(new_t));
+    }
+
+    return range.first;
+  }
+
+  // `InlinedVector::emplace_back()`
+  //
+  // Constructs and appends a new element to the end of the inlined vector,
+  // returning a `reference` to the emplaced element.
+  template <typename... Args>
+  reference emplace_back(Args&&... args) {
+    size_type s = size();
     if (ABSL_PREDICT_FALSE(s == capacity())) {
       return GrowAndEmplaceBack(std::forward<Args>(args)...);
     }
-    assert(s < capacity());
-
-    value_type* space;
+    pointer space;
     if (allocated()) {
       tag().set_allocated_size(s + 1);
       space = allocated_space();
@@ -388,19 +698,22 @@
     return Construct(space + s, std::forward<Args>(args)...);
   }
 
-  // InlinedVector::push_back()
+  // `InlinedVector::push_back()`
   //
-  // Appends a const element to the inlined vector.
-  void push_back(const value_type& t) { emplace_back(t); }
+  // Appends a copy of `v` to the end of the inlined vector.
+  void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }
 
-  // Overload of InlinedVector::push_back() to append a move-only element to the
-  // inlined vector.
-  void push_back(value_type&& t) { emplace_back(std::move(t)); }
+  // Overload of `InlinedVector::push_back()` for moving `v` into a newly
+  // appended element.
+  void push_back(rvalue_reference v) {
+    static_cast<void>(emplace_back(std::move(v)));
+  }
 
-  // InlinedVector::pop_back()
+  // `InlinedVector::pop_back()`
   //
-  // Removes the last element (which is destroyed) in the inlined vector.
-  void pop_back() {
+  // Destroys the element at the end of the inlined vector and shrinks the size
+  // by `1` (unless the inlined vector is empty, in which case this is a no-op).
+  void pop_back() noexcept {
     assert(!empty());
     size_type s = size();
     if (allocated()) {
@@ -412,161 +725,75 @@
     }
   }
 
-  // InlinedVector::resize()
+  // `InlinedVector::erase()`
   //
-  // Resizes the inlined vector to contain `n` elements. If `n` is smaller than
-  // the inlined vector's current size, extra elements are destroyed. If `n` is
-  // larger than the initial size, new elements are value-initialized.
-  void resize(size_type n);
-
-  // Overload of InlinedVector::resize() to resize the inlined vector to contain
-  // `n` elements. If `n` is larger than the current size, enough copies of
-  // `elem` are appended to increase its size to `n`.
-  void resize(size_type n, const value_type& elem);
-
-  // InlinedVector::begin()
+  // Erases the element at `pos` of the inlined vector, returning an `iterator`
+  // pointing to the first element following the erased element.
   //
-  // Returns an iterator to the beginning of the inlined vector.
-  iterator begin() noexcept { return data(); }
+  // NOTE: May return the end iterator, which is not dereferencable.
+  iterator erase(const_iterator pos) {
+    assert(pos >= begin());
+    assert(pos < end());
 
-  // Overload of InlinedVector::begin() for returning a const iterator to the
-  // beginning of the inlined vector.
-  const_iterator begin() const noexcept { return data(); }
-
-  // InlinedVector::cbegin()
-  //
-  // Returns a const iterator to the beginning of the inlined vector.
-  const_iterator cbegin() const noexcept { return begin(); }
-
-  // InlinedVector::end()
-  //
-  // Returns an iterator to the end of the inlined vector.
-  iterator end() noexcept { return data() + size(); }
-
-  // Overload of InlinedVector::end() for returning a const iterator to the end
-  // of the inlined vector.
-  const_iterator end() const noexcept { return data() + size(); }
-
-  // InlinedVector::cend()
-  //
-  // Returns a const iterator to the end of the inlined vector.
-  const_iterator cend() const noexcept { return end(); }
-
-  // InlinedVector::rbegin()
-  //
-  // Returns a reverse iterator from the end of the inlined vector.
-  reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
-
-  // Overload of InlinedVector::rbegin() for returning a const reverse iterator
-  // from the end of the inlined vector.
-  const_reverse_iterator rbegin() const noexcept {
-    return const_reverse_iterator(end());
-  }
-
-  // InlinedVector::crbegin()
-  //
-  // Returns a const reverse iterator from the end of the inlined vector.
-  const_reverse_iterator crbegin() const noexcept { return rbegin(); }
-
-  // InlinedVector::rend()
-  //
-  // Returns a reverse iterator from the beginning of the inlined vector.
-  reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
-
-  // Overload of InlinedVector::rend() for returning a const reverse iterator
-  // from the beginning of the inlined vector.
-  const_reverse_iterator rend() const noexcept {
-    return const_reverse_iterator(begin());
-  }
-
-  // InlinedVector::crend()
-  //
-  // Returns a reverse iterator from the beginning of the inlined vector.
-  const_reverse_iterator crend() const noexcept { return rend(); }
-
-  // InlinedVector::emplace()
-  //
-  // Constructs and inserts an object to the inlined vector at the given
-  // `position`, returning an iterator pointing to the newly emplaced element.
-  template <typename... Args>
-  iterator emplace(const_iterator position, Args&&... args);
-
-  // InlinedVector::insert()
-  //
-  // Inserts an element of the specified value at `position`, returning an
-  // iterator pointing to the newly inserted element.
-  iterator insert(const_iterator position, const value_type& v) {
-    return emplace(position, v);
-  }
-
-  // Overload of InlinedVector::insert() for inserting an element of the
-  // specified rvalue, returning an iterator pointing to the newly inserted
-  // element.
-  iterator insert(const_iterator position, value_type&& v) {
-    return emplace(position, std::move(v));
-  }
-
-  // Overload of InlinedVector::insert() for inserting `n` elements of the
-  // specified value at `position`, returning an iterator pointing to the first
-  // of the newly inserted elements.
-  iterator insert(const_iterator position, size_type n, const value_type& v) {
-    return InsertWithCount(position, n, v);
-  }
-
-  // Overload of `InlinedVector::insert()` to disambiguate the two
-  // three-argument overloads of `insert()`, returning an iterator pointing to
-  // the first of the newly inserted elements.
-  template <typename InputIterator,
-            typename = typename std::enable_if<std::is_convertible<
-                typename std::iterator_traits<InputIterator>::iterator_category,
-                std::input_iterator_tag>::value>::type>
-  iterator insert(const_iterator position, InputIterator first,
-                  InputIterator last) {
-    using IterType =
-        typename std::iterator_traits<InputIterator>::iterator_category;
-    return InsertWithRange(position, first, last, IterType());
-  }
-
-  // Overload of InlinedVector::insert() for inserting a list of elements at
-  // `position`, returning an iterator pointing to the first of the newly
-  // inserted elements.
-  iterator insert(const_iterator position,
-                  std::initializer_list<value_type> init) {
-    return insert(position, init.begin(), init.end());
-  }
-
-  // InlinedVector::erase()
-  //
-  // Erases the element at `position` of the inlined vector, returning an
-  // iterator pointing to the following element or the container's end if the
-  // last element was erased.
-  iterator erase(const_iterator position) {
-    assert(position >= begin());
-    assert(position < end());
-
-    iterator pos = const_cast<iterator>(position);
-    std::move(pos + 1, end(), pos);
+    iterator position = const_cast<iterator>(pos);
+    std::move(position + 1, end(), position);
     pop_back();
-    return pos;
+    return position;
   }
 
-  // Overload of InlinedVector::erase() for erasing all elements in the
-  // iterator range [first, last) in the inlined vector, returning an iterator
-  // pointing to the first element following the range erased, or the
-  // container's end if range included the container's last element.
-  iterator erase(const_iterator first, const_iterator last);
+  // Overload of `InlinedVector::erase()` for erasing all elements in the
+  // range [`from`, `to`) in the inlined vector. Returns an `iterator` pointing
+  // to the first element following the range erased or the end iterator if `to`
+  // was the end iterator.
+  iterator erase(const_iterator from, const_iterator to) {
+    assert(begin() <= from);
+    assert(from <= to);
+    assert(to <= end());
 
-  // InlinedVector::reserve()
+    iterator range_start = const_cast<iterator>(from);
+    iterator range_end = const_cast<iterator>(to);
+
+    size_type s = size();
+    ptrdiff_t erase_gap = std::distance(range_start, range_end);
+    if (erase_gap > 0) {
+      pointer space;
+      if (allocated()) {
+        space = allocated_space();
+        tag().set_allocated_size(s - erase_gap);
+      } else {
+        space = inlined_space();
+        tag().set_inline_size(s - erase_gap);
+      }
+      std::move(range_end, space + s, range_start);
+      Destroy(space + s - erase_gap, space + s);
+    }
+    return range_start;
+  }
+
+  // `InlinedVector::clear()`
+  //
+  // Destroys all elements in the inlined vector, sets the size of `0` and
+  // deallocates the heap allocation if the inlined vector was allocated.
+  void clear() noexcept {
+    size_type s = size();
+    if (allocated()) {
+      Destroy(allocated_space(), allocated_space() + s);
+      allocation().Dealloc(allocator());
+    } else if (s != 0) {  // do nothing for empty vectors
+      Destroy(inlined_space(), inlined_space() + s);
+    }
+    tag() = Tag();
+  }
+
+  // `InlinedVector::reserve()`
   //
   // Enlarges the underlying representation of the inlined vector so it can hold
   // at least `n` elements. This method does not change `size()` or the actual
   // contents of the vector.
   //
-  // Note that if `n` does not exceed the inlined vector's initial size `N`,
-  // `reserve()` will have no effect; if it does exceed its initial size,
-  // `reserve()` will trigger an initial allocation and move the inlined vector
-  // onto the heap. If the vector already exists on the heap and the requested
-  // size exceeds it, a reallocation will be performed.
+  // NOTE: If `n` does not exceed `capacity()`, `reserve()` will have no
+  // effects. Otherwise, `reserve()` will reallocate, performing an n-time
+  // element-wise move of everything contained.
   void reserve(size_type n) {
     if (n > capacity()) {
       // Make room for new elements
@@ -574,26 +801,25 @@
     }
   }
 
-  // InlinedVector::shrink_to_fit()
+  // `InlinedVector::shrink_to_fit()`
   //
-  // Reduces memory usage by freeing unused memory.
-  // After this call `capacity()` will be equal to `max(N, size())`.
+  // Reduces memory usage by freeing unused memory. After this call, calls to
+  // `capacity()` will be equal to `max(N, size())`.
   //
   // If `size() <= N` and the elements are currently stored on the heap, they
-  // will be moved to the inlined storage and the heap memory deallocated.
-  // If `size() > N` and `size() < capacity()` the elements will be moved to
-  // a reallocated storage on heap.
+  // will be moved to the inlined storage and the heap memory will be
+  // deallocated.
+  //
+  // If `size() > N` and `size() < capacity()` the elements will be moved to a
+  // smaller heap allocation.
   void shrink_to_fit() {
     const auto s = size();
-    if (!allocated() || s == capacity()) {
-      // There's nothing to deallocate.
-      return;
-    }
+    if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return;
 
     if (s <= N) {
       // Move the elements to the inlined storage.
-      // We have to do this using a temporary, because inlined_storage and
-      // allocation_storage are in a union field.
+      // We have to do this using a temporary, because `inlined_storage` and
+      // `allocation_storage` are in a union field.
       auto temp = std::move(*this);
       assign(std::make_move_iterator(temp.begin()),
              std::make_move_iterator(temp.end()));
@@ -601,8 +827,8 @@
     }
 
     // Reallocate storage and move elements.
-    // We can't simply use the same approach as above, because assign() would
-    // call into reserve() internally and reserve larger capacity than we need.
+    // We can't simply use the same approach as above, because `assign()` would
+    // call into `reserve()` internally and reserve larger capacity than we need
     Allocation new_allocation(allocator(), s);
     UninitializedCopy(std::make_move_iterator(allocated_space()),
                       std::make_move_iterator(allocated_space() + s),
@@ -610,129 +836,62 @@
     ResetAllocation(new_allocation, s);
   }
 
-  // InlinedVector::swap()
+  // `InlinedVector::swap()`
   //
   // Swaps the contents of this inlined vector with the contents of `other`.
-  void swap(InlinedVector& other);
+  void swap(InlinedVector& other) {
+    if (ABSL_PREDICT_FALSE(this == &other)) return;
 
-  // InlinedVector::get_allocator()
-  //
-  // Returns the allocator of this inlined vector.
-  allocator_type get_allocator() const { return allocator(); }
-
-  template <typename H>
-  friend H AbslHashValue(H h, const InlinedVector& v) {
-    return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
-                      v.size());
+    SwapImpl(other);
   }
 
  private:
-  static_assert(N > 0, "inlined vector with nonpositive size");
+  template <typename H, typename TheT, size_t TheN, typename TheA>
+  friend auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H;
 
-  // It holds whether the vector is allocated or not in the lowest bit.
-  // The size is held in the high bits:
-  //   size_ = (size << 1) | is_allocated;
-  //
-  // Maintainer's Note: size_type is user defined. The contract is limited to
-  // arithmetic operators to avoid depending on compliant overloaded bitwise
-  // operators.
-  class Tag {
-   public:
-    Tag() : size_(0) {}
-    size_type size() const { return size_ / 2; }
-    void add_size(size_type n) { size_ += n * 2; }
-    void set_inline_size(size_type n) { size_ = n * 2; }
-    void set_allocated_size(size_type n) { size_ = (n * 2) + 1; }
-    bool allocated() const { return size_ % 2; }
+  const Tag& tag() const { return storage_.allocator_and_tag_.tag(); }
 
-   private:
-    size_type size_;
-  };
-
-  // Derives from allocator_type to use the empty base class optimization.
-  // If the allocator_type is stateless, we can 'store'
-  // our instance of it for free.
-  class AllocatorAndTag : private allocator_type {
-   public:
-    explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
-    Tag& tag() { return tag_; }
-    const Tag& tag() const { return tag_; }
-    allocator_type& allocator() { return *this; }
-    const allocator_type& allocator() const { return *this; }
-
-   private:
-    Tag tag_;
-  };
-
-  class Allocation {
-   public:
-    Allocation(allocator_type& a,  // NOLINT(runtime/references)
-               size_type capacity)
-        : capacity_(capacity),
-          buffer_(AllocatorTraits::allocate(a, capacity_)) {}
-
-    void Dealloc(allocator_type& a) {  // NOLINT(runtime/references)
-      AllocatorTraits::deallocate(a, buffer(), capacity());
-    }
-
-    size_type capacity() const { return capacity_; }
-    const value_type* buffer() const { return buffer_; }
-    value_type* buffer() { return buffer_; }
-
-   private:
-    size_type capacity_;
-    value_type* buffer_;
-  };
-
-  const Tag& tag() const { return allocator_and_tag_.tag(); }
-  Tag& tag() { return allocator_and_tag_.tag(); }
+  Tag& tag() { return storage_.allocator_and_tag_.tag(); }
 
   Allocation& allocation() {
-    return reinterpret_cast<Allocation&>(rep_.allocation_storage.allocation);
+    return reinterpret_cast<Allocation&>(
+        storage_.rep_.allocation_storage.allocation);
   }
+
   const Allocation& allocation() const {
     return reinterpret_cast<const Allocation&>(
-        rep_.allocation_storage.allocation);
+        storage_.rep_.allocation_storage.allocation);
   }
+
   void init_allocation(const Allocation& allocation) {
-    new (&rep_.allocation_storage.allocation) Allocation(allocation);
+    new (&storage_.rep_.allocation_storage.allocation) Allocation(allocation);
   }
 
   // TODO(absl-team): investigate whether the reinterpret_cast is appropriate.
-  value_type* inlined_space() {
-    return reinterpret_cast<value_type*>(
-        std::addressof(rep_.inlined_storage.inlined[0]));
-  }
-  const value_type* inlined_space() const {
-    return reinterpret_cast<const value_type*>(
-        std::addressof(rep_.inlined_storage.inlined[0]));
+  pointer inlined_space() {
+    return reinterpret_cast<pointer>(
+        std::addressof(storage_.rep_.inlined_storage.inlined[0]));
   }
 
-  value_type* allocated_space() { return allocation().buffer(); }
-  const value_type* allocated_space() const { return allocation().buffer(); }
+  const_pointer inlined_space() const {
+    return reinterpret_cast<const_pointer>(
+        std::addressof(storage_.rep_.inlined_storage.inlined[0]));
+  }
+
+  pointer allocated_space() { return allocation().buffer(); }
+
+  const_pointer allocated_space() const { return allocation().buffer(); }
 
   const allocator_type& allocator() const {
-    return allocator_and_tag_.allocator();
+    return storage_.allocator_and_tag_.allocator();
   }
-  allocator_type& allocator() { return allocator_and_tag_.allocator(); }
+
+  allocator_type& allocator() {
+    return storage_.allocator_and_tag_.allocator();
+  }
 
   bool allocated() const { return tag().allocated(); }
 
-  // Enlarge the underlying representation so we can store size_ + delta elems.
-  // The size is not changed, and any newly added memory is not initialized.
-  void EnlargeBy(size_type delta);
-
-  // Shift all elements from position to end() n places to the right.
-  // If the vector needs to be enlarged, memory will be allocated.
-  // Returns iterators pointing to the start of the previously-initialized
-  // portion and the start of the uninitialized portion of the created gap.
-  // The number of initialized spots is pair.second - pair.first;
-  // the number of raw spots is n - (pair.second - pair.first).
-  //
-  // Updates the size of the InlinedVector internally.
-  std::pair<iterator, iterator> ShiftRight(const_iterator position,
-                                           size_type n);
-
   void ResetAllocation(Allocation new_allocation, size_type new_size) {
     if (allocated()) {
       Destroy(allocated_space(), allocated_space() + size());
@@ -747,13 +906,137 @@
   }
 
   template <typename... Args>
-  value_type& GrowAndEmplaceBack(Args&&... args) {
+  reference Construct(pointer p, Args&&... args) {
+    std::allocator_traits<allocator_type>::construct(
+        allocator(), p, std::forward<Args>(args)...);
+    return *p;
+  }
+
+  template <typename Iterator>
+  void UninitializedCopy(Iterator src, Iterator src_last, pointer dst) {
+    for (; src != src_last; ++dst, ++src) Construct(dst, *src);
+  }
+
+  template <typename... Args>
+  void UninitializedFill(pointer dst, pointer dst_last, const Args&... args) {
+    for (; dst != dst_last; ++dst) Construct(dst, args...);
+  }
+
+  // Destroy [`from`, `to`) in place.
+  void Destroy(pointer from, pointer to) {
+    for (pointer cur = from; cur != to; ++cur) {
+      std::allocator_traits<allocator_type>::destroy(allocator(), cur);
+    }
+#if !defined(NDEBUG)
+    // Overwrite unused memory with `0xab` so we can catch uninitialized usage.
+    // Cast to `void*` to tell the compiler that we don't care that we might be
+    // scribbling on a vtable pointer.
+    if (from != to) {
+      auto len = sizeof(value_type) * std::distance(from, to);
+      std::memset(reinterpret_cast<void*>(from), 0xab, len);
+    }
+#endif  // !defined(NDEBUG)
+  }
+
+  // Enlarge the underlying representation so we can store `size_ + delta` elems
+  // in allocated space. The size is not changed, and any newly added memory is
+  // not initialized.
+  void EnlargeBy(size_type delta) {
+    const size_type s = size();
+    assert(s <= capacity());
+
+    size_type target = (std::max)(N, s + delta);
+
+    // Compute new capacity by repeatedly doubling current capacity
+    // TODO(psrc): Check and avoid overflow?
+    size_type new_capacity = capacity();
+    while (new_capacity < target) {
+      new_capacity <<= 1;
+    }
+
+    Allocation new_allocation(allocator(), new_capacity);
+
+    UninitializedCopy(std::make_move_iterator(data()),
+                      std::make_move_iterator(data() + s),
+                      new_allocation.buffer());
+
+    ResetAllocation(new_allocation, s);
+  }
+
+  // Shift all elements from `position` to `end()` by `n` places to the right.
+  // If the vector needs to be enlarged, memory will be allocated.
+  // Returns `iterator`s pointing to the start of the previously-initialized
+  // portion and the start of the uninitialized portion of the created gap.
+  // The number of initialized spots is `pair.second - pair.first`. The number
+  // of raw spots is `n - (pair.second - pair.first)`.
+  //
+  // Updates the size of the InlinedVector internally.
+  std::pair<iterator, iterator> ShiftRight(const_iterator position,
+                                           size_type n) {
+    iterator start_used = const_cast<iterator>(position);
+    iterator start_raw = const_cast<iterator>(position);
+    size_type s = size();
+    size_type required_size = s + n;
+
+    if (required_size > capacity()) {
+      // Compute new capacity by repeatedly doubling current capacity
+      size_type new_capacity = capacity();
+      while (new_capacity < required_size) {
+        new_capacity <<= 1;
+      }
+      // Move everyone into the new allocation, leaving a gap of `n` for the
+      // requested shift.
+      Allocation new_allocation(allocator(), new_capacity);
+      size_type index = position - begin();
+      UninitializedCopy(std::make_move_iterator(data()),
+                        std::make_move_iterator(data() + index),
+                        new_allocation.buffer());
+      UninitializedCopy(std::make_move_iterator(data() + index),
+                        std::make_move_iterator(data() + s),
+                        new_allocation.buffer() + index + n);
+      ResetAllocation(new_allocation, s);
+
+      // New allocation means our iterator is invalid, so we'll recalculate.
+      // Since the entire gap is in new space, there's no used space to reuse.
+      start_raw = begin() + index;
+      start_used = start_raw;
+    } else {
+      // If we had enough space, it's a two-part move. Elements going into
+      // previously-unoccupied space need an `UninitializedCopy()`. Elements
+      // going into a previously-occupied space are just a `std::move()`.
+      iterator pos = const_cast<iterator>(position);
+      iterator raw_space = end();
+      size_type slots_in_used_space = raw_space - pos;
+      size_type new_elements_in_used_space = (std::min)(n, slots_in_used_space);
+      size_type new_elements_in_raw_space = n - new_elements_in_used_space;
+      size_type old_elements_in_used_space =
+          slots_in_used_space - new_elements_in_used_space;
+
+      UninitializedCopy(
+          std::make_move_iterator(pos + old_elements_in_used_space),
+          std::make_move_iterator(raw_space),
+          raw_space + new_elements_in_raw_space);
+      std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
+
+      // If the gap is entirely in raw space, the used space starts where the
+      // raw space starts, leaving no elements in used space. If the gap is
+      // entirely in used space, the raw space starts at the end of the gap,
+      // leaving all elements accounted for within the used space.
+      start_used = pos;
+      start_raw = pos + new_elements_in_used_space;
+    }
+    tag().add_size(n);
+    return std::make_pair(start_used, start_raw);
+  }
+
+  template <typename... Args>
+  reference GrowAndEmplaceBack(Args&&... args) {
     assert(size() == capacity());
     const size_type s = size();
 
     Allocation new_allocation(allocator(), 2 * capacity());
 
-    value_type& new_element =
+    reference new_element =
         Construct(new_allocation.buffer() + s, std::forward<Args>(args)...);
     UninitializedCopy(std::make_move_iterator(data()),
                       std::make_move_iterator(data() + s),
@@ -764,628 +1047,268 @@
     return new_element;
   }
 
-  void InitAssign(size_type n);
-  void InitAssign(size_type n, const value_type& t);
-
-  template <typename... Args>
-  value_type& Construct(pointer p, Args&&... args) {
-    AllocatorTraits::construct(allocator(), p, std::forward<Args>(args)...);
-    return *p;
+  void InitAssign(size_type n) {
+    if (n > N) {
+      Allocation new_allocation(allocator(), n);
+      init_allocation(new_allocation);
+      UninitializedFill(allocated_space(), allocated_space() + n);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space(), inlined_space() + n);
+      tag().set_inline_size(n);
+    }
   }
 
-  template <typename Iter>
-  void UninitializedCopy(Iter src, Iter src_last, value_type* dst) {
-    for (; src != src_last; ++dst, ++src) Construct(dst, *src);
+  void InitAssign(size_type n, const_reference v) {
+    if (n > N) {
+      Allocation new_allocation(allocator(), n);
+      init_allocation(new_allocation);
+      UninitializedFill(allocated_space(), allocated_space() + n, v);
+      tag().set_allocated_size(n);
+    } else {
+      UninitializedFill(inlined_space(), inlined_space() + n, v);
+      tag().set_inline_size(n);
+    }
   }
 
-  template <typename... Args>
-  void UninitializedFill(value_type* dst, value_type* dst_last,
-                         const Args&... args) {
-    for (; dst != dst_last; ++dst) Construct(dst, args...);
+  template <typename ForwardIt>
+  void AssignForwardRange(ForwardIt first, ForwardIt last) {
+    static_assert(IsAtLeastForwardIterator<ForwardIt>::value, "");
+
+    auto length = std::distance(first, last);
+
+    // Prefer reassignment to copy construction for elements.
+    if (static_cast<size_type>(length) <= size()) {
+      erase(std::copy(first, last, begin()), end());
+      return;
+    }
+
+    reserve(length);
+    iterator out = begin();
+    for (; out != end(); ++first, ++out) *out = *first;
+    if (allocated()) {
+      UninitializedCopy(first, last, out);
+      tag().set_allocated_size(length);
+    } else {
+      UninitializedCopy(first, last, out);
+      tag().set_inline_size(length);
+    }
   }
 
-  // Destroy [ptr, ptr_last) in place.
-  void Destroy(value_type* ptr, value_type* ptr_last);
+  template <typename ForwardIt>
+  void AppendForwardRange(ForwardIt first, ForwardIt last) {
+    static_assert(IsAtLeastForwardIterator<ForwardIt>::value, "");
 
-  template <typename Iter>
-  void AppendRange(Iter first, Iter last, std::input_iterator_tag) {
-    std::copy(first, last, std::back_inserter(*this));
-  }
-
-  // Faster path for forward iterators.
-  template <typename Iter>
-  void AppendRange(Iter first, Iter last, std::forward_iterator_tag);
-
-  template <typename Iter>
-  void AppendRange(Iter first, Iter last) {
-    using IterTag = typename std::iterator_traits<Iter>::iterator_category;
-    AppendRange(first, last, IterTag());
-  }
-
-  template <typename Iter>
-  void AssignRange(Iter first, Iter last, std::input_iterator_tag);
-
-  // Faster path for forward iterators.
-  template <typename Iter>
-  void AssignRange(Iter first, Iter last, std::forward_iterator_tag);
-
-  template <typename Iter>
-  void AssignRange(Iter first, Iter last) {
-    using IterTag = typename std::iterator_traits<Iter>::iterator_category;
-    AssignRange(first, last, IterTag());
+    auto length = std::distance(first, last);
+    reserve(size() + length);
+    if (allocated()) {
+      UninitializedCopy(first, last, allocated_space() + size());
+      tag().set_allocated_size(size() + length);
+    } else {
+      UninitializedCopy(first, last, inlined_space() + size());
+      tag().set_inline_size(size() + length);
+    }
   }
 
   iterator InsertWithCount(const_iterator position, size_type n,
-                           const value_type& v);
+                           const_reference v) {
+    assert(position >= begin() && position <= end());
+    if (ABSL_PREDICT_FALSE(n == 0)) return const_cast<iterator>(position);
 
-  template <typename InputIter>
-  iterator InsertWithRange(const_iterator position, InputIter first,
-                           InputIter last, std::input_iterator_tag);
-  template <typename ForwardIter>
-  iterator InsertWithRange(const_iterator position, ForwardIter first,
-                           ForwardIter last, std::forward_iterator_tag);
+    value_type copy = v;
+    std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
+    std::fill(it_pair.first, it_pair.second, copy);
+    UninitializedFill(it_pair.second, it_pair.first + n, copy);
 
-  AllocatorAndTag allocator_and_tag_;
+    return it_pair.first;
+  }
 
-  // Either the inlined or allocated representation
-  union Rep {
-    // Use struct to perform indirection that solves a bizarre compilation
-    // error on Visual Studio (all known versions).
-    struct {
-      typename std::aligned_storage<sizeof(value_type),
-                                    alignof(value_type)>::type inlined[N];
-    } inlined_storage;
-    struct {
-      typename std::aligned_storage<sizeof(Allocation),
-                                    alignof(Allocation)>::type allocation;
-    } allocation_storage;
-  } rep_;
+  template <typename ForwardIt>
+  iterator InsertWithForwardRange(const_iterator position, ForwardIt first,
+                                  ForwardIt last) {
+    static_assert(IsAtLeastForwardIterator<ForwardIt>::value, "");
+    assert(position >= begin() && position <= end());
+
+    if (ABSL_PREDICT_FALSE(first == last))
+      return const_cast<iterator>(position);
+
+    auto n = std::distance(first, last);
+    std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
+    size_type used_spots = it_pair.second - it_pair.first;
+    auto open_spot = std::next(first, used_spots);
+    std::copy(first, open_spot, it_pair.first);
+    UninitializedCopy(open_spot, last, it_pair.second);
+    return it_pair.first;
+  }
+
+  void SwapImpl(InlinedVector& other) {
+    using std::swap;  // Augment ADL with `std::swap`.
+
+    if (allocated() && other.allocated()) {
+      // Both out of line, so just swap the tag, allocation, and allocator.
+      swap(tag(), other.tag());
+      swap(allocation(), other.allocation());
+      swap(allocator(), other.allocator());
+      return;
+    }
+    if (!allocated() && !other.allocated()) {
+      // Both inlined: swap up to smaller size, then move remaining elements.
+      InlinedVector* a = this;
+      InlinedVector* b = &other;
+      if (size() < other.size()) {
+        swap(a, b);
+      }
+
+      const size_type a_size = a->size();
+      const size_type b_size = b->size();
+      assert(a_size >= b_size);
+      // `a` is larger. Swap the elements up to the smaller array size.
+      std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
+                       b->inlined_space());
+
+      // Move the remaining elements:
+      //   [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
+      b->UninitializedCopy(a->inlined_space() + b_size,
+                           a->inlined_space() + a_size,
+                           b->inlined_space() + b_size);
+      a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
+
+      swap(a->tag(), b->tag());
+      swap(a->allocator(), b->allocator());
+      assert(b->size() == a_size);
+      assert(a->size() == b_size);
+      return;
+    }
+
+    // One is out of line, one is inline.
+    // We first move the elements from the inlined vector into the
+    // inlined space in the other vector.  We then put the other vector's
+    // pointer/capacity into the originally inlined vector and swap
+    // the tags.
+    InlinedVector* a = this;
+    InlinedVector* b = &other;
+    if (a->allocated()) {
+      swap(a, b);
+    }
+    assert(!a->allocated());
+    assert(b->allocated());
+    const size_type a_size = a->size();
+    const size_type b_size = b->size();
+    // In an optimized build, `b_size` would be unused.
+    static_cast<void>(b_size);
+
+    // Made Local copies of `size()`, don't need `tag()` accurate anymore
+    swap(a->tag(), b->tag());
+
+    // Copy `b_allocation` out before `b`'s union gets clobbered by
+    // `inline_space`
+    Allocation b_allocation = b->allocation();
+
+    b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
+                         b->inlined_space());
+    a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
+
+    a->allocation() = b_allocation;
+
+    if (a->allocator() != b->allocator()) {
+      swap(a->allocator(), b->allocator());
+    }
+
+    assert(b->size() == a_size);
+    assert(a->size() == b_size);
+  }
+
+  Storage storage_;
 };
 
 // -----------------------------------------------------------------------------
 // InlinedVector Non-Member Functions
 // -----------------------------------------------------------------------------
 
-// swap()
+// `swap()`
 //
 // Swaps the contents of two inlined vectors. This convenience function
-// simply calls InlinedVector::swap(other_inlined_vector).
+// simply calls `InlinedVector::swap()`.
 template <typename T, size_t N, typename A>
-void swap(InlinedVector<T, N, A>& a,
-          InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
+auto swap(InlinedVector<T, N, A>& a,
+          InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) -> void {
   a.swap(b);
 }
 
-// operator==()
+// `operator==()`
 //
 // Tests the equivalency of the contents of two inlined vectors.
 template <typename T, size_t N, typename A>
-bool operator==(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator==(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return absl::equal(a.begin(), a.end(), b.begin(), b.end());
 }
 
-// operator!=()
+// `operator!=()`
 //
 // Tests the inequality of the contents of two inlined vectors.
 template <typename T, size_t N, typename A>
-bool operator!=(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator!=(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return !(a == b);
 }
 
-// operator<()
+// `operator<()`
 //
 // Tests whether the contents of one inlined vector are less than the contents
 // of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator<(const InlinedVector<T, N, A>& a,
-               const InlinedVector<T, N, A>& b) {
+auto operator<(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b)
+    -> bool {
   return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
 }
 
-// operator>()
+// `operator>()`
 //
 // Tests whether the contents of one inlined vector are greater than the
 // contents of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator>(const InlinedVector<T, N, A>& a,
-               const InlinedVector<T, N, A>& b) {
+auto operator>(const InlinedVector<T, N, A>& a, const InlinedVector<T, N, A>& b)
+    -> bool {
   return b < a;
 }
 
-// operator<=()
+// `operator<=()`
 //
 // Tests whether the contents of one inlined vector are less than or equal to
 // the contents of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator<=(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator<=(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return !(b < a);
 }
 
-// operator>=()
+// `operator>=()`
 //
 // Tests whether the contents of one inlined vector are greater than or equal to
 // the contents of another through a lexicographical comparison operation.
 template <typename T, size_t N, typename A>
-bool operator>=(const InlinedVector<T, N, A>& a,
-                const InlinedVector<T, N, A>& b) {
+auto operator>=(const InlinedVector<T, N, A>& a,
+                const InlinedVector<T, N, A>& b) -> bool {
   return !(a < b);
 }
 
+// AbslHashValue()
+//
+// Provides `absl::Hash` support for inlined vectors. You do not normally call
+// this function directly.
+template <typename H, typename TheT, size_t TheN, typename TheA>
+auto AbslHashValue(H h, const InlinedVector<TheT, TheN, TheA>& v) -> H {
+  auto p = v.data();
+  auto n = v.size();
+  return H::combine(H::combine_contiguous(std::move(h), p, n), n);
+}
+}  // namespace absl
+
 // -----------------------------------------------------------------------------
 // Implementation of InlinedVector
-// -----------------------------------------------------------------------------
 //
-// Do not depend on any implementation details below this line.
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(const InlinedVector& v)
-    : allocator_and_tag_(v.allocator()) {
-  reserve(v.size());
-  if (allocated()) {
-    UninitializedCopy(v.begin(), v.end(), allocated_space());
-    tag().set_allocated_size(v.size());
-  } else {
-    UninitializedCopy(v.begin(), v.end(), inlined_space());
-    tag().set_inline_size(v.size());
-  }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(const InlinedVector& v,
-                                      const allocator_type& alloc)
-    : allocator_and_tag_(alloc) {
-  reserve(v.size());
-  if (allocated()) {
-    UninitializedCopy(v.begin(), v.end(), allocated_space());
-    tag().set_allocated_size(v.size());
-  } else {
-    UninitializedCopy(v.begin(), v.end(), inlined_space());
-    tag().set_inline_size(v.size());
-  }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(InlinedVector&& v) noexcept(
-    absl::allocator_is_nothrow<allocator_type>::value ||
-    std::is_nothrow_move_constructible<value_type>::value)
-    : allocator_and_tag_(v.allocator_and_tag_) {
-  if (v.allocated()) {
-    // We can just steal the underlying buffer from the source.
-    // That leaves the source empty, so we clear its size.
-    init_allocation(v.allocation());
-    v.tag() = Tag();
-  } else {
-    UninitializedCopy(std::make_move_iterator(v.inlined_space()),
-                      std::make_move_iterator(v.inlined_space() + v.size()),
-                      inlined_space());
-  }
-}
-
-template <typename T, size_t N, typename A>
-InlinedVector<T, N, A>::InlinedVector(
-    InlinedVector&& v,
-    const allocator_type&
-        alloc) noexcept(absl::allocator_is_nothrow<allocator_type>::value)
-    : allocator_and_tag_(alloc) {
-  if (v.allocated()) {
-    if (alloc == v.allocator()) {
-      // We can just steal the allocation from the source.
-      tag() = v.tag();
-      init_allocation(v.allocation());
-      v.tag() = Tag();
-    } else {
-      // We need to use our own allocator
-      reserve(v.size());
-      UninitializedCopy(std::make_move_iterator(v.begin()),
-                        std::make_move_iterator(v.end()), allocated_space());
-      tag().set_allocated_size(v.size());
-    }
-  } else {
-    UninitializedCopy(std::make_move_iterator(v.inlined_space()),
-                      std::make_move_iterator(v.inlined_space() + v.size()),
-                      inlined_space());
-    tag().set_inline_size(v.size());
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::InitAssign(size_type n, const value_type& t) {
-  if (n > static_cast<size_type>(N)) {
-    Allocation new_allocation(allocator(), n);
-    init_allocation(new_allocation);
-    UninitializedFill(allocated_space(), allocated_space() + n, t);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space(), inlined_space() + n, t);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::InitAssign(size_type n) {
-  if (n > static_cast<size_type>(N)) {
-    Allocation new_allocation(allocator(), n);
-    init_allocation(new_allocation);
-    UninitializedFill(allocated_space(), allocated_space() + n);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space(), inlined_space() + n);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::resize(size_type n) {
-  size_type s = size();
-  if (n < s) {
-    erase(begin() + n, end());
-    return;
-  }
-  reserve(n);
-  assert(capacity() >= n);
-
-  // Fill new space with elements constructed in-place.
-  if (allocated()) {
-    UninitializedFill(allocated_space() + s, allocated_space() + n);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space() + s, inlined_space() + n);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::resize(size_type n, const value_type& elem) {
-  size_type s = size();
-  if (n < s) {
-    erase(begin() + n, end());
-    return;
-  }
-  reserve(n);
-  assert(capacity() >= n);
-
-  // Fill new space with copies of 'elem'.
-  if (allocated()) {
-    UninitializedFill(allocated_space() + s, allocated_space() + n, elem);
-    tag().set_allocated_size(n);
-  } else {
-    UninitializedFill(inlined_space() + s, inlined_space() + n, elem);
-    tag().set_inline_size(n);
-  }
-}
-
-template <typename T, size_t N, typename A>
-template <typename... Args>
-typename InlinedVector<T, N, A>::iterator InlinedVector<T, N, A>::emplace(
-    const_iterator position, Args&&... args) {
-  assert(position >= begin());
-  assert(position <= end());
-  if (position == end()) {
-    emplace_back(std::forward<Args>(args)...);
-    return end() - 1;
-  }
-
-  T new_t = T(std::forward<Args>(args)...);
-
-  auto range = ShiftRight(position, 1);
-  if (range.first == range.second) {
-    // constructing into uninitialized memory
-    Construct(range.first, std::move(new_t));
-  } else {
-    // assigning into moved-from object
-    *range.first = T(std::move(new_t));
-  }
-
-  return range.first;
-}
-
-template <typename T, size_t N, typename A>
-typename InlinedVector<T, N, A>::iterator InlinedVector<T, N, A>::erase(
-    const_iterator first, const_iterator last) {
-  assert(begin() <= first);
-  assert(first <= last);
-  assert(last <= end());
-
-  iterator range_start = const_cast<iterator>(first);
-  iterator range_end = const_cast<iterator>(last);
-
-  size_type s = size();
-  ptrdiff_t erase_gap = std::distance(range_start, range_end);
-  if (erase_gap > 0) {
-    pointer space;
-    if (allocated()) {
-      space = allocated_space();
-      tag().set_allocated_size(s - erase_gap);
-    } else {
-      space = inlined_space();
-      tag().set_inline_size(s - erase_gap);
-    }
-    std::move(range_end, space + s, range_start);
-    Destroy(space + s - erase_gap, space + s);
-  }
-  return range_start;
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::swap(InlinedVector& other) {
-  using std::swap;  // Augment ADL with std::swap.
-  if (&other == this) {
-    return;
-  }
-  if (allocated() && other.allocated()) {
-    // Both out of line, so just swap the tag, allocation, and allocator.
-    swap(tag(), other.tag());
-    swap(allocation(), other.allocation());
-    swap(allocator(), other.allocator());
-    return;
-  }
-  if (!allocated() && !other.allocated()) {
-    // Both inlined: swap up to smaller size, then move remaining elements.
-    InlinedVector* a = this;
-    InlinedVector* b = &other;
-    if (size() < other.size()) {
-      swap(a, b);
-    }
-
-    const size_type a_size = a->size();
-    const size_type b_size = b->size();
-    assert(a_size >= b_size);
-    // 'a' is larger. Swap the elements up to the smaller array size.
-    std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
-                     b->inlined_space());
-
-    // Move the remaining elements: A[b_size,a_size) -> B[b_size,a_size)
-    b->UninitializedCopy(a->inlined_space() + b_size,
-                         a->inlined_space() + a_size,
-                         b->inlined_space() + b_size);
-    a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
-
-    swap(a->tag(), b->tag());
-    swap(a->allocator(), b->allocator());
-    assert(b->size() == a_size);
-    assert(a->size() == b_size);
-    return;
-  }
-  // One is out of line, one is inline.
-  // We first move the elements from the inlined vector into the
-  // inlined space in the other vector.  We then put the other vector's
-  // pointer/capacity into the originally inlined vector and swap
-  // the tags.
-  InlinedVector* a = this;
-  InlinedVector* b = &other;
-  if (a->allocated()) {
-    swap(a, b);
-  }
-  assert(!a->allocated());
-  assert(b->allocated());
-  const size_type a_size = a->size();
-  const size_type b_size = b->size();
-  // In an optimized build, b_size would be unused.
-  (void)b_size;
-
-  // Made Local copies of size(), don't need tag() accurate anymore
-  swap(a->tag(), b->tag());
-
-  // Copy b_allocation out before b's union gets clobbered by inline_space.
-  Allocation b_allocation = b->allocation();
-
-  b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
-                       b->inlined_space());
-  a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
-
-  a->allocation() = b_allocation;
-
-  if (a->allocator() != b->allocator()) {
-    swap(a->allocator(), b->allocator());
-  }
-
-  assert(b->size() == a_size);
-  assert(a->size() == b_size);
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::EnlargeBy(size_type delta) {
-  const size_type s = size();
-  assert(s <= capacity());
-
-  size_type target = std::max(static_cast<size_type>(N), s + delta);
-
-  // Compute new capacity by repeatedly doubling current capacity
-  // TODO(psrc): Check and avoid overflow?
-  size_type new_capacity = capacity();
-  while (new_capacity < target) {
-    new_capacity <<= 1;
-  }
-
-  Allocation new_allocation(allocator(), new_capacity);
-
-  UninitializedCopy(std::make_move_iterator(data()),
-                    std::make_move_iterator(data() + s),
-                    new_allocation.buffer());
-
-  ResetAllocation(new_allocation, s);
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::ShiftRight(const_iterator position, size_type n)
-    -> std::pair<iterator, iterator> {
-  iterator start_used = const_cast<iterator>(position);
-  iterator start_raw = const_cast<iterator>(position);
-  size_type s = size();
-  size_type required_size = s + n;
-
-  if (required_size > capacity()) {
-    // Compute new capacity by repeatedly doubling current capacity
-    size_type new_capacity = capacity();
-    while (new_capacity < required_size) {
-      new_capacity <<= 1;
-    }
-    // Move everyone into the new allocation, leaving a gap of n for the
-    // requested shift.
-    Allocation new_allocation(allocator(), new_capacity);
-    size_type index = position - begin();
-    UninitializedCopy(std::make_move_iterator(data()),
-                      std::make_move_iterator(data() + index),
-                      new_allocation.buffer());
-    UninitializedCopy(std::make_move_iterator(data() + index),
-                      std::make_move_iterator(data() + s),
-                      new_allocation.buffer() + index + n);
-    ResetAllocation(new_allocation, s);
-
-    // New allocation means our iterator is invalid, so we'll recalculate.
-    // Since the entire gap is in new space, there's no used space to reuse.
-    start_raw = begin() + index;
-    start_used = start_raw;
-  } else {
-    // If we had enough space, it's a two-part move. Elements going into
-    // previously-unoccupied space need an UninitializedCopy. Elements
-    // going into a previously-occupied space are just a move.
-    iterator pos = const_cast<iterator>(position);
-    iterator raw_space = end();
-    size_type slots_in_used_space = raw_space - pos;
-    size_type new_elements_in_used_space = std::min(n, slots_in_used_space);
-    size_type new_elements_in_raw_space = n - new_elements_in_used_space;
-    size_type old_elements_in_used_space =
-        slots_in_used_space - new_elements_in_used_space;
-
-    UninitializedCopy(std::make_move_iterator(pos + old_elements_in_used_space),
-                      std::make_move_iterator(raw_space),
-                      raw_space + new_elements_in_raw_space);
-    std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
-
-    // If the gap is entirely in raw space, the used space starts where the raw
-    // space starts, leaving no elements in used space. If the gap is entirely
-    // in used space, the raw space starts at the end of the gap, leaving all
-    // elements accounted for within the used space.
-    start_used = pos;
-    start_raw = pos + new_elements_in_used_space;
-  }
-  tag().add_size(n);
-  return std::make_pair(start_used, start_raw);
-}
-
-template <typename T, size_t N, typename A>
-void InlinedVector<T, N, A>::Destroy(value_type* ptr, value_type* ptr_last) {
-  for (value_type* p = ptr; p != ptr_last; ++p) {
-    AllocatorTraits::destroy(allocator(), p);
-  }
-
-  // Overwrite unused memory with 0xab so we can catch uninitialized usage.
-  // Cast to void* to tell the compiler that we don't care that we might be
-  // scribbling on a vtable pointer.
-#ifndef NDEBUG
-  if (ptr != ptr_last) {
-    memset(reinterpret_cast<void*>(ptr), 0xab, sizeof(*ptr) * (ptr_last - ptr));
-  }
-#endif
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iter>
-void InlinedVector<T, N, A>::AppendRange(Iter first, Iter last,
-                                         std::forward_iterator_tag) {
-  using Length = typename std::iterator_traits<Iter>::difference_type;
-  Length length = std::distance(first, last);
-  reserve(size() + length);
-  if (allocated()) {
-    UninitializedCopy(first, last, allocated_space() + size());
-    tag().set_allocated_size(size() + length);
-  } else {
-    UninitializedCopy(first, last, inlined_space() + size());
-    tag().set_inline_size(size() + length);
-  }
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iter>
-void InlinedVector<T, N, A>::AssignRange(Iter first, Iter last,
-                                         std::input_iterator_tag) {
-  // Optimized to avoid reallocation.
-  // Prefer reassignment to copy construction for elements.
-  iterator out = begin();
-  for (; first != last && out != end(); ++first, ++out) {
-    *out = *first;
-  }
-  erase(out, end());
-  std::copy(first, last, std::back_inserter(*this));
-}
-
-template <typename T, size_t N, typename A>
-template <typename Iter>
-void InlinedVector<T, N, A>::AssignRange(Iter first, Iter last,
-                                         std::forward_iterator_tag) {
-  using Length = typename std::iterator_traits<Iter>::difference_type;
-  Length length = std::distance(first, last);
-  // Prefer reassignment to copy construction for elements.
-  if (static_cast<size_type>(length) <= size()) {
-    erase(std::copy(first, last, begin()), end());
-    return;
-  }
-  reserve(length);
-  iterator out = begin();
-  for (; out != end(); ++first, ++out) *out = *first;
-  if (allocated()) {
-    UninitializedCopy(first, last, out);
-    tag().set_allocated_size(length);
-  } else {
-    UninitializedCopy(first, last, out);
-    tag().set_inline_size(length);
-  }
-}
-
-template <typename T, size_t N, typename A>
-auto InlinedVector<T, N, A>::InsertWithCount(const_iterator position,
-                                             size_type n, const value_type& v)
-    -> iterator {
-  assert(position >= begin() && position <= end());
-  if (n == 0) return const_cast<iterator>(position);
-
-  value_type copy = v;
-  std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
-  std::fill(it_pair.first, it_pair.second, copy);
-  UninitializedFill(it_pair.second, it_pair.first + n, copy);
-
-  return it_pair.first;
-}
-
-template <typename T, size_t N, typename A>
-template <typename InputIter>
-auto InlinedVector<T, N, A>::InsertWithRange(const_iterator position,
-                                             InputIter first, InputIter last,
-                                             std::input_iterator_tag)
-    -> iterator {
-  assert(position >= begin() && position <= end());
-  size_type index = position - cbegin();
-  size_type i = index;
-  while (first != last) insert(begin() + i++, *first++);
-  return begin() + index;
-}
-
-// Overload of InlinedVector::InsertWithRange()
-template <typename T, size_t N, typename A>
-template <typename ForwardIter>
-auto InlinedVector<T, N, A>::InsertWithRange(const_iterator position,
-                                             ForwardIter first,
-                                             ForwardIter last,
-                                             std::forward_iterator_tag)
-    -> iterator {
-  assert(position >= begin() && position <= end());
-  if (first == last) {
-    return const_cast<iterator>(position);
-  }
-  using Length = typename std::iterator_traits<ForwardIter>::difference_type;
-  Length n = std::distance(first, last);
-  std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
-  size_type used_spots = it_pair.second - it_pair.first;
-  ForwardIter open_spot = std::next(first, used_spots);
-  std::copy(first, open_spot, it_pair.first);
-  UninitializedCopy(open_spot, last, it_pair.second);
-  return it_pair.first;
-}
-
-}  // namespace absl
+// Do not depend on any below implementation details!
+// -----------------------------------------------------------------------------
 
 #endif  // ABSL_CONTAINER_INLINED_VECTOR_H_
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index a3ad0f8..867a29e 100644
--- a/absl/container/inlined_vector_benchmark.cc
+++ b/absl/container/inlined_vector_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -23,17 +23,13 @@
 
 namespace {
 
-using IntVec = absl::InlinedVector<int, 8>;
-
 void BM_InlinedVectorFill(benchmark::State& state) {
-  const int len = state.range(0);
+  absl::InlinedVector<int, 8> v;
+  int val = 10;
   for (auto _ : state) {
-    IntVec v;
-    for (int i = 0; i < len; i++) {
-      v.push_back(i);
-    }
+    benchmark::DoNotOptimize(v);
+    v.push_back(val);
   }
-  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
 }
 BENCHMARK(BM_InlinedVectorFill)->Range(0, 1024);
 
@@ -43,23 +39,25 @@
   for (int i = 0; i < len; i++) {
     ia[i] = i;
   }
+  auto* from = ia.get();
+  auto* to = from + len;
   for (auto _ : state) {
-    IntVec v(ia.get(), ia.get() + len);
+    benchmark::DoNotOptimize(from);
+    benchmark::DoNotOptimize(to);
+    absl::InlinedVector<int, 8> v(from, to);
     benchmark::DoNotOptimize(v);
   }
-  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
 }
 BENCHMARK(BM_InlinedVectorFillRange)->Range(0, 1024);
 
 void BM_StdVectorFill(benchmark::State& state) {
-  const int len = state.range(0);
+  std::vector<int> v;
+  int val = 10;
   for (auto _ : state) {
-    std::vector<int> v;
-    for (int i = 0; i < len; i++) {
-      v.push_back(i);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(val);
+    v.push_back(val);
   }
-  state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
 }
 BENCHMARK(BM_StdVectorFill)->Range(0, 1024);
 
@@ -89,7 +87,7 @@
   const int len = state.range(0);
   const int no_sso = GetNonShortStringOptimizationSize();
   std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
-                       std::string(no_sso, 'C'), std::string(no_sso, 'D')};
+                            std::string(no_sso, 'C'), std::string(no_sso, 'D')};
 
   for (auto _ : state) {
     absl::InlinedVector<std::string, 8> v;
@@ -105,7 +103,7 @@
   const int len = state.range(0);
   const int no_sso = GetNonShortStringOptimizationSize();
   std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
-                       std::string(no_sso, 'C'), std::string(no_sso, 'D')};
+                            std::string(no_sso, 'C'), std::string(no_sso, 'D')};
 
   for (auto _ : state) {
     std::vector<std::string> v;
@@ -124,7 +122,7 @@
   void* user_data;
 };
 
-void BM_InlinedVectorTenAssignments(benchmark::State& state) {
+void BM_InlinedVectorAssignments(benchmark::State& state) {
   const int len = state.range(0);
   using BufferVec = absl::InlinedVector<Buffer, 2>;
 
@@ -133,18 +131,25 @@
 
   BufferVec dst;
   for (auto _ : state) {
-    for (int i = 0; i < 10; ++i) {
-      dst = src;
-    }
+    benchmark::DoNotOptimize(dst);
+    benchmark::DoNotOptimize(src);
+    dst = src;
   }
 }
-BENCHMARK(BM_InlinedVectorTenAssignments)
-    ->Arg(0)->Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(20);
+BENCHMARK(BM_InlinedVectorAssignments)
+    ->Arg(0)
+    ->Arg(1)
+    ->Arg(2)
+    ->Arg(3)
+    ->Arg(4)
+    ->Arg(20);
 
 void BM_CreateFromContainer(benchmark::State& state) {
   for (auto _ : state) {
-    absl::InlinedVector<int, 4> x(absl::InlinedVector<int, 4>{1, 2, 3});
-    benchmark::DoNotOptimize(x);
+    absl::InlinedVector<int, 4> src{1, 2, 3};
+    benchmark::DoNotOptimize(src);
+    absl::InlinedVector<int, 4> dst(std::move(src));
+    benchmark::DoNotOptimize(dst);
   }
 }
 BENCHMARK(BM_CreateFromContainer);
@@ -159,15 +164,14 @@
 
 struct LargeCopyableSwappable {
   LargeCopyableSwappable() : d(1024, 17) {}
+
   LargeCopyableSwappable(const LargeCopyableSwappable& o) = default;
-  LargeCopyableSwappable(LargeCopyableSwappable&& o) = delete;
 
   LargeCopyableSwappable& operator=(LargeCopyableSwappable o) {
     using std::swap;
     swap(*this, o);
     return *this;
   }
-  LargeCopyableSwappable& operator=(LargeCopyableSwappable&& o) = delete;
 
   friend void swap(LargeCopyableSwappable& a, LargeCopyableSwappable& b) {
     using std::swap;
@@ -215,6 +219,8 @@
   Vec b;
   for (auto _ : state) {
     using std::swap;
+    benchmark::DoNotOptimize(a);
+    benchmark::DoNotOptimize(b);
     swap(a, b);
   }
 }
@@ -260,60 +266,44 @@
 void BM_InlinedVectorIndexInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    for (int i = 0; i < 1000; ++i) {
-      benchmark::DoNotOptimize(v);
-      benchmark::DoNotOptimize(v[4]);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v[4]);
   }
-  state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorIndexInlined);
 
 void BM_InlinedVectorIndexExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    for (int i = 0; i < 1000; ++i) {
-      benchmark::DoNotOptimize(v);
-      benchmark::DoNotOptimize(v[4]);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v[4]);
   }
-  state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorIndexExternal);
 
 void BM_StdVectorIndex(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    for (int i = 0; i < 1000; ++i) {
-      benchmark::DoNotOptimize(v);
-      benchmark::DoNotOptimize(v[4]);
-    }
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v[4]);
   }
-  state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_StdVectorIndex);
 
-#define UNROLL_2(x)            \
-  benchmark::DoNotOptimize(x); \
-  benchmark::DoNotOptimize(x);
-
-#define UNROLL_4(x) UNROLL_2(x) UNROLL_2(x)
-#define UNROLL_8(x) UNROLL_4(x) UNROLL_4(x)
-#define UNROLL_16(x) UNROLL_8(x) UNROLL_8(x);
-
 void BM_InlinedVectorDataInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    UNROLL_16(v.data());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.data());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorDataInlined);
 
 void BM_InlinedVectorDataExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.data());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.data());
   }
   state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
@@ -322,7 +312,8 @@
 void BM_StdVectorData(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.data());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.data());
   }
   state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
@@ -331,54 +322,54 @@
 void BM_InlinedVectorSizeInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    UNROLL_16(v.size());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.size());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorSizeInlined);
 
 void BM_InlinedVectorSizeExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.size());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.size());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorSizeExternal);
 
 void BM_StdVectorSize(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.size());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.size());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_StdVectorSize);
 
 void BM_InlinedVectorEmptyInlined(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
   for (auto _ : state) {
-    UNROLL_16(v.empty());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.empty());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorEmptyInlined);
 
 void BM_InlinedVectorEmptyExternal(benchmark::State& state) {
   absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.empty());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.empty());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_InlinedVectorEmptyExternal);
 
 void BM_StdVectorEmpty(benchmark::State& state) {
   std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   for (auto _ : state) {
-    UNROLL_16(v.empty());
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(v.empty());
   }
-  state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
 }
 BENCHMARK(BM_StdVectorEmpty);
 
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc
index 08dcd3e..6037001 100644
--- a/absl/container/inlined_vector_test.cc
+++ b/absl/container/inlined_vector_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -30,6 +30,7 @@
 #include "absl/base/internal/exception_testing.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
+#include "absl/container/internal/counting_allocator.h"
 #include "absl/container/internal/test_instance_tracker.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/memory/memory.h"
@@ -37,6 +38,7 @@
 
 namespace {
 
+using absl::container_internal::CountingAllocator;
 using absl::test_internal::CopyableMovableInstance;
 using absl::test_internal::CopyableOnlyInstance;
 using absl::test_internal::InstanceTracker;
@@ -68,7 +70,7 @@
 // test_instance_tracker.h.
 template <typename T>
 class InstanceTest : public ::testing::Test {};
-TYPED_TEST_CASE_P(InstanceTest);
+TYPED_TEST_SUITE_P(InstanceTest);
 
 // A simple reference counted class to make sure that the proper elements are
 // destroyed in the erase(begin, end) test.
@@ -138,57 +140,6 @@
   return v;
 }
 
-// This is a stateful allocator, but the state lives outside of the
-// allocator (in whatever test is using the allocator). This is odd
-// but helps in tests where the allocator is propagated into nested
-// containers - that chain of allocators uses the same state and is
-// thus easier to query for aggregate allocation information.
-template <typename T>
-class CountingAllocator : public std::allocator<T> {
- public:
-  using Alloc = std::allocator<T>;
-  using pointer = typename Alloc::pointer;
-  using size_type = typename Alloc::size_type;
-
-  CountingAllocator() : bytes_used_(nullptr) {}
-  explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
-
-  template <typename U>
-  CountingAllocator(const CountingAllocator<U>& x)
-      : Alloc(x), bytes_used_(x.bytes_used_) {}
-
-  pointer allocate(size_type n,
-                   std::allocator<void>::const_pointer hint = nullptr) {
-    assert(bytes_used_ != nullptr);
-    *bytes_used_ += n * sizeof(T);
-    return Alloc::allocate(n, hint);
-  }
-
-  void deallocate(pointer p, size_type n) {
-    Alloc::deallocate(p, n);
-    assert(bytes_used_ != nullptr);
-    *bytes_used_ -= n * sizeof(T);
-  }
-
-  template<typename U>
-  class rebind {
-   public:
-    using other = CountingAllocator<U>;
-  };
-
-  friend bool operator==(const CountingAllocator& a,
-                         const CountingAllocator& b) {
-    return a.bytes_used_ == b.bytes_used_;
-  }
-
-  friend bool operator!=(const CountingAllocator& a,
-                         const CountingAllocator& b) {
-    return !(a == b);
-  }
-
-  int64_t* bytes_used_;
-};
-
 TEST(IntVec, SimpleOps) {
   for (int len = 0; len < 20; len++) {
     IntVec v;
@@ -906,6 +857,8 @@
       InstanceTracker tracker;
       InstanceVec a, b;
       const size_t inlined_capacity = a.capacity();
+      auto min_len = std::min(l1, l2);
+      auto max_len = std::max(l1, l2);
       for (int i = 0; i < l1; i++) a.push_back(Instance(i));
       for (int i = 0; i < l2; i++) b.push_back(Instance(100+i));
       EXPECT_EQ(tracker.instances(), l1 + l2);
@@ -919,15 +872,15 @@
         EXPECT_EQ(tracker.swaps(), 0);  // Allocations are swapped.
         EXPECT_EQ(tracker.moves(), 0);
       } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
-        EXPECT_EQ(tracker.swaps(), std::min(l1, l2));
-        // TODO(bsamwel): This should use moves when the type is movable.
-        EXPECT_EQ(tracker.copies(), std::max(l1, l2) - std::min(l1, l2));
+        EXPECT_EQ(tracker.swaps(), min_len);
+        EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
+                  max_len - min_len);
       } else {
         // One is allocated and the other isn't. The allocation is transferred
         // without copying elements, and the inlined instances are copied/moved.
         EXPECT_EQ(tracker.swaps(), 0);
-        // TODO(bsamwel): This should use moves when the type is movable.
-        EXPECT_EQ(tracker.copies(), std::min(l1, l2));
+        EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
+                  min_len);
       }
 
       EXPECT_EQ(l1, b.size());
@@ -1726,39 +1679,58 @@
       std::scoped_allocator_adaptor<CountingAllocator<StdVector>>;
   using AllocVec = absl::InlinedVector<StdVector, 4, MyAlloc>;
 
+  // MSVC 2017's std::vector allocates different amounts of memory in debug
+  // versus opt mode.
+  int64_t test_allocated = 0;
+  StdVector v(CountingAllocator<int>{&test_allocated});
+  // The amount of memory allocated by a default constructed vector<int>
+  auto default_std_vec_allocated = test_allocated;
+  v.push_back(1);
+  // The amound of memory allocated by a copy-constructed vector<int> with one
+  // element.
+  int64_t one_element_std_vec_copy_allocated = test_allocated;
+
   int64_t allocated = 0;
   AllocVec vec(MyAlloc{CountingAllocator<StdVector>{&allocated}});
   EXPECT_EQ(allocated, 0);
 
   // This default constructs a vector<int>, but the allocator should pass itself
-  // into the vector<int>.
+  // into the vector<int>, so check allocation compared to that.
   // The absl::InlinedVector does not allocate any memory.
-  // The vector<int> does not allocate any memory.
+  // The vector<int> may allocate any memory.
+  auto expected = default_std_vec_allocated;
   vec.resize(1);
-  EXPECT_EQ(allocated, 0);
+  EXPECT_EQ(allocated, expected);
 
   // We make vector<int> allocate memory.
   // It must go through the allocator even though we didn't construct the
-  // vector directly.
+  // vector directly.  This assumes that vec[0] doesn't need to grow its
+  // allocation.
+  expected += sizeof(int);
   vec[0].push_back(1);
-  EXPECT_EQ(allocated, sizeof(int) * 1);
+  EXPECT_EQ(allocated, expected);
 
   // Another allocating vector.
+  expected += one_element_std_vec_copy_allocated;
   vec.push_back(vec[0]);
-  EXPECT_EQ(allocated, sizeof(int) * 2);
+  EXPECT_EQ(allocated, expected);
 
   // Overflow the inlined memory.
   // The absl::InlinedVector will now allocate.
+  expected += sizeof(StdVector) * 8 + default_std_vec_allocated * 3;
   vec.resize(5);
-  EXPECT_EQ(allocated, sizeof(int) * 2 + sizeof(StdVector) * 8);
+  EXPECT_EQ(allocated, expected);
 
   // Adding one more in external mode should also work.
+  expected += one_element_std_vec_copy_allocated;
   vec.push_back(vec[0]);
-  EXPECT_EQ(allocated, sizeof(int) * 3 + sizeof(StdVector) * 8);
+  EXPECT_EQ(allocated, expected);
 
-  // And extending these should still work.
+  // And extending these should still work.  This assumes that vec[0] does not
+  // need to grow its allocation.
+  expected += sizeof(int);
   vec[0].push_back(1);
-  EXPECT_EQ(allocated, sizeof(int) * 4 + sizeof(StdVector) * 8);
+  EXPECT_EQ(allocated, expected);
 
   vec.clear();
   EXPECT_EQ(allocated, 0);
@@ -1790,4 +1762,23 @@
   }
 }
 
+TEST(InlinedVectorTest, AbslHashValueWorks) {
+  using V = absl::InlinedVector<int, 4>;
+  std::vector<V> cases;
+
+  // Generate a variety of vectors some of these are small enough for the inline
+  // space but are stored out of line.
+  for (int i = 0; i < 10; ++i) {
+    V v;
+    for (int j = 0; j < i; ++j) {
+      v.push_back(j);
+    }
+    cases.push_back(v);
+    v.resize(i % 4);
+    cases.push_back(v);
+  }
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
+}
+
 }  // anonymous namespace
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
new file mode 100644
index 0000000..b06e711
--- /dev/null
+++ b/absl/container/internal/common.h
@@ -0,0 +1,183 @@
+// 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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+#define ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+
+#include <cassert>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+namespace container_internal {
+
+template <class, class = void>
+struct IsTransparent : std::false_type {};
+template <class T>
+struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
+    : std::true_type {};
+
+template <bool is_transparent>
+struct KeyArg {
+  // Transparent. Forward `K`.
+  template <typename K, typename key_type>
+  using type = K;
+};
+
+template <>
+struct KeyArg<false> {
+  // Not transparent. Always use `key_type`.
+  template <typename K, typename key_type>
+  using type = key_type;
+};
+
+// The node_handle concept from C++17.
+// We specialize node_handle for sets and maps. node_handle_base holds the
+// common API of both.
+template <typename PolicyTraits, typename Alloc>
+class node_handle_base {
+ protected:
+  using slot_type = typename PolicyTraits::slot_type;
+
+ public:
+  using allocator_type = Alloc;
+
+  constexpr node_handle_base() {}
+  node_handle_base(node_handle_base&& other) noexcept {
+    *this = std::move(other);
+  }
+  ~node_handle_base() { destroy(); }
+  node_handle_base& operator=(node_handle_base&& other) noexcept {
+    destroy();
+    if (!other.empty()) {
+      alloc_ = other.alloc_;
+      PolicyTraits::transfer(alloc(), slot(), other.slot());
+      other.reset();
+    }
+    return *this;
+  }
+
+  bool empty() const noexcept { return !alloc_; }
+  explicit operator bool() const noexcept { return !empty(); }
+  allocator_type get_allocator() const { return *alloc_; }
+
+ protected:
+  friend struct CommonAccess;
+
+  node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
+    PolicyTraits::transfer(alloc(), slot(), s);
+  }
+
+  void destroy() {
+    if (!empty()) {
+      PolicyTraits::destroy(alloc(), slot());
+      reset();
+    }
+  }
+
+  void reset() {
+    assert(alloc_.has_value());
+    alloc_ = absl::nullopt;
+  }
+
+  slot_type* slot() const {
+    assert(!empty());
+    return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
+  }
+  allocator_type* alloc() { return std::addressof(*alloc_); }
+
+ private:
+  absl::optional<allocator_type> alloc_;
+  mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
+      slot_space_;
+};
+
+// For sets.
+template <typename Policy, typename PolicyTraits, typename Alloc,
+          typename = void>
+class node_handle : public node_handle_base<PolicyTraits, Alloc> {
+  using Base = typename node_handle::node_handle_base;
+
+ public:
+  using value_type = typename PolicyTraits::value_type;
+
+  constexpr node_handle() {}
+
+  value_type& value() const { return PolicyTraits::element(this->slot()); }
+
+ private:
+  friend struct CommonAccess;
+
+  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
+};
+
+// For maps.
+template <typename Policy, typename PolicyTraits, typename Alloc>
+class node_handle<Policy, PolicyTraits, Alloc,
+                  absl::void_t<typename Policy::mapped_type>>
+    : public node_handle_base<PolicyTraits, Alloc> {
+  using Base = typename node_handle::node_handle_base;
+
+ public:
+  using key_type = typename Policy::key_type;
+  using mapped_type = typename Policy::mapped_type;
+
+  constexpr node_handle() {}
+
+  auto key() const -> decltype(PolicyTraits::key(this->slot())) {
+    return PolicyTraits::key(this->slot());
+  }
+
+  mapped_type& mapped() const {
+    return PolicyTraits::value(&PolicyTraits::element(this->slot()));
+  }
+
+ private:
+  friend struct CommonAccess;
+
+  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
+};
+
+// Provide access to non-public node-handle functions.
+struct CommonAccess {
+  template <typename Node>
+  static auto GetSlot(const Node& node) -> decltype(node.slot()) {
+    return node.slot();
+  }
+
+  template <typename Node>
+  static void Reset(Node* node) {
+    node->reset();
+  }
+
+  template <typename T, typename... Args>
+  static T Make(Args&&... args) {
+    return T(std::forward<Args>(args)...);
+  }
+};
+
+// Implement the insert_return_type<> concept of C++17.
+template <class Iterator, class NodeType>
+struct InsertReturnType {
+  Iterator position;
+  bool inserted;
+  NodeType node;
+};
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_CONTAINER_H_
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index cc52614..b9bd91a 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -27,7 +27,7 @@
 //   const T2& t2 = value.get<2>();
 //   ...
 //
-// http://en.cppreference.com/w/cpp/language/ebo
+// https://en.cppreference.com/w/cpp/language/ebo
 
 #ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
 #define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
@@ -89,8 +89,10 @@
   T value;
   constexpr Storage() = default;
   explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
-  constexpr const T& get() const { return value; }
-  T& get() { return value; }
+  constexpr const T& get() const& { return value; }
+  T& get() & { return value; }
+  constexpr const T&& get() const&& { return absl::move(*this).value; }
+  T&& get() && { return std::move(*this).value; }
 };
 
 template <typename D, size_t I>
@@ -99,8 +101,10 @@
   using T = internal_compressed_tuple::ElemT<D, I>;
   constexpr Storage() = default;
   explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
-  constexpr const T& get() const { return *this; }
-  T& get() { return *this; }
+  constexpr const T& get() const& { return *this; }
+  T& get() & { return *this; }
+  constexpr const T&& get() const&& { return absl::move(*this); }
+  T&& get() && { return std::move(*this); }
 };
 
 template <typename D, typename I>
@@ -137,7 +141,7 @@
 //   const T2& t2 = value.get<2>();
 //   ...
 //
-// http://en.cppreference.com/w/cpp/language/ebo
+// https://en.cppreference.com/w/cpp/language/ebo
 template <typename... Ts>
 class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
     : private internal_compressed_tuple::CompressedTupleImpl<
@@ -152,14 +156,26 @@
       : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
 
   template <int I>
-  ElemT<I>& get() {
+  ElemT<I>& get() & {
     return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
   }
 
   template <int I>
-  constexpr const ElemT<I>& get() const {
+  constexpr const ElemT<I>& get() const& {
     return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
   }
+
+  template <int I>
+  ElemT<I>&& get() && {
+    return std::move(*this)
+        .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+  }
+
+  template <int I>
+  constexpr const ElemT<I>&& get() const&& {
+    return absl::move(*this)
+        .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+  }
 };
 
 // Explicit specialization for a zero-element tuple
diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc
index 45030c6..28e7741 100644
--- a/absl/container/internal/compressed_tuple_test.cc
+++ b/absl/container/internal/compressed_tuple_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -14,17 +14,25 @@
 
 #include "absl/container/internal/compressed_tuple.h"
 
+#include <memory>
 #include <string>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/memory/memory.h"
+#include "absl/utility/utility.h"
 
 namespace absl {
 namespace container_internal {
 namespace {
 
+enum class CallType { kConstRef, kConstMove };
+
 template <int>
-struct Empty {};
+struct Empty {
+  constexpr CallType value() const& { return CallType::kConstRef; }
+  constexpr CallType value() const&& { return CallType::kConstMove; }
+};
 
 template <typename T>
 struct NotEmpty {
@@ -140,15 +148,44 @@
   EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);
 }
 
+TEST(CompressedTupleTest, MoveOnlyElements) {
+  CompressedTuple<std::unique_ptr<std::string>> str_tup(
+      absl::make_unique<std::string>("str"));
+
+  CompressedTuple<CompressedTuple<std::unique_ptr<std::string>>,
+                  std::unique_ptr<int>>
+  x(std::move(str_tup), absl::make_unique<int>(5));
+
+  EXPECT_EQ(*x.get<0>().get<0>(), "str");
+  EXPECT_EQ(*x.get<1>(), 5);
+
+  std::unique_ptr<std::string> x0 = std::move(x.get<0>()).get<0>();
+  std::unique_ptr<int> x1 = std::move(x).get<1>();
+
+  EXPECT_EQ(*x0, "str");
+  EXPECT_EQ(*x1, 5);
+}
+
 TEST(CompressedTupleTest, Constexpr) {
-  constexpr CompressedTuple<int, double, CompressedTuple<int>> x(
-      7, 1.25, CompressedTuple<int>(5));
+  constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> x(
+      7, 1.25, CompressedTuple<int>(5), {});
   constexpr int x0 = x.get<0>();
   constexpr double x1 = x.get<1>();
   constexpr int x2 = x.get<2>().get<0>();
+  constexpr CallType x3 = x.get<3>().value();
+
   EXPECT_EQ(x0, 7);
   EXPECT_EQ(x1, 1.25);
   EXPECT_EQ(x2, 5);
+  EXPECT_EQ(x3, CallType::kConstRef);
+
+#if defined(__clang__)
+  // An apparent bug in earlier versions of gcc claims these are ambiguous.
+  constexpr int x2m = absl::move(x.get<2>()).get<0>();
+  constexpr CallType x3m = absl::move(x).get<3>().value();
+  EXPECT_EQ(x2m, 5);
+  EXPECT_EQ(x3m, CallType::kConstMove);
+#endif
 }
 
 #if defined(__clang__) || defined(__GNUC__)
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index 56c5d2d..e5bb977 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -286,13 +286,48 @@
 
 }  // namespace memory_internal
 
-// If kMutableKeys is false, only the value member is accessed.
+// The internal storage type for key-value containers like flat_hash_map.
 //
-// If kMutableKeys is true, key is accessed through all slots while value and
-// mutable_value are accessed only via INITIALIZED slots. Slots are created and
-// destroyed via mutable_value so that the key can be moved later.
+// It is convenient for the value_type of a flat_hash_map<K, V> to be
+// pair<const K, V>; the "const K" prevents accidental modification of the key
+// when dealing with the reference returned from find() and similar methods.
+// However, this creates other problems; we want to be able to emplace(K, V)
+// efficiently with move operations, and similarly be able to move a
+// pair<K, V> in insert().
+//
+// The solution is this union, which aliases the const and non-const versions
+// of the pair. This also allows flat_hash_map<const K, V> to work, even though
+// that has the same efficiency issues with move in emplace() and insert() -
+// but people do it anyway.
+//
+// If kMutableKeys is false, only the value member can be accessed.
+//
+// If kMutableKeys is true, key can be accessed through all slots while value
+// and mutable_value must be accessed only via INITIALIZED slots. Slots are
+// created and destroyed via mutable_value so that the key can be moved later.
+//
+// Accessing one of the union fields while the other is active is safe as
+// long as they are layout-compatible, which is guaranteed by the definition of
+// kMutableKeys. For C++11, the relevant section of the standard is
+// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
 template <class K, class V>
-union slot_type {
+union map_slot_type {
+  map_slot_type() {}
+  ~map_slot_type() = delete;
+  using value_type = std::pair<const K, V>;
+  using mutable_value_type = std::pair<K, V>;
+
+  value_type value;
+  mutable_value_type mutable_value;
+  K key;
+};
+
+template <class K, class V>
+struct map_slot_policy {
+  using slot_type = map_slot_type<K, V>;
+  using value_type = std::pair<const K, V>;
+  using mutable_value_type = std::pair<K, V>;
+
  private:
   static void emplace(slot_type* slot) {
     // The construction of union doesn't do anything at runtime but it allows us
@@ -302,19 +337,17 @@
   // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
   // or the other via slot_type. We are also free to access the key via
   // slot_type::key in this case.
-  using kMutableKeys =
-      std::integral_constant<bool,
-                             memory_internal::IsLayoutCompatible<K, V>::value>;
+  using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;
 
  public:
-  slot_type() {}
-  ~slot_type() = delete;
-  using value_type = std::pair<const K, V>;
-  using mutable_value_type = std::pair<K, V>;
+  static value_type& element(slot_type* slot) { return slot->value; }
+  static const value_type& element(const slot_type* slot) {
+    return slot->value;
+  }
 
-  value_type value;
-  mutable_value_type mutable_value;
-  K key;
+  static const K& key(const slot_type* slot) {
+    return kMutableKeys::value ? slot->key : slot->value.first;
+  }
 
   template <class Allocator, class... Args>
   static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
diff --git a/absl/container/internal/container_memory_test.cc b/absl/container/internal/container_memory_test.cc
index f1c4058..d6b0495 100644
--- a/absl/container/internal/container_memory_test.cc
+++ b/absl/container/internal/container_memory_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/counting_allocator.h b/absl/container/internal/counting_allocator.h
new file mode 100644
index 0000000..4e717be
--- /dev/null
+++ b/absl/container/internal/counting_allocator.h
@@ -0,0 +1,79 @@
+// 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.
+
+#ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
+#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+
+namespace absl {
+namespace container_internal {
+
+// This is a stateful allocator, but the state lives outside of the
+// allocator (in whatever test is using the allocator). This is odd
+// but helps in tests where the allocator is propagated into nested
+// containers - that chain of allocators uses the same state and is
+// thus easier to query for aggregate allocation information.
+template <typename T>
+class CountingAllocator : public std::allocator<T> {
+ public:
+  using Alloc = std::allocator<T>;
+  using pointer = typename Alloc::pointer;
+  using size_type = typename Alloc::size_type;
+
+  CountingAllocator() : bytes_used_(nullptr) {}
+  explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
+
+  template <typename U>
+  CountingAllocator(const CountingAllocator<U>& x)
+      : Alloc(x), bytes_used_(x.bytes_used_) {}
+
+  pointer allocate(size_type n,
+                   std::allocator<void>::const_pointer hint = nullptr) {
+    assert(bytes_used_ != nullptr);
+    *bytes_used_ += n * sizeof(T);
+    return Alloc::allocate(n, hint);
+  }
+
+  void deallocate(pointer p, size_type n) {
+    Alloc::deallocate(p, n);
+    assert(bytes_used_ != nullptr);
+    *bytes_used_ -= n * sizeof(T);
+  }
+
+  template<typename U>
+  class rebind {
+   public:
+    using other = CountingAllocator<U>;
+  };
+
+  friend bool operator==(const CountingAllocator& a,
+                         const CountingAllocator& b) {
+    return a.bytes_used_ == b.bytes_used_;
+  }
+
+  friend bool operator!=(const CountingAllocator& a,
+                         const CountingAllocator& b) {
+    return !(a == b);
+  }
+
+  int64_t* bytes_used_;
+};
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h
index 1f0d794..cb8f03c 100644
--- a/absl/container/internal/hash_function_defaults.h
+++ b/absl/container/internal/hash_function_defaults.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -39,8 +39,8 @@
 // equal functions are still bound to T. This is important because some type U
 // can be hashed by/tested for equality differently depending on T. A notable
 // example is `const char*`. `const char*` is treated as a c-style string when
-// the hash function is hash<string> but as a pointer when the hash function is
-// hash<void*>.
+// the hash function is hash<std::string> but as a pointer when the hash
+// function is hash<void*>.
 //
 #ifndef ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
 #define ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
@@ -83,6 +83,7 @@
     }
   };
 };
+
 template <>
 struct HashEq<std::string> : StringHashEq {};
 template <>
diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc
index 464baae..82708db 100644
--- a/absl/container/internal/hash_function_defaults_test.cc
+++ b/absl/container/internal/hash_function_defaults_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -77,14 +77,14 @@
   hash_default_eq<T> key_eq;
 };
 
-TYPED_TEST_CASE(EqString, StringTypes);
+TYPED_TEST_SUITE(EqString, StringTypes);
 
 template <class T>
 struct HashString : ::testing::Test {
   hash_default_hash<T> hasher;
 };
 
-TYPED_TEST_CASE(HashString, StringTypes);
+TYPED_TEST_SUITE(HashString, StringTypes);
 
 TYPED_TEST(EqString, Works) {
   auto eq = this->key_eq;
@@ -121,14 +121,14 @@
   hash_default_eq<T> key_eq;
 };
 
-TYPED_TEST_CASE(EqPointer, PointerTypes);
+TYPED_TEST_SUITE(EqPointer, PointerTypes);
 
 template <class T>
 struct HashPointer : ::testing::Test {
   hash_default_hash<T> hasher;
 };
 
-TYPED_TEST_CASE(HashPointer, PointerTypes);
+TYPED_TEST_SUITE(HashPointer, PointerTypes);
 
 TYPED_TEST(EqPointer, Works) {
   int dummy;
@@ -202,15 +202,11 @@
   EXPECT_NE(hash(&dummy), hash(cuptr));
 }
 
-// Cartesian product of (string, std::string, absl::string_view)
-// with (string, std::string, absl::string_view, const char*).
+// Cartesian product of (std::string, absl::string_view)
+// with (std::string, absl::string_view, const char*).
 using StringTypesCartesianProduct = Types<
     // clang-format off
 
-    std::pair<std::string, std::string>,
-    std::pair<std::string, absl::string_view>,
-    std::pair<std::string, const char*>,
-
     std::pair<absl::string_view, std::string>,
     std::pair<absl::string_view, absl::string_view>,
     std::pair<absl::string_view, const char*>>;
@@ -248,7 +244,7 @@
   EXPECT_NE(this->hash(this->a1), this->hash(this->b2));
 }
 
-TYPED_TEST_CASE(StringLikeTest, StringTypesCartesianProduct);
+TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct);
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index 0d6a9df..37a23d6 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -39,9 +39,9 @@
 
 }  // namespace
 
-std::mt19937_64* GetThreadLocalRng() {
+std::mt19937_64* GetSharedRng() {
   RandomDeviceSeedSeq seed_seq;
-  thread_local auto* rng = new std::mt19937_64(seed_seq);
+  static auto* rng = new std::mt19937_64(seed_seq);
   return rng;
 }
 
@@ -51,7 +51,7 @@
   std::string res;
   res.resize(32);
   std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetThreadLocalRng()); });
+                [&]() { return chars(*GetSharedRng()); });
   return res;
 }
 
@@ -63,7 +63,7 @@
   auto& res = arena->back();
   res.resize(32);
   std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetThreadLocalRng()); });
+                [&]() { return chars(*GetSharedRng()); });
   return res;
 }
 
diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h
index 50d7710..27fb84f 100644
--- a/absl/container/internal/hash_generator_testing.h
+++ b/absl/container/internal/hash_generator_testing.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -43,7 +43,7 @@
 
 }  // namespace generator_internal
 
-std::mt19937_64* GetThreadLocalRng();
+std::mt19937_64* GetSharedRng();
 
 enum Enum {
   kEnumEmpty,
@@ -66,7 +66,7 @@
 struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> {
   T operator()() const {
     std::uniform_int_distribution<T> dist;
-    return dist(*GetThreadLocalRng());
+    return dist(*GetSharedRng());
   }
 };
 
@@ -76,7 +76,7 @@
     std::uniform_int_distribution<typename std::underlying_type<Enum>::type>
         dist;
     while (true) {
-      auto variate = dist(*GetThreadLocalRng());
+      auto variate = dist(*GetSharedRng());
       if (variate != kEnumEmpty && variate != kEnumDeleted)
         return static_cast<Enum>(variate);
     }
@@ -90,7 +90,7 @@
         typename std::underlying_type<EnumClass>::type>
         dist;
     while (true) {
-      EnumClass variate = static_cast<EnumClass>(dist(*GetThreadLocalRng()));
+      EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng()));
       if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted)
         return static_cast<EnumClass>(variate);
     }
diff --git a/absl/container/internal/hash_policy_testing.h b/absl/container/internal/hash_policy_testing.h
index ffc76ea..c57407a 100644
--- a/absl/container/internal/hash_policy_testing.h
+++ b/absl/container/internal/hash_policy_testing.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -139,7 +139,7 @@
   friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); }
 
  private:
-  size_t id_ = std::numeric_limits<size_t>::max();
+  size_t id_ = (std::numeric_limits<size_t>::max)();
 };
 
 template <class Map>
@@ -169,7 +169,11 @@
 // take allocator arguments. This test is defined ad-hoc for the platforms
 // we care about (notably Crosstool 17) because libstdcxx's useless
 // versioning scheme precludes a more principled solution.
-#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425
+// From GCC-4.9 Changelog: (src: https://gcc.gnu.org/gcc-4.9/changes.html)
+// "the unordered associative containers in <unordered_map> and <unordered_set>
+// meet the allocator-aware container requirements;"
+#if (defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425 ) || \
+( __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9 ))
 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0
 #else
 #define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1
diff --git a/absl/container/internal/hash_policy_testing_test.cc b/absl/container/internal/hash_policy_testing_test.cc
index c215c42..0c95eb5 100644
--- a/absl/container/internal/hash_policy_testing_test.cc
+++ b/absl/container/internal/hash_policy_testing_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index 029e47e..fd007de 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -84,7 +84,7 @@
   }
 
   // Transfers the `old_slot` to `new_slot`. Any memory allocated by the
-  // allocator inside `old_slot` to `new_slot` can be transfered.
+  // allocator inside `old_slot` to `new_slot` can be transferred.
   //
   // OPTIONAL: defaults to:
   //
diff --git a/absl/container/internal/hash_policy_traits_test.cc b/absl/container/internal/hash_policy_traits_test.cc
index 423f154..e643d18 100644
--- a/absl/container/internal/hash_policy_traits_test.cc
+++ b/absl/container/internal/hash_policy_traits_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/hashtable_debug.h b/absl/container/internal/hashtable_debug.h
index c3bd65c..7193000 100644
--- a/absl/container/internal/hashtable_debug.h
+++ b/absl/container/internal/hashtable_debug.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -60,7 +60,7 @@
     size_t num_probes = GetHashtableDebugNumProbes(
         container,
         absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));
-    v.resize(std::max(v.size(), num_probes + 1));
+    v.resize((std::max)(v.size(), num_probes + 1));
     v[num_probes]++;
   }
   return v;
diff --git a/absl/container/internal/hashtable_debug_hooks.h b/absl/container/internal/hashtable_debug_hooks.h
index 8f21972..371ce81 100644
--- a/absl/container/internal/hashtable_debug_hooks.h
+++ b/absl/container/internal/hashtable_debug_hooks.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
new file mode 100644
index 0000000..6667d3a
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -0,0 +1,308 @@
+// 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.
+
+#include "absl/container/internal/hashtablez_sampler.h"
+
+#include <atomic>
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/memory/memory.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+namespace container_internal {
+constexpr int HashtablezInfo::kMaxStackDepth;
+
+namespace {
+ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
+   false
+};
+ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
+ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20};
+
+// Returns the next pseudo-random value.
+// pRNG is: aX+b mod c with a = 0x5DEECE66D, b =  0xB, c = 1<<48
+// This is the lrand64 generator.
+uint64_t NextRandom(uint64_t rnd) {
+  const uint64_t prng_mult = uint64_t{0x5DEECE66D};
+  const uint64_t prng_add = 0xB;
+  const uint64_t prng_mod_power = 48;
+  const uint64_t prng_mod_mask = ~(~uint64_t{0} << prng_mod_power);
+  return (prng_mult * rnd + prng_add) & prng_mod_mask;
+}
+
+// Generates a geometric variable with the specified mean.
+// This is done by generating a random number between 0 and 1 and applying
+// the inverse cumulative distribution function for an exponential.
+// Specifically: Let m be the inverse of the sample period, then
+// the probability distribution function is m*exp(-mx) so the CDF is
+// p = 1 - exp(-mx), so
+// q = 1 - p = exp(-mx)
+// log_e(q) = -mx
+// -log_e(q)/m = x
+// log_2(q) * (-log_e(2) * 1/m) = x
+// In the code, q is actually in the range 1 to 2**26, hence the -26 below
+//
+int64_t GetGeometricVariable(int64_t mean) {
+#if ABSL_HAVE_THREAD_LOCAL
+  thread_local
+#else   // ABSL_HAVE_THREAD_LOCAL
+  // SampleSlow and hence GetGeometricVariable is guarded by a single mutex when
+  // there are not thread locals.  Thus, a single global rng is acceptable for
+  // that case.
+  static
+#endif  // ABSL_HAVE_THREAD_LOCAL
+      uint64_t rng = []() {
+        // We don't get well distributed numbers from this so we call
+        // NextRandom() a bunch to mush the bits around.  We use a global_rand
+        // to handle the case where the same thread (by memory address) gets
+        // created and destroyed repeatedly.
+        ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);
+        uint64_t r = reinterpret_cast<uint64_t>(&rng) +
+                   global_rand.fetch_add(1, std::memory_order_relaxed);
+        for (int i = 0; i < 20; ++i) {
+          r = NextRandom(r);
+        }
+        return r;
+      }();
+
+  rng = NextRandom(rng);
+
+  // Take the top 26 bits as the random number
+  // (This plus the 1<<58 sampling bound give a max possible step of
+  // 5194297183973780480 bytes.)
+  const uint64_t prng_mod_power = 48;  // Number of bits in prng
+  // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
+  // under piii debug for some binaries.
+  double q = static_cast<uint32_t>(rng >> (prng_mod_power - 26)) + 1.0;
+  // Put the computed p-value through the CDF of a geometric.
+  double interval = (log2(q) - 26) * (-std::log(2.0) * mean);
+
+  // Very large values of interval overflow int64_t. If we happen to
+  // hit such improbable condition, we simply cheat and clamp interval
+  // to largest supported value.
+  if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {
+    return std::numeric_limits<int64_t>::max() / 2;
+  }
+
+  // Small values of interval are equivalent to just sampling next time.
+  if (interval < 1) {
+    return 1;
+  }
+  return static_cast<int64_t>(interval);
+}
+
+}  // namespace
+
+HashtablezSampler& HashtablezSampler::Global() {
+  static auto* sampler = new HashtablezSampler();
+  return *sampler;
+}
+
+HashtablezSampler::DisposeCallback HashtablezSampler::SetDisposeCallback(
+    DisposeCallback f) {
+  return dispose_.exchange(f, std::memory_order_relaxed);
+}
+
+HashtablezInfo::HashtablezInfo() { PrepareForSampling(); }
+HashtablezInfo::~HashtablezInfo() = default;
+
+void HashtablezInfo::PrepareForSampling() {
+  capacity.store(0, std::memory_order_relaxed);
+  size.store(0, std::memory_order_relaxed);
+  num_erases.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);
+  hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed);
+
+  create_time = absl::Now();
+  // The inliner makes hardcoded skip_count difficult (especially when combined
+  // with LTO).  We use the ability to exclude stacks by regex when encoding
+  // instead.
+  depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth,
+                              /* skip_count= */ 0);
+  dead = nullptr;
+}
+
+HashtablezSampler::HashtablezSampler()
+    : dropped_samples_(0), size_estimate_(0), all_(nullptr), dispose_(nullptr) {
+  absl::MutexLock l(&graveyard_.init_mu);
+  graveyard_.dead = &graveyard_;
+}
+
+HashtablezSampler::~HashtablezSampler() {
+  HashtablezInfo* s = all_.load(std::memory_order_acquire);
+  while (s != nullptr) {
+    HashtablezInfo* next = s->next;
+    delete s;
+    s = next;
+  }
+}
+
+void HashtablezSampler::PushNew(HashtablezInfo* sample) {
+  sample->next = all_.load(std::memory_order_relaxed);
+  while (!all_.compare_exchange_weak(sample->next, sample,
+                                     std::memory_order_release,
+                                     std::memory_order_relaxed)) {
+  }
+}
+
+void HashtablezSampler::PushDead(HashtablezInfo* sample) {
+  if (auto* dispose = dispose_.load(std::memory_order_relaxed)) {
+    dispose(*sample);
+  }
+
+  absl::MutexLock graveyard_lock(&graveyard_.init_mu);
+  absl::MutexLock sample_lock(&sample->init_mu);
+  sample->dead = graveyard_.dead;
+  graveyard_.dead = sample;
+}
+
+HashtablezInfo* HashtablezSampler::PopDead() {
+  absl::MutexLock graveyard_lock(&graveyard_.init_mu);
+
+  // The list is circular, so eventually it collapses down to
+  //   graveyard_.dead == &graveyard_
+  // when it is empty.
+  HashtablezInfo* sample = graveyard_.dead;
+  if (sample == &graveyard_) return nullptr;
+
+  absl::MutexLock sample_lock(&sample->init_mu);
+  graveyard_.dead = sample->dead;
+  sample->PrepareForSampling();
+  return sample;
+}
+
+HashtablezInfo* HashtablezSampler::Register() {
+  int64_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);
+  if (size > g_hashtablez_max_samples.load(std::memory_order_relaxed)) {
+    size_estimate_.fetch_sub(1, std::memory_order_relaxed);
+    dropped_samples_.fetch_add(1, std::memory_order_relaxed);
+    return nullptr;
+  }
+
+  HashtablezInfo* sample = PopDead();
+  if (sample == nullptr) {
+    // Resurrection failed.  Hire a new warlock.
+    sample = new HashtablezInfo();
+    PushNew(sample);
+  }
+
+  return sample;
+}
+
+void HashtablezSampler::Unregister(HashtablezInfo* sample) {
+  PushDead(sample);
+  size_estimate_.fetch_sub(1, std::memory_order_relaxed);
+}
+
+int64_t HashtablezSampler::Iterate(
+    const std::function<void(const HashtablezInfo& stack)>& f) {
+  HashtablezInfo* s = all_.load(std::memory_order_acquire);
+  while (s != nullptr) {
+    absl::MutexLock l(&s->init_mu);
+    if (s->dead == nullptr) {
+      f(*s);
+    }
+    s = s->next;
+  }
+
+  return dropped_samples_.load(std::memory_order_relaxed);
+}
+
+HashtablezInfo* SampleSlow(int64_t* next_sample) {
+  if (kAbslContainerInternalSampleEverything) {
+    *next_sample = 1;
+    return HashtablezSampler::Global().Register();
+  }
+
+  bool first = *next_sample < 0;
+  *next_sample = GetGeometricVariable(
+      g_hashtablez_sample_parameter.load(std::memory_order_relaxed));
+
+  // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold
+  // low enough that we will start sampling in a reasonable time, so we just use
+  // the default sampling rate.
+  if (!g_hashtablez_enabled.load(std::memory_order_relaxed)) return nullptr;
+
+  // We will only be negative on our first count, so we should just retry in
+  // that case.
+  if (first) {
+    if (ABSL_PREDICT_TRUE(--*next_sample > 0)) return nullptr;
+    return SampleSlow(next_sample);
+  }
+
+  return HashtablezSampler::Global().Register();
+}
+
+#if ABSL_PER_THREAD_TLS == 1
+ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
+#endif  // ABSL_PER_THREAD_TLS == 1
+
+void UnsampleSlow(HashtablezInfo* info) {
+  HashtablezSampler::Global().Unregister(info);
+}
+
+void RecordInsertSlow(HashtablezInfo* info, size_t hash,
+                      size_t distance_from_desired) {
+  // SwissTables probe in groups of 16, so scale this to count items probes and
+  // not offset from desired.
+  size_t probe_length = distance_from_desired;
+#if SWISSTABLE_HAVE_SSE2
+  probe_length /= 16;
+#else
+  probe_length /= 8;
+#endif
+
+  info->hashes_bitwise_and.fetch_and(hash, std::memory_order_relaxed);
+  info->hashes_bitwise_or.fetch_or(hash, std::memory_order_relaxed);
+  info->max_probe_length.store(
+      std::max(info->max_probe_length.load(std::memory_order_relaxed),
+               probe_length),
+      std::memory_order_relaxed);
+  info->total_probe_length.fetch_add(probe_length, std::memory_order_relaxed);
+  info->size.fetch_add(1, std::memory_order_relaxed);
+}
+
+void SetHashtablezEnabled(bool enabled) {
+  g_hashtablez_enabled.store(enabled, std::memory_order_release);
+}
+
+void SetHashtablezSampleParameter(int32_t rate) {
+  if (rate > 0) {
+    g_hashtablez_sample_parameter.store(rate, std::memory_order_release);
+  } else {
+    ABSL_RAW_LOG(ERROR, "Invalid hashtablez sample rate: %lld",
+                 static_cast<long long>(rate));  // NOLINT(runtime/int)
+  }
+}
+
+void SetHashtablezMaxSamples(int32_t max) {
+  if (max > 0) {
+    g_hashtablez_max_samples.store(max, std::memory_order_release);
+  } else {
+    ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: %lld",
+                 static_cast<long long>(max));  // NOLINT(runtime/int)
+  }
+}
+
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
new file mode 100644
index 0000000..a308e78
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -0,0 +1,288 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: hashtablez_sampler.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for a low level library to sample hashtables
+// and collect runtime statistics about them.
+//
+// `HashtablezSampler` controls the lifecycle of `HashtablezInfo` objects which
+// store information about a single sample.
+//
+// `Record*` methods store information into samples.
+// `Sample()` and `Unsample()` make use of a single global sampler with
+// properties controlled by the flags hashtablez_enabled,
+// hashtablez_sample_rate, and hashtablez_max_samples.
+//
+// WARNING
+//
+// Using this sampling API may cause sampled Swiss tables to use the global
+// allocator (operator `new`) in addition to any custom allocator.  If you
+// are using a table in an unusual circumstance where allocation or calling a
+// linux syscall is unacceptable, this could interfere.
+//
+// This utility is internal-only. Use at your own risk.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
+#define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+namespace container_internal {
+
+// Stores information about a sampled hashtable.  All mutations to this *must*
+// be made through `Record*` functions below.  All reads from this *must* only
+// occur in the callback to `HashtablezSampler::Iterate`.
+struct HashtablezInfo {
+  // Constructs the object but does not fill in any fields.
+  HashtablezInfo();
+  ~HashtablezInfo();
+  HashtablezInfo(const HashtablezInfo&) = delete;
+  HashtablezInfo& operator=(const HashtablezInfo&) = delete;
+
+  // Puts the object into a clean state, fills in the logically `const` members,
+  // blocking for any readers that are currently sampling the object.
+  void PrepareForSampling() EXCLUSIVE_LOCKS_REQUIRED(init_mu);
+
+  // These fields are mutated by the various Record* APIs and need to be
+  // thread-safe.
+  std::atomic<size_t> capacity;
+  std::atomic<size_t> size;
+  std::atomic<size_t> num_erases;
+  std::atomic<size_t> max_probe_length;
+  std::atomic<size_t> total_probe_length;
+  std::atomic<size_t> hashes_bitwise_or;
+  std::atomic<size_t> hashes_bitwise_and;
+
+  // `HashtablezSampler` maintains intrusive linked lists for all samples.  See
+  // comments on `HashtablezSampler::all_` for details on these.  `init_mu`
+  // guards the ability to restore the sample to a pristine state.  This
+  // prevents races with sampling and resurrecting an object.
+  absl::Mutex init_mu;
+  HashtablezInfo* next;
+  HashtablezInfo* dead GUARDED_BY(init_mu);
+
+  // All of the fields below are set by `PrepareForSampling`, they must not be
+  // mutated in `Record*` functions.  They are logically `const` in that sense.
+  // These are guarded by init_mu, but that is not externalized to clients, who
+  // can only read them during `HashtablezSampler::Iterate` which will hold the
+  // lock.
+  static constexpr int kMaxStackDepth = 64;
+  absl::Time create_time;
+  int32_t depth;
+  void* stack[kMaxStackDepth];
+};
+
+inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
+#if SWISSTABLE_HAVE_SSE2
+  total_probe_length /= 16;
+#else
+  total_probe_length /= 8;
+#endif
+  info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
+  info->num_erases.store(0, std::memory_order_relaxed);
+}
+
+inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
+                                     size_t capacity) {
+  info->size.store(size, std::memory_order_relaxed);
+  info->capacity.store(capacity, std::memory_order_relaxed);
+  if (size == 0) {
+    // This is a clear, reset the total/num_erases too.
+    RecordRehashSlow(info, 0);
+  }
+}
+
+void RecordInsertSlow(HashtablezInfo* info, size_t hash,
+                      size_t distance_from_desired);
+
+inline void RecordEraseSlow(HashtablezInfo* info) {
+  info->size.fetch_sub(1, std::memory_order_relaxed);
+  info->num_erases.fetch_add(1, std::memory_order_relaxed);
+}
+
+HashtablezInfo* SampleSlow(int64_t* next_sample);
+void UnsampleSlow(HashtablezInfo* info);
+
+class HashtablezInfoHandle {
+ public:
+  explicit HashtablezInfoHandle() : info_(nullptr) {}
+  explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {}
+  ~HashtablezInfoHandle() {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    UnsampleSlow(info_);
+  }
+
+  HashtablezInfoHandle(const HashtablezInfoHandle&) = delete;
+  HashtablezInfoHandle& operator=(const HashtablezInfoHandle&) = delete;
+
+  HashtablezInfoHandle(HashtablezInfoHandle&& o) noexcept
+      : info_(absl::exchange(o.info_, nullptr)) {}
+  HashtablezInfoHandle& operator=(HashtablezInfoHandle&& o) noexcept {
+    if (ABSL_PREDICT_FALSE(info_ != nullptr)) {
+      UnsampleSlow(info_);
+    }
+    info_ = absl::exchange(o.info_, nullptr);
+    return *this;
+  }
+
+  inline void RecordStorageChanged(size_t size, size_t capacity) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordStorageChangedSlow(info_, size, capacity);
+  }
+
+  inline void RecordRehash(size_t total_probe_length) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordRehashSlow(info_, total_probe_length);
+  }
+
+  inline void RecordInsert(size_t hash, size_t distance_from_desired) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordInsertSlow(info_, hash, distance_from_desired);
+  }
+
+  inline void RecordErase() {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordEraseSlow(info_);
+  }
+
+  friend inline void swap(HashtablezInfoHandle& lhs,
+                          HashtablezInfoHandle& rhs) {
+    std::swap(lhs.info_, rhs.info_);
+  }
+
+ private:
+  friend class HashtablezInfoHandlePeer;
+  HashtablezInfo* info_;
+};
+
+#if ABSL_PER_THREAD_TLS == 1
+extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
+#endif  // ABSL_PER_THREAD_TLS
+
+// Returns an RAII sampling handle that manages registration and unregistation
+// with the global sampler.
+inline HashtablezInfoHandle Sample() {
+#if ABSL_PER_THREAD_TLS == 0
+  static auto* mu = new absl::Mutex;
+  static int64_t global_next_sample = 0;
+  absl::MutexLock l(mu);
+#endif  // !ABSL_HAVE_THREAD_LOCAL
+
+  if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) {
+    return HashtablezInfoHandle(nullptr);
+  }
+  return HashtablezInfoHandle(SampleSlow(&global_next_sample));
+}
+
+// Holds samples and their associated stack traces with a soft limit of
+// `SetHashtablezMaxSamples()`.
+//
+// Thread safe.
+class HashtablezSampler {
+ public:
+  // Returns a global Sampler.
+  static HashtablezSampler& Global();
+
+  HashtablezSampler();
+  ~HashtablezSampler();
+
+  // Registers for sampling.  Returns an opaque registration info.
+  HashtablezInfo* Register();
+
+  // Unregisters the sample.
+  void Unregister(HashtablezInfo* sample);
+
+  // The dispose callback will be called on all samples the moment they are
+  // being unregistered. Only affects samples that are unregistered after the
+  // callback has been set.
+  // Returns the previous callback.
+  using DisposeCallback = void (*)(const HashtablezInfo&);
+  DisposeCallback SetDisposeCallback(DisposeCallback f);
+
+  // Iterates over all the registered `StackInfo`s.  Returning the number of
+  // samples that have been dropped.
+  int64_t Iterate(const std::function<void(const HashtablezInfo& stack)>& f);
+
+ private:
+  void PushNew(HashtablezInfo* sample);
+  void PushDead(HashtablezInfo* sample);
+  HashtablezInfo* PopDead();
+
+  std::atomic<size_t> dropped_samples_;
+  std::atomic<size_t> size_estimate_;
+
+  // Intrusive lock free linked lists for tracking samples.
+  //
+  // `all_` records all samples (they are never removed from this list) and is
+  // terminated with a `nullptr`.
+  //
+  // `graveyard_.dead` is a circular linked list.  When it is empty,
+  // `graveyard_.dead == &graveyard`.  The list is circular so that
+  // every item on it (even the last) has a non-null dead pointer.  This allows
+  // `Iterate` to determine if a given sample is live or dead using only
+  // information on the sample itself.
+  //
+  // For example, nodes [A, B, C, D, E] with [A, C, E] alive and [B, D] dead
+  // looks like this (G is the Graveyard):
+  //
+  //           +---+    +---+    +---+    +---+    +---+
+  //    all -->| A |--->| B |--->| C |--->| D |--->| E |
+  //           |   |    |   |    |   |    |   |    |   |
+  //   +---+   |   | +->|   |-+  |   | +->|   |-+  |   |
+  //   | G |   +---+ |  +---+ |  +---+ |  +---+ |  +---+
+  //   |   |         |        |        |        |
+  //   |   | --------+        +--------+        |
+  //   +---+                                    |
+  //     ^                                      |
+  //     +--------------------------------------+
+  //
+  std::atomic<HashtablezInfo*> all_;
+  HashtablezInfo graveyard_;
+
+  std::atomic<DisposeCallback> dispose_;
+};
+
+// Enables or disables sampling for Swiss tables.
+void SetHashtablezEnabled(bool enabled);
+
+// Sets the rate at which Swiss tables will be sampled.
+void SetHashtablezSampleParameter(int32_t rate);
+
+// Sets a soft max for the number of samples that will be kept.
+void SetHashtablezMaxSamples(int32_t max);
+
+// Configuration override.
+// This allows process-wide sampling without depending on order of
+// initialization of static storage duration objects.
+// The definition of this constant is weak, which allows us to inject a
+// different value for it at link time.
+extern "C" const bool kAbslContainerInternalSampleEverything;
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
diff --git a/absl/container/internal/hashtablez_sampler_force_weak_definition.cc b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
new file mode 100644
index 0000000..4ca6ffd
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
@@ -0,0 +1,27 @@
+// 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.
+
+#include "absl/container/internal/hashtablez_sampler.h"
+
+#include "absl/base/attributes.h"
+
+namespace absl {
+namespace container_internal {
+
+// See hashtablez_sampler.h for details.
+extern "C" ABSL_ATTRIBUTE_WEAK const bool
+    kAbslContainerInternalSampleEverything = false;
+
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
new file mode 100644
index 0000000..d2435ed
--- /dev/null
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -0,0 +1,355 @@
+// 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.
+
+#include "absl/container/internal/hashtablez_sampler.h"
+
+#include <atomic>
+#include <limits>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/synchronization/blocking_counter.h"
+#include "absl/synchronization/internal/thread_pool.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+#if SWISSTABLE_HAVE_SSE2
+constexpr int kProbeLength = 16;
+#else
+constexpr int kProbeLength = 8;
+#endif
+
+namespace absl {
+namespace container_internal {
+class HashtablezInfoHandlePeer {
+ public:
+  static bool IsSampled(const HashtablezInfoHandle& h) {
+    return h.info_ != nullptr;
+  }
+
+  static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }
+};
+
+namespace {
+using ::absl::synchronization_internal::ThreadPool;
+using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
+
+std::vector<size_t> GetSizes(HashtablezSampler* s) {
+  std::vector<size_t> res;
+  s->Iterate([&](const HashtablezInfo& info) {
+    res.push_back(info.size.load(std::memory_order_acquire));
+  });
+  return res;
+}
+
+HashtablezInfo* Register(HashtablezSampler* s, size_t size) {
+  auto* info = s->Register();
+  assert(info != nullptr);
+  info->size.store(size);
+  return info;
+}
+
+TEST(HashtablezInfoTest, PrepareForSampling) {
+  absl::Time test_start = absl::Now();
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+
+  EXPECT_EQ(info.capacity.load(), 0);
+  EXPECT_EQ(info.size.load(), 0);
+  EXPECT_EQ(info.num_erases.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);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
+  EXPECT_GE(info.create_time, test_start);
+
+  info.capacity.store(1, std::memory_order_relaxed);
+  info.size.store(1, std::memory_order_relaxed);
+  info.num_erases.store(1, std::memory_order_relaxed);
+  info.max_probe_length.store(1, std::memory_order_relaxed);
+  info.total_probe_length.store(1, std::memory_order_relaxed);
+  info.hashes_bitwise_or.store(1, std::memory_order_relaxed);
+  info.hashes_bitwise_and.store(1, std::memory_order_relaxed);
+  info.create_time = test_start - absl::Hours(20);
+
+  info.PrepareForSampling();
+  EXPECT_EQ(info.capacity.load(), 0);
+  EXPECT_EQ(info.size.load(), 0);
+  EXPECT_EQ(info.num_erases.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);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
+  EXPECT_GE(info.create_time, test_start);
+}
+
+TEST(HashtablezInfoTest, RecordStorageChanged) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  RecordStorageChangedSlow(&info, 17, 47);
+  EXPECT_EQ(info.size.load(), 17);
+  EXPECT_EQ(info.capacity.load(), 47);
+  RecordStorageChangedSlow(&info, 20, 20);
+  EXPECT_EQ(info.size.load(), 20);
+  EXPECT_EQ(info.capacity.load(), 20);
+}
+
+TEST(HashtablezInfoTest, RecordInsert) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  EXPECT_EQ(info.max_probe_length.load(), 0);
+  RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
+  EXPECT_EQ(info.max_probe_length.load(), 6);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000FF00);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x0000FF00);
+  RecordInsertSlow(&info, 0x000FF000, 4 * kProbeLength);
+  EXPECT_EQ(info.max_probe_length.load(), 6);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000F000);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x000FFF00);
+  RecordInsertSlow(&info, 0x00FF0000, 12 * kProbeLength);
+  EXPECT_EQ(info.max_probe_length.load(), 12);
+  EXPECT_EQ(info.hashes_bitwise_and.load(), 0x00000000);
+  EXPECT_EQ(info.hashes_bitwise_or.load(), 0x00FFFF00);
+}
+
+TEST(HashtablezInfoTest, RecordErase) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.size.load(), 0);
+  RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 1);
+  RecordEraseSlow(&info);
+  EXPECT_EQ(info.size.load(), 0);
+  EXPECT_EQ(info.num_erases.load(), 1);
+}
+
+TEST(HashtablezInfoTest, RecordRehash) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  RecordInsertSlow(&info, 0x1, 0);
+  RecordInsertSlow(&info, 0x2, kProbeLength);
+  RecordInsertSlow(&info, 0x4, kProbeLength);
+  RecordInsertSlow(&info, 0x8, 2 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 4);
+  EXPECT_EQ(info.total_probe_length.load(), 4);
+
+  RecordEraseSlow(&info);
+  RecordEraseSlow(&info);
+  EXPECT_EQ(info.size.load(), 2);
+  EXPECT_EQ(info.total_probe_length.load(), 4);
+  EXPECT_EQ(info.num_erases.load(), 2);
+
+  RecordRehashSlow(&info, 3 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 2);
+  EXPECT_EQ(info.total_probe_length.load(), 3);
+  EXPECT_EQ(info.num_erases.load(), 0);
+}
+
+TEST(HashtablezSamplerTest, SmallSampleParameter) {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);
+
+  for (int i = 0; i < 1000; ++i) {
+    int64_t next_sample = 0;
+    HashtablezInfo* sample = SampleSlow(&next_sample);
+    EXPECT_GT(next_sample, 0);
+    EXPECT_NE(sample, nullptr);
+    UnsampleSlow(sample);
+  }
+}
+
+TEST(HashtablezSamplerTest, LargeSampleParameter) {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max());
+
+  for (int i = 0; i < 1000; ++i) {
+    int64_t next_sample = 0;
+    HashtablezInfo* sample = SampleSlow(&next_sample);
+    EXPECT_GT(next_sample, 0);
+    EXPECT_NE(sample, nullptr);
+    UnsampleSlow(sample);
+  }
+}
+
+TEST(HashtablezSamplerTest, Sample) {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);
+  int64_t num_sampled = 0;
+  int64_t total = 0;
+  double sample_rate;
+  for (int i = 0; i < 1000000; ++i) {
+    HashtablezInfoHandle h = Sample();
+    ++total;
+    if (HashtablezInfoHandlePeer::IsSampled(h)) {
+      ++num_sampled;
+    }
+    sample_rate = static_cast<double>(num_sampled) / total;
+    if (0.005 < sample_rate && sample_rate < 0.015) break;
+  }
+  EXPECT_NEAR(sample_rate, 0.01, 0.005);
+}
+
+TEST(HashtablezSamplerTest, Handle) {
+  auto& sampler = HashtablezSampler::Global();
+  HashtablezInfoHandle h(sampler.Register());
+  auto* info = HashtablezInfoHandlePeer::GetInfo(&h);
+  info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed);
+
+  bool found = false;
+  sampler.Iterate([&](const HashtablezInfo& h) {
+    if (&h == info) {
+      EXPECT_EQ(h.hashes_bitwise_and.load(), 0x12345678);
+      found = true;
+    }
+  });
+  EXPECT_TRUE(found);
+
+  h = HashtablezInfoHandle();
+  found = false;
+  sampler.Iterate([&](const HashtablezInfo& h) {
+    if (&h == info) {
+      // this will only happen if some other thread has resurrected the info
+      // the old handle was using.
+      if (h.hashes_bitwise_and.load() == 0x12345678) {
+        found = true;
+      }
+    }
+  });
+  EXPECT_FALSE(found);
+}
+
+TEST(HashtablezSamplerTest, Registration) {
+  HashtablezSampler sampler;
+  auto* info1 = Register(&sampler, 1);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1));
+
+  auto* info2 = Register(&sampler, 2);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1, 2));
+  info1->size.store(3);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(3, 2));
+
+  sampler.Unregister(info1);
+  sampler.Unregister(info2);
+}
+
+TEST(HashtablezSamplerTest, Unregistration) {
+  HashtablezSampler sampler;
+  std::vector<HashtablezInfo*> infos;
+  for (size_t i = 0; i < 3; ++i) {
+    infos.push_back(Register(&sampler, i));
+  }
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 1, 2));
+
+  sampler.Unregister(infos[1]);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2));
+
+  infos.push_back(Register(&sampler, 3));
+  infos.push_back(Register(&sampler, 4));
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 3, 4));
+  sampler.Unregister(infos[3]);
+  EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 4));
+
+  sampler.Unregister(infos[0]);
+  sampler.Unregister(infos[2]);
+  sampler.Unregister(infos[4]);
+  EXPECT_THAT(GetSizes(&sampler), IsEmpty());
+}
+
+TEST(HashtablezSamplerTest, MultiThreaded) {
+  HashtablezSampler sampler;
+  Notification stop;
+  ThreadPool pool(10);
+
+  for (int i = 0; i < 10; ++i) {
+    pool.Schedule([&sampler, &stop]() {
+      std::random_device rd;
+      std::mt19937 gen(rd());
+
+      std::vector<HashtablezInfo*> infoz;
+      while (!stop.HasBeenNotified()) {
+        if (infoz.empty()) {
+          infoz.push_back(sampler.Register());
+        }
+        switch (std::uniform_int_distribution<>(0, 2)(gen)) {
+          case 0: {
+            infoz.push_back(sampler.Register());
+            break;
+          }
+          case 1: {
+            size_t p =
+                std::uniform_int_distribution<>(0, infoz.size() - 1)(gen);
+            HashtablezInfo* info = infoz[p];
+            infoz[p] = infoz.back();
+            infoz.pop_back();
+            sampler.Unregister(info);
+            break;
+          }
+          case 2: {
+            absl::Duration oldest = absl::ZeroDuration();
+            sampler.Iterate([&](const HashtablezInfo& info) {
+              oldest = std::max(oldest, absl::Now() - info.create_time);
+            });
+            ASSERT_GE(oldest, absl::ZeroDuration());
+            break;
+          }
+        }
+      }
+    });
+  }
+  // The threads will hammer away.  Give it a little bit of time for tsan to
+  // spot errors.
+  absl::SleepFor(absl::Seconds(3));
+  stop.Notify();
+}
+
+TEST(HashtablezSamplerTest, Callback) {
+  HashtablezSampler sampler;
+
+  auto* info1 = Register(&sampler, 1);
+  auto* info2 = Register(&sampler, 2);
+
+  static const HashtablezInfo* expected;
+
+  auto callback = [](const HashtablezInfo& info) {
+    // We can't use `info` outside of this callback because the object will be
+    // disposed as soon as we return from here.
+    EXPECT_EQ(&info, expected);
+  };
+
+  // Set the callback.
+  EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr);
+  expected = info1;
+  sampler.Unregister(info1);
+
+  // Unset the callback.
+  EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr));
+  expected = nullptr;  // no more calls.
+  sampler.Unregister(info2);
+}
+
+}  // namespace
+}  // namespace container_internal
+}  // namespace absl
diff --git a/absl/container/internal/have_sse.h b/absl/container/internal/have_sse.h
new file mode 100644
index 0000000..4341441
--- /dev/null
+++ b/absl/container/internal/have_sse.h
@@ -0,0 +1,49 @@
+// 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.
+//
+// Shared config probing for SSE instructions used in Swiss tables.
+#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
+#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
+
+#ifndef SWISSTABLE_HAVE_SSE2
+#if defined(__SSE2__) ||  \
+    (defined(_MSC_VER) && \
+     (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
+#define SWISSTABLE_HAVE_SSE2 1
+#else
+#define SWISSTABLE_HAVE_SSE2 0
+#endif
+#endif
+
+#ifndef SWISSTABLE_HAVE_SSSE3
+#ifdef __SSSE3__
+#define SWISSTABLE_HAVE_SSSE3 1
+#else
+#define SWISSTABLE_HAVE_SSSE3 0
+#endif
+#endif
+
+#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
+#error "Bad configuration!"
+#endif
+
+#if SWISSTABLE_HAVE_SSE2
+#include <emmintrin.h>
+#endif
+
+#if SWISSTABLE_HAVE_SSSE3
+#include <tmmintrin.h>
+#endif
+
+#endif  // ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
new file mode 100644
index 0000000..24059d9
--- /dev/null
+++ b/absl/container/internal/inlined_vector.h
@@ -0,0 +1,126 @@
+// 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_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+
+#include <cstddef>
+#include <iterator>
+#include <memory>
+
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace inlined_vector_internal {
+
+template <typename InlinedVector>
+class Storage;
+
+template <template <typename, size_t, typename> class InlinedVector, typename T,
+          size_t N, typename A>
+class Storage<InlinedVector<T, N, A>> {
+ public:
+  using allocator_type = A;
+  using value_type = typename allocator_type::value_type;
+  using pointer = typename allocator_type::pointer;
+  using const_pointer = typename allocator_type::const_pointer;
+  using reference = typename allocator_type::reference;
+  using const_reference = typename allocator_type::const_reference;
+  using rvalue_reference = typename allocator_type::value_type&&;
+  using size_type = typename allocator_type::size_type;
+  using difference_type = typename allocator_type::difference_type;
+  using iterator = pointer;
+  using const_iterator = const_pointer;
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+  explicit Storage(const allocator_type& a) : allocator_and_tag_(a) {}
+
+  // TODO(johnsoncj): Make the below types and members private after migration
+
+  // Holds whether the vector is allocated or not in the lowest bit and the size
+  // in the high bits:
+  //   `size_ = (size << 1) | is_allocated;`
+  class Tag {
+    size_type size_;
+
+   public:
+    Tag() : size_(0) {}
+    size_type size() const { return size_ / 2; }
+    void add_size(size_type n) { size_ += n * 2; }
+    void set_inline_size(size_type n) { size_ = n * 2; }
+    void set_allocated_size(size_type n) { size_ = (n * 2) + 1; }
+    bool allocated() const { return size_ % 2; }
+  };
+
+  // Derives from `allocator_type` to use the empty base class optimization.
+  // If the `allocator_type` is stateless, we can store our instance for free.
+  class AllocatorAndTag : private allocator_type {
+    Tag tag_;
+
+   public:
+    explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
+    Tag& tag() { return tag_; }
+    const Tag& tag() const { return tag_; }
+    allocator_type& allocator() { return *this; }
+    const allocator_type& allocator() const { return *this; }
+  };
+
+  class Allocation {
+    size_type capacity_;
+    pointer buffer_;
+
+   public:
+    Allocation(allocator_type& a, size_type capacity)
+        : capacity_(capacity), buffer_(Create(a, capacity)) {}
+    void Dealloc(allocator_type& a) {
+      std::allocator_traits<allocator_type>::deallocate(a, buffer_, capacity_);
+    }
+    size_type capacity() const { return capacity_; }
+    const_pointer buffer() const { return buffer_; }
+    pointer buffer() { return buffer_; }
+    static pointer Create(allocator_type& a, size_type n) {
+      return std::allocator_traits<allocator_type>::allocate(a, n);
+    }
+  };
+
+  // Stores either the inlined or allocated representation
+  union Rep {
+    using ValueTypeBuffer =
+        absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
+    using AllocationBuffer =
+        absl::aligned_storage_t<sizeof(Allocation), alignof(Allocation)>;
+
+    // Structs wrap the buffers to perform indirection that solves a bizarre
+    // compilation error on Visual Studio (all known versions).
+    struct InlinedRep {
+      ValueTypeBuffer inlined[N];
+    };
+
+    struct AllocatedRep {
+      AllocationBuffer allocation;
+    };
+
+    InlinedRep inlined_storage;
+    AllocatedRep allocation_storage;
+  };
+
+  AllocatorAndTag allocator_and_tag_;
+  Rep rep_;
+};
+
+}  // namespace inlined_vector_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index 676c7d6..bbdde50 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -232,13 +232,17 @@
 template <class T, size_t N>
 struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
 
+// Note: workaround for https://gcc.gnu.org/PR88115
 template <class T>
-struct AlignOf : NotAligned<T>, std::integral_constant<size_t, alignof(T)> {};
+struct AlignOf : NotAligned<T> {
+  static constexpr size_t value = alignof(T);
+};
 
 template <class T, size_t N>
-struct AlignOf<Aligned<T, N>> : std::integral_constant<size_t, N> {
+struct AlignOf<Aligned<T, N>> {
   static_assert(N % alignof(T) == 0,
                 "Custom alignment can't be lower than the type's alignment");
+  static constexpr size_t value = N;
 };
 
 // Does `Ts...` contain `T`?
@@ -249,8 +253,10 @@
 using CopyConst =
     typename std::conditional<std::is_const<From>::value, const To, To>::type;
 
+// Note: We're not qualifying this with absl:: because it doesn't compile under
+// MSVC.
 template <class T>
-using SliceType = absl::Span<T>;
+using SliceType = Span<T>;
 
 // This namespace contains no types. It prevents functions defined in it from
 // being found by ADL.
@@ -290,7 +296,7 @@
 #ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
   demangled = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
 #endif
-  if (status == 0 && demangled != nullptr) {  // Demangling succeeeded.
+  if (status == 0 && demangled != nullptr) {  // Demangling succeeded.
     absl::StrAppend(&out, "<", demangled, ">");
     free(demangled);
   } else {
@@ -396,7 +402,7 @@
     static_assert(N < NumOffsets, "Index out of bounds");
     return adl_barrier::Align(
         Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1],
-        ElementAlignment<N>());
+        ElementAlignment<N>::value);
   }
 
   // Offset in bytes of the array with the specified element type. There must
@@ -445,7 +451,7 @@
     return Size<ElementIndex<T>()>();
   }
 
-    // The number of elements of all arrays for which they are known.
+  // The number of elements of all arrays for which they are known.
   constexpr std::array<size_t, NumSizes> Sizes() const {
     return {{Size<SizeSeq>()...}};
   }
@@ -610,7 +616,7 @@
 #ifdef ADDRESS_SANITIZER
     PoisonPadding<Char, N - 1>(p);
     // The `if` is an optimization. It doesn't affect the observable behaviour.
-    if (ElementAlignment<N - 1>() % ElementAlignment<N>()) {
+    if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
       size_t start =
           Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1];
       ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
@@ -637,7 +643,8 @@
   std::string DebugString() const {
     const auto offsets = Offsets();
     const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>()...};
-    const std::string types[] = {adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
+    const std::string types[] = {
+        adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
     std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")");
     for (size_t i = 0; i != NumOffsets - 1; ++i) {
       absl::StrAppend(&res, "[", size_[i], "]; @", offsets[i + 1], types[i + 1],
@@ -690,7 +697,7 @@
   //
   // It's allowed to pass fewer array sizes than the number of arrays. E.g.,
   // if all you need is to the offset of the second array, you only need to
-  // pass one argument -- the number of elements in the first arrays.
+  // pass one argument -- the number of elements in the first array.
   //
   //   // int[3] followed by 4 bytes of padding and an unknown number of
   //   // doubles.
diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc
index f35157a..33b72bd 100644
--- a/absl/container/internal/layout_test.cc
+++ b/absl/container/internal/layout_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -45,7 +45,25 @@
   return val;
 }
 
-using Int128 = int64_t[2];
+// Helper classes to test different size and alignments.
+struct alignas(8) Int128 {
+  uint64_t a, b;
+  friend bool operator==(Int128 lhs, Int128 rhs) {
+    return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
+  }
+
+  static std::string Name() {
+    return internal_layout::adl_barrier::TypeName<Int128>();
+  }
+};
+
+// int64_t is *not* 8-byte aligned on all platforms!
+struct alignas(8) Int64 {
+  int64_t a;
+  friend bool operator==(Int64 lhs, Int64 rhs) {
+    return lhs.a == rhs.a;
+  }
+};
 
 // Properties of types that this test relies on.
 static_assert(sizeof(int8_t) == 1, "");
@@ -54,6 +72,8 @@
 static_assert(alignof(int16_t) == 2, "");
 static_assert(sizeof(int32_t) == 4, "");
 static_assert(alignof(int32_t) == 4, "");
+static_assert(sizeof(Int64) == 8, "");
+static_assert(alignof(Int64) == 8, "");
 static_assert(sizeof(Int128) == 16, "");
 static_assert(alignof(Int128) == 8, "");
 
@@ -1271,14 +1291,14 @@
 TEST(Layout, Alignment) {
   static_assert(Layout<int8_t>::Alignment() == 1, "");
   static_assert(Layout<int32_t>::Alignment() == 4, "");
-  static_assert(Layout<int64_t>::Alignment() == 8, "");
+  static_assert(Layout<Int64>::Alignment() == 8, "");
   static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
-  static_assert(Layout<int8_t, int32_t, int64_t>::Alignment() == 8, "");
-  static_assert(Layout<int8_t, int64_t, int32_t>::Alignment() == 8, "");
-  static_assert(Layout<int32_t, int8_t, int64_t>::Alignment() == 8, "");
-  static_assert(Layout<int32_t, int64_t, int8_t>::Alignment() == 8, "");
-  static_assert(Layout<int64_t, int8_t, int32_t>::Alignment() == 8, "");
-  static_assert(Layout<int64_t, int32_t, int8_t>::Alignment() == 8, "");
+  static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
+  static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
+  static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
+  static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
+  static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
+  static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
 }
 
 TEST(Layout, ConstexprPartial) {
@@ -1313,7 +1333,7 @@
 }
 
 TEST(Layout, PoisonPadding) {
-  using L = Layout<int8_t, int64_t, int32_t, Int128>;
+  using L = Layout<int8_t, Int64, int32_t, Int128>;
 
   constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
   {
@@ -1361,12 +1381,6 @@
 }
 
 TEST(Layout, DebugString) {
-  const std::string int64_type =
-#ifdef _MSC_VER
-  "__int64";
-#else   // _MSC_VER
-  std::is_same<int64_t, long long>::value ? "long long" : "long";  // NOLINT
-#endif  // _MSC_VER
   {
     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
     EXPECT_EQ("@0<signed char>(1)", x.DebugString());
@@ -1384,24 +1398,24 @@
     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<" +
-            int64_type + " [2]>(16)",
+        "@16" +
+            Int128::Name() + "(16)",
         x.DebugString());
   }
   {
     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<" +
-            int64_type + " [2]>(16)[4]",
+        "@16" +
+            Int128::Name() + "(16)[4]",
         x.DebugString());
   }
   {
     constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
-        "@16<" +
-            int64_type + " [2]>(16)[4]",
+        "@16" +
+            Int128::Name() + "(16)[4]",
         x.DebugString());
   }
 }
@@ -1528,8 +1542,7 @@
   const char* c_str() const {
     // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
     // The argument in Partial(1) specifies that we have size_t[1] in front of
-    // the
-    // characters.
+    // the characters.
     return L::Partial(1).Pointer<char>(p_.get());
   }
 
diff --git a/absl/container/internal/node_hash_policy.h b/absl/container/internal/node_hash_policy.h
index 065e700..19b4fc0 100644
--- a/absl/container/internal/node_hash_policy.h
+++ b/absl/container/internal/node_hash_policy.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/node_hash_policy_test.cc b/absl/container/internal/node_hash_policy_test.cc
index 43d287e..f1d3ec3 100644
--- a/absl/container/internal/node_hash_policy_test.cc
+++ b/absl/container/internal/node_hash_policy_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 1edc007..0014cf8 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -39,11 +39,14 @@
   using MappedConstReference = decltype(P::value(
       std::addressof(std::declval<typename raw_hash_map::const_reference>())));
 
+  using KeyArgImpl =
+      KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
+
  public:
   using key_type = typename Policy::key_type;
   using mapped_type = typename Policy::mapped_type;
-  template <typename K>
-  using key_arg = typename raw_hash_map::raw_hash_set::template key_arg<K>;
+  template <class K>
+  using key_arg = typename KeyArgImpl::template type<K, key_type>;
 
   static_assert(!std::is_reference<key_type>::value, "");
   // TODO(alkis): remove this assertion and verify that reference mapped_type is
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 1015312..ac2d10a 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -14,6 +14,7 @@
 
 #include "absl/container/internal/raw_hash_set.h"
 
+#include <atomic>
 #include <cstddef>
 
 #include "absl/base/config.h"
@@ -29,7 +30,7 @@
   static thread_local size_t counter = 0;
   size_t value = ++counter;
 #else   // ABSL_HAVE_THREAD_LOCAL
-  static std::atomic<size_t> counter;
+  static std::atomic<size_t> counter(0);
   size_t value = counter.fetch_add(1, std::memory_order_relaxed);
 #endif  // ABSL_HAVE_THREAD_LOCAL
   return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 70da90f..85e3334 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -91,30 +91,6 @@
 #ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
 #define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
 
-#ifndef SWISSTABLE_HAVE_SSE2
-#ifdef __SSE2__
-#define SWISSTABLE_HAVE_SSE2 1
-#else
-#define SWISSTABLE_HAVE_SSE2 0
-#endif
-#endif
-
-#ifndef SWISSTABLE_HAVE_SSSE3
-#ifdef __SSSE3__
-#define SWISSTABLE_HAVE_SSSE3 1
-#else
-#define SWISSTABLE_HAVE_SSSE3 0
-#endif
-#endif
-
-#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
-#error "Bad configuration!"
-#endif
-
-#if SWISSTABLE_HAVE_SSE2
-#include <x86intrin.h>
-#endif
-
 #include <algorithm>
 #include <cmath>
 #include <cstdint>
@@ -129,14 +105,16 @@
 #include "absl/base/internal/bits.h"
 #include "absl/base/internal/endian.h"
 #include "absl/base/port.h"
+#include "absl/container/internal/common.h"
 #include "absl/container/internal/compressed_tuple.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_policy_traits.h"
 #include "absl/container/internal/hashtable_debug_hooks.h"
+#include "absl/container/internal/hashtablez_sampler.h"
+#include "absl/container/internal/have_sse.h"
 #include "absl/container/internal/layout.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
-#include "absl/types/optional.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
@@ -187,12 +165,6 @@
                       std::declval<Ts>()...))>,
     Policy, Hash, Eq, Ts...> : std::true_type {};
 
-template <class, class = void>
-struct IsTransparent : std::false_type {};
-template <class T>
-struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
-    : std::true_type {};
-
 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
 template <class T>
 constexpr bool IsNoThrowSwappable() {
@@ -202,14 +174,17 @@
 
 template <typename T>
 int TrailingZeros(T x) {
-  return sizeof(T) == 8 ? base_internal::CountTrailingZerosNonZero64(x)
-                        : base_internal::CountTrailingZerosNonZero32(x);
+  return sizeof(T) == 8 ? base_internal::CountTrailingZerosNonZero64(
+                              static_cast<uint64_t>(x))
+                        : base_internal::CountTrailingZerosNonZero32(
+                              static_cast<uint32_t>(x));
 }
 
 template <typename T>
 int LeadingZeros(T x) {
-  return sizeof(T) == 8 ? base_internal::CountLeadingZeros64(x)
-                        : base_internal::CountLeadingZeros32(x);
+  return sizeof(T) == 8
+             ? base_internal::CountLeadingZeros64(static_cast<uint64_t>(x))
+             : base_internal::CountLeadingZeros32(static_cast<uint32_t>(x));
 }
 
 // An abstraction over a bitmask. It provides an easy way to iterate through the
@@ -337,10 +312,27 @@
 inline bool IsEmptyOrDeleted(ctrl_t c) { return c < kSentinel; }
 
 #if SWISSTABLE_HAVE_SSE2
-struct Group {
+
+// https://github.com/abseil/abseil-cpp/issues/209
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
+// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
+// Work around this by using the portable implementation of Group
+// when using -funsigned-char under GCC.
+inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
+#if defined(__GNUC__) && !defined(__clang__)
+  if (std::is_unsigned<char>::value) {
+    const __m128i mask = _mm_set1_epi8(0x80);
+    const __m128i diff = _mm_subs_epi8(b, a);
+    return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
+  }
+#endif
+  return _mm_cmpgt_epi8(a, b);
+}
+
+struct GroupSse2Impl {
   static constexpr size_t kWidth = 16;  // the number of slots per group
 
-  explicit Group(const ctrl_t* pos) {
+  explicit GroupSse2Impl(const ctrl_t* pos) {
     ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
   }
 
@@ -366,23 +358,24 @@
   BitMask<uint32_t, kWidth> MatchEmptyOrDeleted() const {
     auto special = _mm_set1_epi8(kSentinel);
     return BitMask<uint32_t, kWidth>(
-        _mm_movemask_epi8(_mm_cmpgt_epi8(special, ctrl)));
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)));
   }
 
   // Returns the number of trailing empty or deleted elements in the group.
   uint32_t CountLeadingEmptyOrDeleted() const {
     auto special = _mm_set1_epi8(kSentinel);
-    return TrailingZeros(_mm_movemask_epi8(_mm_cmpgt_epi8(special, ctrl)) + 1);
+    return TrailingZeros(
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1);
   }
 
   void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
-    auto msbs = _mm_set1_epi8(0x80);
+    auto msbs = _mm_set1_epi8(static_cast<char>(-128));
     auto x126 = _mm_set1_epi8(126);
 #if SWISSTABLE_HAVE_SSSE3
     auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
 #else
     auto zero = _mm_setzero_si128();
-    auto special_mask = _mm_cmpgt_epi8(zero, ctrl);
+    auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
     auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
 #endif
     _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
@@ -390,11 +383,13 @@
 
   __m128i ctrl;
 };
-#else
-struct Group {
+#endif  // SWISSTABLE_HAVE_SSE2
+
+struct GroupPortableImpl {
   static constexpr size_t kWidth = 8;
 
-  explicit Group(const ctrl_t* pos) : ctrl(little_endian::Load64(pos)) {}
+  explicit GroupPortableImpl(const ctrl_t* pos)
+      : ctrl(little_endian::Load64(pos)) {}
 
   BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
     // For the technique, see:
@@ -441,15 +436,17 @@
 
   uint64_t ctrl;
 };
-#endif  // SWISSTABLE_HAVE_SSE2
+
+#if SWISSTABLE_HAVE_SSE2
+using Group = GroupSse2Impl;
+#else
+using Group = GroupPortableImpl;
+#endif
 
 template <class Policy, class Hash, class Eq, class Alloc>
 class raw_hash_set;
 
-
-inline bool IsValidCapacity(size_t n) {
-  return ((n + 1) & n) == 0 && n >= Group::kWidth - 1;
-}
+inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
 
 // PRECONDITION:
 //   IsValidCapacity(capacity)
@@ -471,152 +468,32 @@
   ctrl[capacity] = kSentinel;
 }
 
-// Rounds up the capacity to the next power of 2 minus 1 and ensures it is
-// greater or equal to Group::kWidth - 1.
+// Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1.
 inline size_t NormalizeCapacity(size_t n) {
-  constexpr size_t kMinCapacity = Group::kWidth - 1;
-  return n <= kMinCapacity
-             ? kMinCapacity
-             : std::numeric_limits<size_t>::max() >> LeadingZeros(n);
+  return n ? ~size_t{} >> LeadingZeros(n) : 1;
 }
 
-// The node_handle concept from C++17.
-// We specialize node_handle for sets and maps. node_handle_base holds the
-// common API of both.
-template <typename Policy, typename Alloc>
-class node_handle_base {
- protected:
-  using PolicyTraits = hash_policy_traits<Policy>;
-  using slot_type = typename PolicyTraits::slot_type;
-
- public:
-  using allocator_type = Alloc;
-
-  constexpr node_handle_base() {}
-  node_handle_base(node_handle_base&& other) noexcept {
-    *this = std::move(other);
+// We use 7/8th as maximum load factor.
+// For 16-wide groups, that gives an average of two empty slots per group.
+inline size_t CapacityToGrowth(size_t capacity) {
+  assert(IsValidCapacity(capacity));
+  // `capacity*7/8`
+  if (Group::kWidth == 8 && capacity == 7) {
+    // x-x/8 does not work when x==7.
+    return 6;
   }
-  ~node_handle_base() { destroy(); }
-  node_handle_base& operator=(node_handle_base&& other) {
-    destroy();
-    if (!other.empty()) {
-      alloc_ = other.alloc_;
-      PolicyTraits::transfer(alloc(), slot(), other.slot());
-      other.reset();
-    }
-    return *this;
+  return capacity - capacity / 8;
+}
+// From desired "growth" to a lowerbound of the necessary capacity.
+// Might not be a valid one and required NormalizeCapacity().
+inline size_t GrowthToLowerboundCapacity(size_t growth) {
+  // `growth*8/7`
+  if (Group::kWidth == 8 && growth == 7) {
+    // x+(x-1)/7 does not work when x==7.
+    return 8;
   }
-
-  bool empty() const noexcept { return !alloc_; }
-  explicit operator bool() const noexcept { return !empty(); }
-  allocator_type get_allocator() const { return *alloc_; }
-
- protected:
-  template <typename, typename, typename, typename>
-  friend class raw_hash_set;
-
-  node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
-    PolicyTraits::transfer(alloc(), slot(), s);
-  }
-
-  void destroy() {
-    if (!empty()) {
-      PolicyTraits::destroy(alloc(), slot());
-      reset();
-    }
-  }
-
-  void reset() {
-    assert(alloc_.has_value());
-    alloc_ = absl::nullopt;
-  }
-
-  slot_type* slot() const {
-    assert(!empty());
-    return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
-  }
-  allocator_type* alloc() { return std::addressof(*alloc_); }
-
- private:
-  absl::optional<allocator_type> alloc_;
-  mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
-      slot_space_;
-};
-
-// For sets.
-template <typename Policy, typename Alloc, typename = void>
-class node_handle : public node_handle_base<Policy, Alloc> {
-  using Base = typename node_handle::node_handle_base;
-
- public:
-  using value_type = typename Base::PolicyTraits::value_type;
-
-  constexpr node_handle() {}
-
-  value_type& value() const {
-    return Base::PolicyTraits::element(this->slot());
-  }
-
- private:
-  template <typename, typename, typename, typename>
-  friend class raw_hash_set;
-
-  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
-};
-
-// For maps.
-template <typename Policy, typename Alloc>
-class node_handle<Policy, Alloc, absl::void_t<typename Policy::mapped_type>>
-    : public node_handle_base<Policy, Alloc> {
-  using Base = typename node_handle::node_handle_base;
-
- public:
-  using key_type = typename Policy::key_type;
-  using mapped_type = typename Policy::mapped_type;
-
-  constexpr node_handle() {}
-
-  auto key() const -> decltype(Base::PolicyTraits::key(this->slot())) {
-    return Base::PolicyTraits::key(this->slot());
-  }
-
-  mapped_type& mapped() const {
-    return Base::PolicyTraits::value(
-        &Base::PolicyTraits::element(this->slot()));
-  }
-
- private:
-  template <typename, typename, typename, typename>
-  friend class raw_hash_set;
-
-  node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
-};
-
-// Implement the insert_return_type<> concept of C++17.
-template <class Iterator, class NodeType>
-struct insert_return_type {
-  Iterator position;
-  bool inserted;
-  NodeType node;
-};
-
-// Helper trait to allow or disallow arbitrary keys when the hash and
-// eq functions are transparent.
-// It is very important that the inner template is an alias and that the type it
-// produces is not a dependent type. Otherwise, type deduction would fail.
-template <bool is_transparent>
-struct KeyArg {
-  // Transparent. Forward `K`.
-  template <typename K, typename key_type>
-  using type = K;
-};
-
-template <>
-struct KeyArg<false> {
-  // Not transparent. Always use `key_type`.
-  template <typename K, typename key_type>
-  using type = key_type;
-};
+  return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
+}
 
 // Policy: a policy defines how to perform different operations on
 // the slots of the hashtable (see hash_policy_traits.h for the full interface
@@ -632,14 +509,14 @@
 // if they are equal, false if they are not. If two keys compare equal, then
 // their hash values as defined by Hash MUST be equal.
 //
-// Allocator: an Allocator [http://devdocs.io/cpp/concept/allocator] with which
+// Allocator: an Allocator [https://devdocs.io/cpp/concept/allocator] with which
 // the storage of the hashtable will be allocated and the elements will be
 // constructed and destroyed.
 template <class Policy, class Hash, class Eq, class Alloc>
 class raw_hash_set {
   using PolicyTraits = hash_policy_traits<Policy>;
-  using KeyArgImpl = container_internal::KeyArg<IsTransparent<Eq>::value &&
-                                                IsTransparent<Hash>::value>;
+  using KeyArgImpl =
+      KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
 
  public:
   using init_type = typename PolicyTraits::init_type;
@@ -662,7 +539,7 @@
       allocator_type>::template rebind_traits<value_type>::const_pointer;
 
   // Alias used for heterogeneous lookup functions.
-  // `key_arg<K>` evaluates to `K` when the functors are tranparent and to
+  // `key_arg<K>` evaluates to `K` when the functors are transparent and to
   // `key_type` otherwise. It permits template argument deduction on `K` for the
   // transparent case.
   template <class K>
@@ -780,7 +657,11 @@
     }
 
     ctrl_t* ctrl_ = nullptr;
-    slot_type* slot_;
+    // To avoid uninitialized member warnigs, put slot_ in an anonymous union.
+    // The member is not initialized on singleton and end iterators.
+    union {
+      slot_type* slot_;
+    };
   };
 
   class const_iterator {
@@ -820,7 +701,8 @@
     iterator inner_;
   };
 
-  using node_type = container_internal::node_handle<Policy, Alloc>;
+  using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
+  using insert_return_type = InsertReturnType<iterator, node_type>;
 
   raw_hash_set() noexcept(
       std::is_nothrow_default_constructible<hasher>::value&&
@@ -833,7 +715,7 @@
       : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) {
     if (bucket_count) {
       capacity_ = NormalizeCapacity(bucket_count);
-      growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor);
+      reset_growth_left();
       initialize_slots();
     }
   }
@@ -875,8 +757,8 @@
   // that accept std::initializer_list<T> and std::initializer_list<init_type>.
   // This is advantageous for performance.
   //
-  //   // Turns {"abc", "def"} into std::initializer_list<std::string>, then copies
-  //   // the strings into the set.
+  //   // Turns {"abc", "def"} into std::initializer_list<std::string>, then
+  //   // copies the strings into the set.
   //   std::unordered_set<std::string> s = {"abc", "def"};
   //
   //   // Turns {"abc", "def"} into std::initializer_list<const char*>, then
@@ -939,9 +821,10 @@
     // than a full `insert`.
     for (const auto& v : that) {
       const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
-      const size_t i = find_first_non_full(hash);
-      set_ctrl(i, H2(hash));
-      emplace_at(i, v);
+      auto target = find_first_non_full(hash);
+      set_ctrl(target.offset, H2(hash));
+      emplace_at(target.offset, v);
+      infoz_.RecordInsert(hash, target.probe_length);
     }
     size_ = that.size();
     growth_left() -= that.size();
@@ -955,6 +838,7 @@
         slots_(absl::exchange(that.slots_, nullptr)),
         size_(absl::exchange(that.size_, 0)),
         capacity_(absl::exchange(that.capacity_, 0)),
+        infoz_(absl::exchange(that.infoz_, HashtablezInfoHandle())),
         // Hash, equality and allocator are copied instead of moved because
         // `that` must be left valid. If Hash is std::function<Key>, moving it
         // would create a nullptr functor that cannot be called.
@@ -975,6 +859,7 @@
       std::swap(size_, that.size_);
       std::swap(capacity_, that.capacity_);
       std::swap(growth_left(), that.growth_left());
+      std::swap(infoz_, that.infoz_);
     } else {
       reserve(that.size());
       // Note: this will copy elements of dense_set and unordered_set instead of
@@ -1022,9 +907,9 @@
   bool empty() const { return !size(); }
   size_t size() const { return size_; }
   size_t capacity() const { return capacity_; }
-  size_t max_size() const { return std::numeric_limits<size_t>::max(); }
+  size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
 
-  void clear() {
+  ABSL_ATTRIBUTE_REINITIALIZES void clear() {
     // Iterating over this container is O(bucket_count()). When bucket_count()
     // is much greater than size(), iteration becomes prohibitively expensive.
     // For clear() it is more important to reuse the allocated array when the
@@ -1042,9 +927,10 @@
       }
       size_ = 0;
       reset_ctrl();
-      growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor);
+      reset_growth_left();
     }
     assert(empty());
+    infoz_.RecordStorageChanged(0, capacity_);
   }
 
   // This overload kicks in when the argument is an rvalue of insertable and
@@ -1124,13 +1010,14 @@
     insert(ilist.begin(), ilist.end());
   }
 
-  insert_return_type<iterator, node_type> insert(node_type&& node) {
+  insert_return_type insert(node_type&& node) {
     if (!node) return {end(), false, node_type()};
-    const auto& elem = PolicyTraits::element(node.slot());
+    const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
     auto res = PolicyTraits::apply(
-        InsertSlot<false>{*this, std::move(*node.slot())}, elem);
+        InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
+        elem);
     if (res.second) {
-      node.reset();
+      CommonAccess::Reset(&node);
       return {res.first, true, node_type()};
     } else {
       return {res.first, false, std::move(node)};
@@ -1294,7 +1181,8 @@
   }
 
   node_type extract(const_iterator position) {
-    node_type node(alloc_ref(), position.inner_.slot_);
+    auto node =
+        CommonAccess::Make<node_type>(alloc_ref(), position.inner_.slot_);
     erase_meta_only(position);
     return node;
   }
@@ -1319,6 +1207,7 @@
     swap(growth_left(), that.growth_left());
     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 {
@@ -1329,17 +1218,21 @@
 
   void rehash(size_t n) {
     if (n == 0 && capacity_ == 0) return;
-    if (n == 0 && size_ == 0) return destroy_slots();
-    auto m = NormalizeCapacity(std::max(n, NumSlotsFast(size())));
+    if (n == 0 && size_ == 0) {
+      destroy_slots();
+      infoz_.RecordStorageChanged(0, 0);
+      return;
+    }
+    // bitor is a faster way of doing `max` here. We will round up to the next
+    // power-of-2-minus-1, so bitor is good enough.
+    auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
     // n == 0 unconditionally rehashes as per the standard.
     if (n == 0 || m > capacity_) {
       resize(m);
     }
   }
 
-  void reserve(size_t n) {
-    rehash(NumSlotsFast(n));
-  }
+  void reserve(size_t n) { rehash(GrowthToLowerboundCapacity(n)); }
 
   // Extension API: support for heterogeneous keys.
   //
@@ -1517,13 +1410,6 @@
     slot_type&& slot;
   };
 
-  // Computes std::ceil(n / kMaxLoadFactor). Faster than calling std::ceil.
-  static inline size_t NumSlotsFast(size_t n) {
-    return static_cast<size_t>(
-        (n * kMaxLoadFactorDenominator + (kMaxLoadFactorNumerator - 1)) /
-        kMaxLoadFactorNumerator);
-  }
-
   // "erases" the object from the container, except that it doesn't actually
   // destroy the object. It only updates all the metadata of the class.
   // This can be used in conjunction with Policy::transfer to move the object to
@@ -1546,17 +1432,23 @@
 
     set_ctrl(index, was_never_full ? kEmpty : kDeleted);
     growth_left() += was_never_full;
+    infoz_.RecordErase();
   }
 
   void initialize_slots() {
     assert(capacity_);
+    if (slots_ == nullptr) {
+      infoz_ = Sample();
+    }
+
     auto layout = MakeLayout(capacity_);
     char* mem = static_cast<char*>(
         Allocate<Layout::Alignment()>(&alloc_ref(), layout.AllocSize()));
     ctrl_ = reinterpret_cast<ctrl_t*>(layout.template Pointer<0>(mem));
     slots_ = layout.template Pointer<1>(mem);
     reset_ctrl();
-    growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor) - size_;
+    reset_growth_left();
+    infoz_.RecordStorageChanged(size_, capacity_);
   }
 
   void destroy_slots() {
@@ -1585,11 +1477,14 @@
     capacity_ = new_capacity;
     initialize_slots();
 
+    size_t total_probe_length = 0;
     for (size_t i = 0; i != old_capacity; ++i) {
       if (IsFull(old_ctrl[i])) {
         size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                           PolicyTraits::element(old_slots + i));
-        size_t new_i = find_first_non_full(hash);
+        auto target = find_first_non_full(hash);
+        size_t new_i = target.offset;
+        total_probe_length += target.probe_length;
         set_ctrl(new_i, H2(hash));
         PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
       }
@@ -1601,10 +1496,12 @@
       Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl,
                                       layout.AllocSize());
     }
+    infoz_.RecordRehash(total_probe_length);
   }
 
   void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
     assert(IsValidCapacity(capacity_));
+    assert(!is_small());
     // Algorithm:
     // - mark all DELETED slots as EMPTY
     // - mark all FULL slots as DELETED
@@ -1624,12 +1521,15 @@
     ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_);
     typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
         raw;
+    size_t total_probe_length = 0;
     slot_type* slot = reinterpret_cast<slot_type*>(&raw);
     for (size_t i = 0; i != capacity_; ++i) {
       if (!IsDeleted(ctrl_[i])) continue;
       size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                         PolicyTraits::element(slots_ + i));
-      size_t new_i = find_first_non_full(hash);
+      auto target = find_first_non_full(hash);
+      size_t new_i = target.offset;
+      total_probe_length += target.probe_length;
 
       // Verify if the old and new i fall within the same group wrt the hash.
       // If they do, we don't need to move the object as it falls already in the
@@ -1661,13 +1561,14 @@
         --i;  // repeat
       }
     }
-    growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor) - size_;
+    reset_growth_left();
+    infoz_.RecordRehash(total_probe_length);
   }
 
   void rehash_and_grow_if_necessary() {
     if (capacity_ == 0) {
-      resize(Group::kWidth - 1);
-    } else if (size() <= kMaxLoadFactor / 2 * capacity_) {
+      resize(1);
+    } else if (size() <= CapacityToGrowth(capacity()) / 2) {
       // Squash DELETED without growing if there is enough capacity.
       drop_deletes_without_resize();
     } else {
@@ -1702,24 +1603,26 @@
   // - the input is already a set
   // - there are enough slots
   // - the element with the hash is not in the table
-  size_t find_first_non_full(size_t hash) {
+  struct FindInfo {
+    size_t offset;
+    size_t probe_length;
+  };
+  FindInfo find_first_non_full(size_t hash) {
     auto seq = probe(hash);
     while (true) {
       Group g{ctrl_ + seq.offset()};
       auto mask = g.MatchEmptyOrDeleted();
       if (mask) {
 #if !defined(NDEBUG)
-        // We want to force small tables to have random entries too, so
-        // in debug build we will randomly insert in either the front or back of
+        // We want to add entropy even when ASLR is not enabled.
+        // In debug build we will randomly insert in either the front or back of
         // the group.
         // TODO(kfm,sbenza): revisit after we do unconditional mixing
-        if (ShouldInsertBackwards(hash, ctrl_))
-          return seq.offset(mask.HighestBitSet());
-        else
-          return seq.offset(mask.LowestBitSet());
-#else
-        return seq.offset(mask.LowestBitSet());
+        if (!is_small() && ShouldInsertBackwards(hash, ctrl_)) {
+          return {seq.offset(mask.HighestBitSet()), seq.index()};
+        }
 #endif
+        return {seq.offset(mask.LowestBitSet()), seq.index()};
       }
       assert(seq.index() < capacity_ && "full table!");
       seq.next();
@@ -1758,15 +1661,17 @@
   }
 
   size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE {
-    size_t target = find_first_non_full(hash);
-    if (ABSL_PREDICT_FALSE(growth_left() == 0 && !IsDeleted(ctrl_[target]))) {
+    auto target = find_first_non_full(hash);
+    if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
+                           !IsDeleted(ctrl_[target.offset]))) {
       rehash_and_grow_if_necessary();
       target = find_first_non_full(hash);
     }
     ++size_;
-    growth_left() -= IsEmpty(ctrl_[target]);
-    set_ctrl(target, H2(hash));
-    return target;
+    growth_left() -= IsEmpty(ctrl_[target.offset]);
+    set_ctrl(target.offset, H2(hash));
+    infoz_.RecordInsert(hash, target.probe_length);
+    return target.offset;
   }
 
   // Constructs the value in the space pointed by the iterator. This only works
@@ -1804,6 +1709,10 @@
     SanitizerPoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
   }
 
+  void reset_growth_left() {
+    growth_left() = CapacityToGrowth(capacity()) - size_;
+  }
+
   // Sets the control byte, and if `i < Group::kWidth`, set the cloned byte at
   // the end too.
   void set_ctrl(size_t i, ctrl_t h) {
@@ -1816,11 +1725,28 @@
     }
 
     ctrl_[i] = h;
-    ctrl_[((i - Group::kWidth) & capacity_) + Group::kWidth] = h;
+    ctrl_[((i - Group::kWidth) & capacity_) + 1 +
+          ((Group::kWidth - 1) & capacity_)] = h;
   }
 
   size_t& growth_left() { return settings_.template get<0>(); }
 
+  // The representation of the object has two modes:
+  //  - small: For capacities < kWidth-1
+  //  - large: For the rest.
+  //
+  // Differences:
+  //  - In small mode we are able to use the whole capacity. The extra control
+  //  bytes give us at least one "empty" control byte to stop the iteration.
+  //  This is important to make 1 a valid capacity.
+  //
+  //  - In small mode only the first `capacity()` control bytes after the
+  //  sentinel are valid. The rest contain dummy kEmpty values that do not
+  //  represent a real slot. This is important to take into account on
+  //  find_first_non_full(), where we never try ShouldInsertBackwards() for
+  //  small tables.
+  bool is_small() const { return capacity_ < Group::kWidth - 1; }
+
   hasher& hash_ref() { return settings_.template get<1>(); }
   const hasher& hash_ref() const { return settings_.template get<1>(); }
   key_equal& eq_ref() { return settings_.template get<2>(); }
@@ -1830,12 +1756,6 @@
     return settings_.template get<3>();
   }
 
-  // On average each group has 2 empty slot (for the vectorized case).
-  static constexpr int64_t kMaxLoadFactorNumerator = 14;
-  static constexpr int64_t kMaxLoadFactorDenominator = 16;
-  static constexpr float kMaxLoadFactor =
-      1.0 * kMaxLoadFactorNumerator / kMaxLoadFactorDenominator;
-
   // TODO(alkis): Investigate removing some of these fields:
   // - ctrl/slots can be derived from each other
   // - size can be moved into the slot array
@@ -1843,6 +1763,7 @@
   slot_type* slots_ = nullptr;     // [capacity * slot_type]
   size_t size_ = 0;                // number of full slots
   size_t capacity_ = 0;            // total number of slots
+  HashtablezInfoHandle infoz_;
   absl::container_internal::CompressedTuple<size_t /* growth_left */, hasher,
                                             key_equal, allocator_type>
       settings_{0, hasher{}, key_equal{}, allocator_type{}};
@@ -1895,10 +1816,9 @@
   }
 
   static size_t LowerBoundAllocatedByteSize(size_t size) {
-    size_t capacity = container_internal::NormalizeCapacity(
-        std::ceil(size / Set::kMaxLoadFactor));
+    size_t capacity = GrowthToLowerboundCapacity(size);
     if (capacity == 0) return 0;
-    auto layout = Set::MakeLayout(capacity);
+    auto layout = Set::MakeLayout(NormalizeCapacity(capacity));
     size_t m = layout.AllocSize();
     size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
     if (per_slot != ~size_t{}) {
diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc
index 891fa45..a5eff0b 100644
--- a/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index cd33a3a..02fd0bf 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -14,7 +14,6 @@
 
 #include "absl/container/internal/raw_hash_set.h"
 
-#include <array>
 #include <cmath>
 #include <cstdint>
 #include <deque>
@@ -49,18 +48,47 @@
 
 using ::testing::DoubleNear;
 using ::testing::ElementsAre;
+using ::testing::Ge;
+using ::testing::Lt;
 using ::testing::Optional;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
 TEST(Util, NormalizeCapacity) {
-  constexpr size_t kMinCapacity = Group::kWidth - 1;
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(0));
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(1));
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(2));
-  EXPECT_EQ(kMinCapacity, NormalizeCapacity(kMinCapacity));
-  EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 1));
-  EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 2));
+  EXPECT_EQ(1, NormalizeCapacity(0));
+  EXPECT_EQ(1, NormalizeCapacity(1));
+  EXPECT_EQ(3, NormalizeCapacity(2));
+  EXPECT_EQ(3, NormalizeCapacity(3));
+  EXPECT_EQ(7, NormalizeCapacity(4));
+  EXPECT_EQ(7, NormalizeCapacity(7));
+  EXPECT_EQ(15, NormalizeCapacity(8));
+  EXPECT_EQ(15, NormalizeCapacity(15));
+  EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1));
+  EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2));
+}
+
+TEST(Util, GrowthAndCapacity) {
+  // Verify that GrowthToCapacity gives the minimum capacity that has enough
+  // growth.
+  for (size_t growth = 0; growth < 10000; ++growth) {
+    SCOPED_TRACE(growth);
+    size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
+    // The capacity is large enough for `growth`
+    EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
+    if (growth != 0 && capacity > 1) {
+      // There is no smaller capacity that works.
+      EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth));
+    }
+  }
+
+  for (size_t capacity = Group::kWidth - 1; capacity < 10000;
+       capacity = 2 * capacity + 1) {
+    SCOPED_TRACE(capacity);
+    size_t growth = CapacityToGrowth(capacity);
+    EXPECT_THAT(growth, Lt(capacity));
+    EXPECT_LE(GrowthToLowerboundCapacity(growth), capacity);
+    EXPECT_EQ(NormalizeCapacity(GrowthToLowerboundCapacity(growth)), capacity);
+  }
 }
 
 TEST(Util, probe_seq) {
@@ -107,14 +135,14 @@
 }
 
 TEST(BitMask, LeadingTrailing) {
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0001101001000000).LeadingZeros()), 3);
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0001101001000000).TrailingZeros()), 6);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).LeadingZeros()), 3);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).TrailingZeros()), 6);
 
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0000000000000001).LeadingZeros()), 15);
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b0000000000000001).TrailingZeros()), 0);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).LeadingZeros()), 15);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).TrailingZeros()), 0);
 
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b1000000000000000).LeadingZeros()), 0);
-  EXPECT_EQ((BitMask<uint32_t, 16>(0b1000000000000000).TrailingZeros()), 15);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).LeadingZeros()), 0);
+  EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).TrailingZeros()), 15);
 
   EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).LeadingZeros()), 3);
   EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).TrailingZeros()), 1);
@@ -130,45 +158,50 @@
   for (h2_t h = 0; h != 128; ++h) EXPECT_FALSE(Group{EmptyGroup()}.Match(h));
 }
 
-#if SWISSTABLE_HAVE_SSE2
 TEST(Group, Match) {
-  ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
-                    7,      5, 3,        1, 1,      1, 1,         1};
-  EXPECT_THAT(Group{group}.Match(0), ElementsAre());
-  EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));
-  EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10));
-  EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9));
-  EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8));
+  if (Group::kWidth == 16) {
+    ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+                      7,      5, 3,        1, 1,      1, 1,         1};
+    EXPECT_THAT(Group{group}.Match(0), ElementsAre());
+    EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));
+    EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10));
+    EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9));
+    EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8));
+  } else if (Group::kWidth == 8) {
+    ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
+    EXPECT_THAT(Group{group}.Match(0), ElementsAre());
+    EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7));
+    EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4));
+  } else {
+    FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
+  }
 }
 
 TEST(Group, MatchEmpty) {
-  ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
-                    7,      5, 3,        1, 1,      1, 1,         1};
-  EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4));
+  if (Group::kWidth == 16) {
+    ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+                      7,      5, 3,        1, 1,      1, 1,         1};
+    EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4));
+  } else if (Group::kWidth == 8) {
+    ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
+    EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0));
+  } else {
+    FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
+  }
 }
 
 TEST(Group, MatchEmptyOrDeleted) {
-  ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
-                    7,      5, 3,        1, 1,      1, 1,         1};
-  EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4));
+  if (Group::kWidth == 16) {
+    ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+                      7,      5, 3,        1, 1,      1, 1,         1};
+    EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4));
+  } else if (Group::kWidth == 8) {
+    ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
+    EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3));
+  } else {
+    FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
+  }
 }
-#else
-TEST(Group, Match) {
-  ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
-  EXPECT_THAT(Group{group}.Match(0), ElementsAre());
-  EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7));
-  EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4));
-}
-TEST(Group, MatchEmpty) {
-  ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
-  EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0));
-}
-
-TEST(Group, MatchEmptyOrDeleted) {
-  ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
-  EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3));
-}
-#endif
 
 TEST(Batch, DropDeletes) {
   constexpr size_t kCapacity = 63;
@@ -338,6 +371,7 @@
     size_t size;
     size_t capacity;
     size_t growth_left;
+    void* infoz;
   };
   struct StatelessHash {
     size_t operator()(absl::string_view) const { return 0; }
@@ -386,7 +420,8 @@
     !defined(UNDEFINED_BEHAVIOR_SANITIZER)
   const auto now = [] { return absl::base_internal::CycleClock::Now(); };
 
-  static constexpr int size = 1000000;
+  // Make size enough to not fit in L2 cache (16.7 Mb)
+  static constexpr int size = 1 << 22;
   for (int i = 0; i < size; ++i) t.insert(i);
 
   int64_t no_prefetch = 0, prefetch = 0;
@@ -687,7 +722,7 @@
   Modulo1000HashTable t;
   // Adding the same length (and the same hash) strings
   // to have at least kMinFullGroups groups
-  // with Group::kWidth collisions. Then feel upto MaxDensitySize;
+  // with Group::kWidth collisions. Then fill up to MaxDensitySize;
   const size_t kMinFullGroups = 7;
   std::vector<int> keys;
   for (size_t i = 0; i < MaxDensitySize(Group::kWidth * kMinFullGroups); ++i) {
@@ -779,7 +814,7 @@
 TEST(Table, ClearBug) {
   IntTable t;
   constexpr size_t capacity = container_internal::Group::kWidth - 1;
-  constexpr size_t max_size = capacity / 2;
+  constexpr size_t max_size = capacity / 2 + 1;
   for (size_t i = 0; i < max_size; ++i) {
     t.insert(i);
   }
@@ -810,6 +845,25 @@
   EXPECT_TRUE(t.find(0) == t.end());
 }
 
+TEST(Table, EraseMaintainsValidIterator) {
+  IntTable t;
+  const int kNumElements = 100;
+  for (int i = 0; i < kNumElements; i ++) {
+    EXPECT_TRUE(t.emplace(i).second);
+  }
+  EXPECT_EQ(t.size(), kNumElements);
+
+  int num_erase_calls = 0;
+  auto it = t.begin();
+  while (it != t.end()) {
+    t.erase(it++);
+    num_erase_calls++;
+  }
+
+  EXPECT_TRUE(t.empty());
+  EXPECT_EQ(num_erase_calls, kNumElements);
+}
+
 // Collect N bad keys by following algorithm:
 // 1. Create an empty table and reserve it to 2 * N.
 // 2. Insert N random elements.
@@ -1029,7 +1083,6 @@
           {{0.95, 0.1}},
           {{0.95, 0}, {0.99, 2}, {0.999, 4}, {0.9999, 10}}};
       }
-      break;
     case 16:
       if (kRandomizesInserts) {
         return {0.1,
@@ -1042,12 +1095,11 @@
                 {{0.95, 0.05}},
                 {{0.95, 0}, {0.99, 1}, {0.999, 4}, {0.9999, 10}}};
       }
-      break;
-    default:
-      ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   }
+  ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   return {};
 }
+
 TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {
   ProbeStatsPerSize stats;
   std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1125,7 +1177,6 @@
                 {{0.95, 0.3}},
                 {{0.95, 0}, {0.99, 3}, {0.999, 15}, {0.9999, 25}}};
       }
-      break;
     case 16:
       if (kRandomizesInserts) {
         return {0.1,
@@ -1138,12 +1189,11 @@
                 {{0.95, 0.1}},
                 {{0.95, 0}, {0.99, 1}, {0.999, 6}, {0.9999, 10}}};
       }
-      break;
-    default:
-      ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   }
+  ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
   return {};
 }
+
 TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {
   ProbeStatsPerSize stats;
   std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1431,7 +1481,8 @@
 
 TEST(Table, Equality) {
   StringTable t;
-  std::vector<std::pair<std::string, std::string>> v = {{"a", "b"}, {"aa", "bb"}};
+  std::vector<std::pair<std::string, std::string>> v = {{"a", "b"},
+                                                        {"aa", "bb"}};
   t.insert(std::begin(v), std::end(v));
   StringTable u = t;
   EXPECT_EQ(u, t);
@@ -1439,20 +1490,24 @@
 
 TEST(Table, Equality2) {
   StringTable t;
-  std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"}, {"aa", "bb"}};
+  std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"},
+                                                         {"aa", "bb"}};
   t.insert(std::begin(v1), std::end(v1));
   StringTable u;
-  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, {"aa", "aa"}};
+  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"},
+                                                         {"aa", "aa"}};
   u.insert(std::begin(v2), std::end(v2));
   EXPECT_NE(u, t);
 }
 
 TEST(Table, Equality3) {
   StringTable t;
-  std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"}, {"bb", "bb"}};
+  std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"},
+                                                         {"bb", "bb"}};
   t.insert(std::begin(v1), std::end(v1));
   StringTable u;
-  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, {"aa", "aa"}};
+  std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"},
+                                                         {"aa", "aa"}};
   u.insert(std::begin(v2), std::end(v2));
   EXPECT_NE(u, t);
 }
@@ -1677,7 +1732,7 @@
   EXPECT_FALSE(node.empty());
 
   StringTable t2;
-  auto res = t2.insert(std::move(node));
+  StringTable::insert_return_type res = t2.insert(std::move(node));
   EXPECT_TRUE(res.inserted);
   EXPECT_THAT(*res.position, Pair(k0, ""));
   EXPECT_FALSE(res.node);
@@ -1707,73 +1762,49 @@
   EXPECT_FALSE(node);
 }
 
-StringTable MakeSimpleTable(size_t size) {
-  StringTable t;
-  for (size_t i = 0; i < size; ++i) t.emplace(std::string(1, 'A' + i), "");
+IntTable MakeSimpleTable(size_t size) {
+  IntTable t;
+  while (t.size() < size) t.insert(t.size());
   return t;
 }
 
-std::string OrderOfIteration(const StringTable& t) {
-  std::string order;
-  for (auto& p : t) order += p.first;
-  return order;
+std::vector<int> OrderOfIteration(const IntTable& t) {
+  return {t.begin(), t.end()};
 }
 
+// These IterationOrderChanges tests depend on non-deterministic behavior.
+// We are injecting non-determinism from the pointer of the table, but do so in
+// a way that only the page matters. We have to retry enough times to make sure
+// we are touching different memory pages to cause the ordering to change.
+// We also need to keep the old tables around to avoid getting the same memory
+// blocks over and over.
 TEST(Table, IterationOrderChangesByInstance) {
-  // Needs to be more than kWidth elements to be able to affect order.
-  const StringTable reference = MakeSimpleTable(20);
+  for (size_t size : {2, 6, 12, 20}) {
+    const auto reference_table = MakeSimpleTable(size);
+    const auto reference = OrderOfIteration(reference_table);
 
-  // Since order is non-deterministic we can't just try once and verify.
-  // We'll try until we find that order changed. It should not take many tries
-  // for that.
-  // Important: we have to keep the old tables around. Otherwise tcmalloc will
-  // just give us the same blocks and we would be doing the same order again.
-  std::vector<StringTable> garbage;
-  for (int i = 0; i < 10; ++i) {
-    auto trial = MakeSimpleTable(20);
-    if (OrderOfIteration(trial) != OrderOfIteration(reference)) {
-      // We are done.
-      return;
+    std::vector<IntTable> tables;
+    bool found_difference = false;
+    for (int i = 0; !found_difference && i < 500; ++i) {
+      tables.push_back(MakeSimpleTable(size));
+      found_difference = OrderOfIteration(tables.back()) != reference;
     }
-    garbage.push_back(std::move(trial));
+    if (!found_difference) {
+      FAIL()
+          << "Iteration order remained the same across many attempts with size "
+          << size;
+    }
   }
-  FAIL();
 }
 
 TEST(Table, IterationOrderChangesOnRehash) {
-  // Since order is non-deterministic we can't just try once and verify.
-  // We'll try until we find that order changed. It should not take many tries
-  // for that.
-  // Important: we have to keep the old tables around. Otherwise tcmalloc will
-  // just give us the same blocks and we would be doing the same order again.
-  std::vector<StringTable> garbage;
-  for (int i = 0; i < 10; ++i) {
-    // Needs to be more than kWidth elements to be able to affect order.
-    StringTable t = MakeSimpleTable(20);
-    const std::string reference = OrderOfIteration(t);
+  std::vector<IntTable> garbage;
+  for (int i = 0; i < 500; ++i) {
+    auto t = MakeSimpleTable(20);
+    const auto reference = OrderOfIteration(t);
     // Force rehash to the same size.
     t.rehash(0);
-    std::string trial = OrderOfIteration(t);
-    if (trial != reference) {
-      // We are done.
-      return;
-    }
-    garbage.push_back(std::move(t));
-  }
-  FAIL();
-}
-
-TEST(Table, IterationOrderChangesForSmallTables) {
-  // Since order is non-deterministic we can't just try once and verify.
-  // We'll try until we find that order changed.
-  // Important: we have to keep the old tables around. Otherwise tcmalloc will
-  // just give us the same blocks and we would be doing the same order again.
-  StringTable reference_table = MakeSimpleTable(5);
-  const std::string reference = OrderOfIteration(reference_table);
-  std::vector<StringTable> garbage;
-  for (int i = 0; i < 50; ++i) {
-    StringTable t = MakeSimpleTable(5);
-    std::string trial = OrderOfIteration(t);
+    auto trial = OrderOfIteration(t);
     if (trial != reference) {
       // We are done.
       return;
@@ -1783,136 +1814,22 @@
   FAIL() << "Iteration order remained the same across many attempts.";
 }
 
-// Fill the table to 3 different load factors (min, median, max) and evaluate
-// the percentage of perfect hits using the debug API.
-template <class Table, class AddFn>
-std::vector<double> CollectPerfectRatios(Table t, AddFn add) {
-  using Key = typename Table::key_type;
+// Verify that pointers are invalidated as soon as a second element is inserted.
+// This prevents dependency on pointer stability on small tables.
+TEST(Table, UnstablePointers) {
+  IntTable table;
 
-  // First, fill enough to have a good distribution.
-  constexpr size_t kMinSize = 10000;
-  std::vector<Key> keys;
-  while (t.size() < kMinSize) keys.push_back(add(t));
-  // Then, insert until we reach min load factor.
-  double lf = t.load_factor();
-  while (lf <= t.load_factor()) keys.push_back(add(t));
-
-  // We are now at min load factor. Take a snapshot.
-  size_t perfect = 0;
-  auto update_perfect = [&](Key k) {
-    perfect += GetHashtableDebugNumProbes(t, k) == 0;
+  const auto addr = [&](int i) {
+    return reinterpret_cast<uintptr_t>(&*table.find(i));
   };
-  for (const auto& k : keys) update_perfect(k);
 
-  std::vector<double> perfect_ratios;
-  // Keep going until we hit max load factor.
-  while (t.load_factor() < .6) {
-    perfect_ratios.push_back(1.0 * perfect / t.size());
-    update_perfect(add(t));
-  }
-  while (t.load_factor() > .5) {
-    perfect_ratios.push_back(1.0 * perfect / t.size());
-    update_perfect(add(t));
-  }
-  return perfect_ratios;
-}
+  table.insert(0);
+  const uintptr_t old_ptr = addr(0);
 
-std::vector<std::pair<double, double>> StringTablePefectRatios() {
-  constexpr bool kRandomizesInserts =
-#if NDEBUG
-      false;
-#else   // NDEBUG
-      true;
-#endif  // NDEBUG
+  // This causes a rehash.
+  table.insert(1);
 
-  // The effective load factor is larger in non-opt mode because we insert
-  // elements out of order.
-  switch (container_internal::Group::kWidth) {
-    case 8:
-      if (kRandomizesInserts) {
-        return {{0.986, 0.02}, {0.95, 0.02}, {0.89, 0.02}};
-      } else {
-        return {{0.995, 0.01}, {0.97, 0.01}, {0.89, 0.02}};
-      }
-      break;
-    case 16:
-      if (kRandomizesInserts) {
-        return {{0.973, 0.01}, {0.965, 0.01}, {0.92, 0.02}};
-      } else {
-        return {{0.995, 0.005}, {0.99, 0.005}, {0.94, 0.01}};
-      }
-      break;
-    default:
-      // Ignore anything else.
-      return {};
-  }
-}
-
-// This is almost a change detector, but it allows us to know how we are
-// affecting the probe distribution.
-TEST(Table, EffectiveLoadFactorStrings) {
-  std::vector<double> perfect_ratios =
-      CollectPerfectRatios(StringTable(), [](StringTable& t) {
-        return t.emplace(std::to_string(t.size()), "").first->first;
-      });
-
-  auto ratios = StringTablePefectRatios();
-  if (ratios.empty()) return;
-
-  EXPECT_THAT(perfect_ratios.front(),
-              DoubleNear(ratios[0].first, ratios[0].second));
-  EXPECT_THAT(perfect_ratios[perfect_ratios.size() / 2],
-              DoubleNear(ratios[1].first, ratios[1].second));
-  EXPECT_THAT(perfect_ratios.back(),
-              DoubleNear(ratios[2].first, ratios[2].second));
-}
-
-std::vector<std::pair<double, double>> IntTablePefectRatios() {
-  constexpr bool kRandomizesInserts =
-#ifdef NDEBUG
-      false;
-#else   // NDEBUG
-      true;
-#endif  // NDEBUG
-
-  // The effective load factor is larger in non-opt mode because we insert
-  // elements out of order.
-  switch (container_internal::Group::kWidth) {
-    case 8:
-      if (kRandomizesInserts) {
-        return {{0.99, 0.02}, {0.985, 0.02}, {0.95, 0.05}};
-      } else {
-        return {{0.99, 0.01}, {0.99, 0.01}, {0.95, 0.02}};
-      }
-      break;
-    case 16:
-      if (kRandomizesInserts) {
-        return {{0.98, 0.02}, {0.978, 0.02}, {0.96, 0.02}};
-      } else {
-        return {{0.998, 0.003}, {0.995, 0.01}, {0.975, 0.02}};
-      }
-      break;
-    default:
-      // Ignore anything else.
-      return {};
-  }
-}
-
-// This is almost a change detector, but it allows us to know how we are
-// affecting the probe distribution.
-TEST(Table, EffectiveLoadFactorInts) {
-  std::vector<double> perfect_ratios = CollectPerfectRatios(
-      IntTable(), [](IntTable& t) { return *t.emplace(t.size()).first; });
-
-  auto ratios = IntTablePefectRatios();
-  if (ratios.empty()) return;
-
-  EXPECT_THAT(perfect_ratios.front(),
-              DoubleNear(ratios[0].first, ratios[0].second));
-  EXPECT_THAT(perfect_ratios[perfect_ratios.size() / 2],
-              DoubleNear(ratios[1].first, ratios[1].second));
-  EXPECT_THAT(perfect_ratios.back(),
-              DoubleNear(ratios[2].first, ratios[2].second));
+  EXPECT_NE(old_ptr, addr(0));
 }
 
 // Confirm that we assert if we try to erase() end().
@@ -1931,9 +1848,31 @@
   EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
 }
 
+TEST(RawHashSamplerTest, Sample) {
+  // Enable the feature even if the prod default is off.
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);
+
+  auto& sampler = HashtablezSampler::Global();
+  size_t start_size = 0;
+  start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
+
+  std::vector<IntTable> tables;
+  for (int i = 0; i < 1000000; ++i) {
+    tables.emplace_back();
+    tables.back().insert(1);
+  }
+  size_t end_size = 0;
+  end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
+
+  EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
+              0.01, 0.005);
+}
+
 #ifdef ADDRESS_SANITIZER
 TEST(Sanitizer, PoisoningUnused) {
   IntTable t;
+  t.reserve(5);
   // Insert something to force an allocation.
   int64_t& v1 = *t.insert(0).first;
 
diff --git a/absl/container/internal/test_instance_tracker.cc b/absl/container/internal/test_instance_tracker.cc
index b18e0bb..5a66cb4 100644
--- a/absl/container/internal/test_instance_tracker.cc
+++ b/absl/container/internal/test_instance_tracker.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/test_instance_tracker.h b/absl/container/internal/test_instance_tracker.h
index ec45f57..032d16d 100644
--- a/absl/container/internal/test_instance_tracker.h
+++ b/absl/container/internal/test_instance_tracker.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/test_instance_tracker_test.cc b/absl/container/internal/test_instance_tracker_test.cc
index 0ae5763..091f428 100644
--- a/absl/container/internal/test_instance_tracker_test.cc
+++ b/absl/container/internal/test_instance_tracker_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/tracked.h b/absl/container/internal/tracked.h
index 7d14af0..75173ab 100644
--- a/absl/container/internal/tracked.h
+++ b/absl/container/internal/tracked.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/container/internal/unordered_map_constructor_test.h b/absl/container/internal/unordered_map_constructor_test.h
index 2ffb646..68817e4 100644
--- a/absl/container/internal/unordered_map_constructor_test.h
+++ b/absl/container/internal/unordered_map_constructor_test.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -29,7 +29,7 @@
 template <class UnordMap>
 class ConstructorTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ConstructorTest);
+TYPED_TEST_SUITE_P(ConstructorTest);
 
 TYPED_TEST_P(ConstructorTest, NoArgs) {
   TypeParam m;
@@ -83,8 +83,28 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+template <typename T>
+struct is_std_unordered_map : std::false_type {};
+
+template <typename... T>
+struct is_std_unordered_map<std::unordered_map<T...>> : std::true_type {};
+
 #if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+using has_cxx14_std_apis = std::true_type;
+#else
+using has_cxx14_std_apis = std::false_type;
+#endif
+
+template <typename T>
+using expect_cxx14_apis =
+    absl::disjunction<absl::negation<is_std_unordered_map<T>>,
+                      has_cxx14_std_apis>;
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(123, alloc);
@@ -92,11 +112,17 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(m, ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+  BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::true_type) {
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
   H hasher;
@@ -107,18 +133,38 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(m, ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketAlloc) {
+TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
+  BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
 #if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+using has_alloc_std_constructors = std::true_type;
+#else
+using has_alloc_std_constructors = std::false_type;
+#endif
+
+template <typename T>
+using expect_alloc_constructors =
+    absl::disjunction<absl::negation<is_std_unordered_map<T>>,
+                      has_alloc_std_constructors>;
+
+template <typename TypeParam>
+void AllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void AllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(alloc);
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(m, ::testing::UnorderedElementsAre());
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+  AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
@@ -140,8 +186,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   A alloc(0);
@@ -152,11 +201,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
+  InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -170,7 +225,10 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+  InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, CopyConstructor) {
@@ -190,8 +248,11 @@
   EXPECT_EQ(m, n);
 }
 
-TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -206,7 +267,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+  CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on copy constructors.
@@ -229,8 +293,11 @@
   EXPECT_EQ(m, n);
 }
 
-TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -246,7 +313,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+  MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on move constructors.
@@ -269,8 +339,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   hash_internal::Generator<T> gen;
@@ -280,11 +353,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
+  InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -297,7 +376,10 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+  InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, Assignment) {
@@ -390,15 +472,16 @@
 
 REGISTER_TYPED_TEST_CASE_P(
     ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
-    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc,
-    BucketAlloc, InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+    InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
     InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
     MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
     InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
-    MoveAssignment, AssignmentFromInitializerList,
-    AssignmentOverwritesExisting, MoveAssignmentOverwritesExisting,
+    MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,
+    MoveAssignmentOverwritesExisting,
     AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
diff --git a/absl/container/internal/unordered_map_lookup_test.h b/absl/container/internal/unordered_map_lookup_test.h
index 1f1b6b4..ebd3612 100644
--- a/absl/container/internal/unordered_map_lookup_test.h
+++ b/absl/container/internal/unordered_map_lookup_test.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -26,7 +26,7 @@
 template <class UnordMap>
 class LookupTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(LookupTest);
+TYPED_TEST_SUITE_P(LookupTest);
 
 TYPED_TEST_P(LookupTest, At) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -111,4 +111,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_
diff --git a/absl/container/internal/unordered_map_members_test.h b/absl/container/internal/unordered_map_members_test.h
new file mode 100644
index 0000000..1bf31ab
--- /dev/null
+++ b/absl/container/internal/unordered_map_members_test.h
@@ -0,0 +1,85 @@
+// 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_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
+
+#include <type_traits>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace container_internal {
+
+template <class UnordMap>
+class MembersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(MembersTest);
+
+template <typename T>
+void UseType() {}
+
+TYPED_TEST_P(MembersTest, Typedefs) {
+  EXPECT_TRUE((std::is_same<std::pair<const typename TypeParam::key_type,
+                                      typename TypeParam::mapped_type>,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((absl::conjunction<
+               absl::negation<std::is_signed<typename TypeParam::size_type>>,
+               std::is_integral<typename TypeParam::size_type>>()));
+  EXPECT_TRUE((absl::conjunction<
+               std::is_signed<typename TypeParam::difference_type>,
+               std::is_integral<typename TypeParam::difference_type>>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::hasher&>()(
+                   std::declval<const typename TypeParam::key_type&>())),
+               size_t>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::key_equal&>()(
+                   std::declval<const typename TypeParam::key_type&>(),
+                   std::declval<const typename TypeParam::key_type&>())),
+               bool>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,
+                            typename TypeParam::reference>()));
+  EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,
+                            typename TypeParam::const_reference>()));
+  EXPECT_TRUE((std::is_same<typename std::allocator_traits<
+                                typename TypeParam::allocator_type>::pointer,
+                            typename TypeParam::pointer>()));
+  EXPECT_TRUE(
+      (std::is_same<typename std::allocator_traits<
+                        typename TypeParam::allocator_type>::const_pointer,
+                    typename TypeParam::const_pointer>()));
+}
+
+TYPED_TEST_P(MembersTest, SimpleFunctions) {
+  EXPECT_GT(TypeParam().max_size(), 0);
+}
+
+TYPED_TEST_P(MembersTest, BeginEnd) {
+  TypeParam t = {typename TypeParam::value_type{}};
+  EXPECT_EQ(t.begin(), t.cbegin());
+  EXPECT_EQ(t.end(), t.cend());
+  EXPECT_NE(t.begin(), t.end());
+  EXPECT_NE(t.cbegin(), t.cend());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
diff --git a/absl/container/internal/unordered_map_modifiers_test.h b/absl/container/internal/unordered_map_modifiers_test.h
index b6c633a..52a1092 100644
--- a/absl/container/internal/unordered_map_modifiers_test.h
+++ b/absl/container/internal/unordered_map_modifiers_test.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -26,7 +26,7 @@
 template <class UnordMap>
 class ModifiersTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ModifiersTest);
+TYPED_TEST_SUITE_P(ModifiersTest);
 
 TYPED_TEST_P(ModifiersTest, Clear) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -269,4 +269,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
diff --git a/absl/container/internal/unordered_map_test.cc b/absl/container/internal/unordered_map_test.cc
index 40e799c..72567ea 100644
--- a/absl/container/internal/unordered_map_test.cc
+++ b/absl/container/internal/unordered_map_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -16,6 +16,7 @@
 
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 
 namespace absl {
@@ -29,9 +30,10 @@
                        StatefulTestingEqual,
                        Alloc<std::pair<const std::string, std::string>>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes);
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/internal/unordered_set_constructor_test.h b/absl/container/internal/unordered_set_constructor_test.h
index cb59370..f484468 100644
--- a/absl/container/internal/unordered_set_constructor_test.h
+++ b/absl/container/internal/unordered_set_constructor_test.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -16,12 +16,14 @@
 #define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
 
 #include <algorithm>
+#include <unordered_set>
 #include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/hash_policy_testing.h"
+#include "absl/meta/type_traits.h"
 
 namespace absl {
 namespace container_internal {
@@ -29,7 +31,7 @@
 template <class UnordMap>
 class ConstructorTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ConstructorTest);
+TYPED_TEST_SUITE_P(ConstructorTest);
 
 TYPED_TEST_P(ConstructorTest, NoArgs) {
   TypeParam m;
@@ -91,8 +93,28 @@
   EXPECT_GE(cm.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+template <typename T>
+struct is_std_unordered_set : std::false_type {};
+
+template <typename... T>
+struct is_std_unordered_set<std::unordered_set<T...>> : std::true_type {};
+
 #if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+using has_cxx14_std_apis = std::true_type;
+#else
+using has_cxx14_std_apis = std::false_type;
+#endif
+
+template <typename T>
+using expect_cxx14_apis =
+    absl::disjunction<absl::negation<is_std_unordered_set<T>>,
+                      has_cxx14_std_apis>;
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(123, alloc);
@@ -100,11 +122,17 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+  BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::true_type) {
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
   H hasher;
@@ -115,18 +143,38 @@
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, BucketAlloc) {
+TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
+  BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
 #if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+using has_alloc_std_constructors = std::true_type;
+#else
+using has_alloc_std_constructors = std::false_type;
+#endif
+
+template <typename T>
+using expect_alloc_constructors =
+    absl::disjunction<absl::negation<is_std_unordered_set<T>>,
+                      has_alloc_std_constructors>;
+
+template <typename TypeParam>
+void AllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void AllocTest(std::true_type) {
   using A = typename TypeParam::allocator_type;
   A alloc(0);
   TypeParam m(alloc);
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_TRUE(m.empty());
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+  AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
@@ -148,8 +196,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   A alloc(0);
@@ -160,11 +211,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
+  InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -178,7 +235,10 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+  InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
 }
 
 TYPED_TEST_P(ConstructorTest, CopyConstructor) {
@@ -196,10 +256,14 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_EQ(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
+  EXPECT_NE(TypeParam(0, hasher, equal, alloc), n);
 }
 
-TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -214,7 +278,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+  CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on copy constructors.
@@ -237,8 +304,11 @@
   EXPECT_EQ(m, n);
 }
 
-TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -254,7 +324,10 @@
   EXPECT_EQ(m.key_eq(), n.key_eq());
   EXPECT_NE(m.get_allocator(), n.get_allocator());
   EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+  MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
 }
 
 // TODO(alkis): Test non-propagating allocators on move constructors.
@@ -277,8 +350,11 @@
   EXPECT_GE(m.bucket_count(), 123);
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using A = typename TypeParam::allocator_type;
   hash_internal::Generator<T> gen;
@@ -288,11 +364,17 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
+  InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::true_type) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using A = typename TypeParam::allocator_type;
@@ -305,10 +387,13 @@
   EXPECT_EQ(m.get_allocator(), alloc);
   EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
   EXPECT_GE(m.bucket_count(), 123);
-#endif
 }
 
-TYPED_TEST_P(ConstructorTest, Assignment) {
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+  InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, CopyAssignment) {
   using T = hash_internal::GeneratedType<TypeParam>;
   using H = typename TypeParam::hasher;
   using E = typename TypeParam::key_equal;
@@ -394,15 +479,16 @@
 
 REGISTER_TYPED_TEST_CASE_P(
     ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
-    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc,
-    BucketAlloc, InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+    BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+    InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
     InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
     MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
-    InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
-    MoveAssignment, AssignmentFromInitializerList,
-    AssignmentOverwritesExisting, MoveAssignmentOverwritesExisting,
+    InitializerListBucketAlloc, InitializerListBucketHashAlloc, CopyAssignment,
+    MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,
+    MoveAssignmentOverwritesExisting,
     AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
diff --git a/absl/container/internal/unordered_set_lookup_test.h b/absl/container/internal/unordered_set_lookup_test.h
index aca9c6a..05b32b5 100644
--- a/absl/container/internal/unordered_set_lookup_test.h
+++ b/absl/container/internal/unordered_set_lookup_test.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -26,7 +26,7 @@
 template <class UnordSet>
 class LookupTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(LookupTest);
+TYPED_TEST_SUITE_P(LookupTest);
 
 TYPED_TEST_P(LookupTest, Count) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -85,4 +85,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_
diff --git a/absl/container/internal/unordered_set_members_test.h b/absl/container/internal/unordered_set_members_test.h
new file mode 100644
index 0000000..b96c945
--- /dev/null
+++ b/absl/container/internal/unordered_set_members_test.h
@@ -0,0 +1,84 @@
+// 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_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
+
+#include <type_traits>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+namespace container_internal {
+
+template <class UnordSet>
+class MembersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(MembersTest);
+
+template <typename T>
+void UseType() {}
+
+TYPED_TEST_P(MembersTest, Typedefs) {
+  EXPECT_TRUE((std::is_same<typename TypeParam::key_type,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((absl::conjunction<
+               absl::negation<std::is_signed<typename TypeParam::size_type>>,
+               std::is_integral<typename TypeParam::size_type>>()));
+  EXPECT_TRUE((absl::conjunction<
+               std::is_signed<typename TypeParam::difference_type>,
+               std::is_integral<typename TypeParam::difference_type>>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::hasher&>()(
+                   std::declval<const typename TypeParam::key_type&>())),
+               size_t>()));
+  EXPECT_TRUE((std::is_convertible<
+               decltype(std::declval<const typename TypeParam::key_equal&>()(
+                   std::declval<const typename TypeParam::key_type&>(),
+                   std::declval<const typename TypeParam::key_type&>())),
+               bool>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,
+                            typename TypeParam::value_type>()));
+  EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,
+                            typename TypeParam::reference>()));
+  EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,
+                            typename TypeParam::const_reference>()));
+  EXPECT_TRUE((std::is_same<typename std::allocator_traits<
+                                typename TypeParam::allocator_type>::pointer,
+                            typename TypeParam::pointer>()));
+  EXPECT_TRUE(
+      (std::is_same<typename std::allocator_traits<
+                        typename TypeParam::allocator_type>::const_pointer,
+                    typename TypeParam::const_pointer>()));
+}
+
+TYPED_TEST_P(MembersTest, SimpleFunctions) {
+  EXPECT_GT(TypeParam().max_size(), 0);
+}
+
+TYPED_TEST_P(MembersTest, BeginEnd) {
+  TypeParam t = {typename TypeParam::value_type{}};
+  EXPECT_EQ(t.begin(), t.cbegin());
+  EXPECT_EQ(t.end(), t.cend());
+  EXPECT_NE(t.begin(), t.end());
+  EXPECT_NE(t.cbegin(), t.cend());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
+
+}  // namespace container_internal
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
diff --git a/absl/container/internal/unordered_set_modifiers_test.h b/absl/container/internal/unordered_set_modifiers_test.h
index 9beacf3..79a8d42 100644
--- a/absl/container/internal/unordered_set_modifiers_test.h
+++ b/absl/container/internal/unordered_set_modifiers_test.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -26,7 +26,7 @@
 template <class UnordSet>
 class ModifiersTest : public ::testing::Test {};
 
-TYPED_TEST_CASE_P(ModifiersTest);
+TYPED_TEST_SUITE_P(ModifiersTest);
 
 TYPED_TEST_P(ModifiersTest, Clear) {
   using T = hash_internal::GeneratedType<TypeParam>;
@@ -184,4 +184,5 @@
 
 }  // namespace container_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_
diff --git a/absl/container/internal/unordered_set_test.cc b/absl/container/internal/unordered_set_test.cc
index 1281ce5..6478fac 100644
--- a/absl/container/internal/unordered_set_test.cc
+++ b/absl/container/internal/unordered_set_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -16,21 +16,23 @@
 
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 
 namespace absl {
 namespace container_internal {
 namespace {
 
-using SetTypes =
-    ::testing::Types<std::unordered_set<int, StatefulTestingHash,
-                                        StatefulTestingEqual, Alloc<int>>,
-                     std::unordered_set<std::string, StatefulTestingHash,
-                                        StatefulTestingEqual, Alloc<std::string>>>;
+using SetTypes = ::testing::Types<
+    std::unordered_set<int, StatefulTestingHash, StatefulTestingEqual,
+                       Alloc<int>>,
+    std::unordered_set<std::string, StatefulTestingHash, StatefulTestingEqual,
+                       Alloc<std::string>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes);
 
 }  // namespace
 }  // namespace container_internal
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 6369ec3..a841f5a 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -40,6 +40,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/algorithm/container.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
 #include "absl/container/internal/node_hash_policy.h"
@@ -71,7 +72,7 @@
 // By default, `node_hash_map` uses the `absl::Hash` hashing framework.
 // All fundamental and Abseil types that support the `absl::Hash` framework have
 // a compatible equality operator for comparing insertions into `node_hash_map`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -91,7 +92,7 @@
 //  std::string search_key = "b";
 //  auto result = ducks.find(search_key);
 //  if (result != ducks.end()) {
-//    std::cout << "Result: " << search_key->second << std::endl;
+//    std::cout << "Result: " << result->second << std::endl;
 //  }
 template <class Key, class Value,
           class Hash = absl::container_internal::hash_default_hash<Key>,
@@ -104,6 +105,46 @@
   using Base = typename node_hash_map::raw_hash_map;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A node_hash_map supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::node_hash_map<int, std::string> map1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::node_hash_map<int, std::string> map2 =
+  //       {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::node_hash_map<int, std::string> map3(map2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::node_hash_map<int, std::string> map4;
+  //  map4 = map3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::node_hash_map<int, std::string> map5(std::move(map4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::node_hash_map<int, std::string> map6;
+  //   map6 = std::move(map5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+  //   absl::node_hash_map<int, std::string> map7(v.begin(), v.end());
   node_hash_map() {}
   using Base::Base;
 
@@ -526,5 +567,16 @@
   static const Value& value(const value_type* elem) { return elem->second; }
 };
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+    absl::node_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+}  // namespace container_algorithm_internal
+
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_NODE_HASH_MAP_H_
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index bd78964..0f2714a 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,6 +17,7 @@
 #include "absl/container/internal/tracked.h"
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 
 namespace absl {
@@ -34,9 +35,10 @@
                         StatefulTestingEqual,
                         Alloc<std::pair<const std::string, std::string>>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ModifiersTest, MapTypes);
 
 using M = absl::node_hash_map<std::string, Tracked<int>>;
 
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 90d4ce0..0cd1fe5 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -37,6 +37,7 @@
 
 #include <type_traits>
 
+#include "absl/algorithm/container.h"
 #include "absl/container/internal/hash_function_defaults.h"  // IWYU pragma: export
 #include "absl/container/internal/node_hash_policy.h"
 #include "absl/container/internal/raw_hash_set.h"  // IWYU pragma: export
@@ -67,7 +68,7 @@
 // By default, `node_hash_set` uses the `absl::Hash` hashing framework.
 // All fundamental and Abseil types that support the `absl::Hash` framework have
 // a compatible equality operator for comparing insertions into `node_hash_set`.
-// If your type is not yet supported by the `asbl::Hash` framework, see
+// If your type is not yet supported by the `absl::Hash` framework, see
 // absl/hash/hash.h for information on extending Abseil hashing to user-defined
 // types.
 //
@@ -96,6 +97,46 @@
   using Base = typename node_hash_set::raw_hash_set;
 
  public:
+  // Constructors and Assignment Operators
+  //
+  // A node_hash_set supports the same overload set as `std::unordered_map`
+  // for construction and assignment:
+  //
+  // *  Default constructor
+  //
+  //    // No allocation for the table's elements is made.
+  //    absl::node_hash_set<std::string> set1;
+  //
+  // * Initializer List constructor
+  //
+  //   absl::node_hash_set<std::string> set2 =
+  //       {{"huey"}, {"dewey"}, {"louie"},};
+  //
+  // * Copy constructor
+  //
+  //   absl::node_hash_set<std::string> set3(set2);
+  //
+  // * Copy assignment operator
+  //
+  //  // Hash functor and Comparator are copied as well
+  //  absl::node_hash_set<std::string> set4;
+  //  set4 = set3;
+  //
+  // * Move constructor
+  //
+  //   // Move is guaranteed efficient
+  //   absl::node_hash_set<std::string> set5(std::move(set4));
+  //
+  // * Move assignment operator
+  //
+  //   // May be efficient if allocators are compatible
+  //   absl::node_hash_set<std::string> set6;
+  //   set6 = std::move(set5);
+  //
+  // * Range constructor
+  //
+  //   std::vector<std::string> v = {"a", "b"};
+  //   absl::node_hash_set<std::string> set7(v.begin(), v.end());
   node_hash_set() {}
   using Base::Base;
 
@@ -232,8 +273,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace;
@@ -247,8 +287,7 @@
   //
   // The element may be constructed even if there already is an element with the
   // key in the container, in which case the newly constructed element will be
-  // destroyed immediately. Prefer `try_emplace()` unless your key is not
-  // copyable or moveable.
+  // destroyed immediately.
   //
   // If rehashing occurs due to the insertion, all iterators are invalidated.
   using Base::emplace_hint;
@@ -435,5 +474,15 @@
   static size_t element_space_used(const T*) { return sizeof(T); }
 };
 }  // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>>
+    : std::true_type {};
+
+}  // namespace container_algorithm_internal
 }  // namespace absl
+
 #endif  // ABSL_CONTAINER_NODE_HASH_SET_H_
diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc
index 7e498f0..0ea76e7 100644
--- a/absl/container/node_hash_set_test.cc
+++ b/absl/container/node_hash_set_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -16,6 +16,7 @@
 
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 
 namespace absl {
@@ -29,14 +30,15 @@
 using SetTypes = ::testing::Types<
     node_hash_set<int, StatefulTestingHash, StatefulTestingEqual, Alloc<int>>,
     node_hash_set<std::string, StatefulTestingHash, StatefulTestingEqual,
-                  Alloc<int>>,
+                  Alloc<std::string>>,
     node_hash_set<Enum, StatefulTestingHash, StatefulTestingEqual, Alloc<Enum>>,
     node_hash_set<EnumClass, StatefulTestingHash, StatefulTestingEqual,
                   Alloc<EnumClass>>>;
 
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ModifiersTest, SetTypes);
 
 TEST(NodeHashSet, MoveableNotCopyableCompiles) {
   node_hash_set<std::unique_ptr<void*>> t;
diff --git a/absl/copts.bzl b/absl/copts.bzl
deleted file mode 100644
index 5c508f1..0000000
--- a/absl/copts.bzl
+++ /dev/null
@@ -1,164 +0,0 @@
-"""absl specific copts.
-
-Flags specified here must not impact ABI. Code compiled with and without these
-opts will be linked together, and in some cases headers compiled with and
-without these options will be part of the same program.
-"""
-GCC_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Wcast-qual",
-    "-Wconversion-null",
-    "-Wmissing-declarations",
-    "-Woverlength-strings",
-    "-Wpointer-arith",
-    "-Wunused-local-typedefs",
-    "-Wunused-result",
-    "-Wvarargs",
-    "-Wvla",  # variable-length array
-    "-Wwrite-strings",
-    # Google style does not use unsigned integers, though STL containers
-    # have unsigned types.
-    "-Wno-sign-compare",
-]
-
-GCC_TEST_FLAGS = [
-    "-Wno-conversion-null",
-    "-Wno-missing-declarations",
-    "-Wno-sign-compare",
-    "-Wno-unused-function",
-    "-Wno-unused-parameter",
-    "-Wno-unused-private-field",
-]
-
-# Docs on single flags is preceded by a comment.
-# Docs on groups of flags is preceded by ###.
-
-LLVM_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Weverything",
-    # 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-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-nested-anon-types",
-    "-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-undef",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    # Causes warnings on include guards
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    ###
-    # 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_FLAGS = [
-    "-Wno-c99-extensions",
-    "-Wno-missing-noreturn",
-    "-Wno-missing-prototypes",
-    "-Wno-missing-variable-declarations",
-    "-Wno-null-conversion",
-    "-Wno-shadow",
-    "-Wno-shift-sign-overflow",
-    "-Wno-sign-compare",
-    "-Wno-unused-function",
-    "-Wno-unused-member-function",
-    "-Wno-unused-parameter",
-    "-Wno-unused-private-field",
-    "-Wno-unused-template",
-    "-Wno-used-but-marked-unused",
-    "-Wno-zero-as-null-pointer-constant",
-    # gtest depends on this GNU extension being offered.
-    "-Wno-gnu-zero-variadic-macro-arguments",
-]
-
-MSVC_FLAGS = [
-    "/W3",
-    "/wd4005",  # macro-redefinition
-    "/wd4068",  # unknown pragma
-    "/wd4180",  # qualifier applied to function type has no meaning; ignored
-    "/wd4244",  # conversion from 'type1' to 'type2', possible loss of data
-    "/wd4267",  # conversion from 'size_t' to 'type', possible loss of data
-    "/wd4800",  # forcing value to bool 'true' or 'false' (performance warning)
-    "/DNOMINMAX",  # Don't define min and max macros (windows.h)
-    "/DWIN32_LEAN_AND_MEAN",  # Don't bloat namespace with incompatible winsock versions.
-    "/D_CRT_SECURE_NO_WARNINGS",  # Don't warn about usage of insecure C functions
-]
-
-MSVC_TEST_FLAGS = [
-    "/wd4018",  # signed/unsigned mismatch
-    "/wd4101",  # unreferenced local variable
-    "/wd4503",  # decorated name length exceeded, name was truncated
-]
-
-# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
-ABSL_DEFAULT_COPTS = select({
-    "//absl:windows": MSVC_FLAGS,
-    "//absl:llvm_compiler": LLVM_FLAGS,
-    "//conditions:default": 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": MSVC_TEST_FLAGS,
-    "//absl:llvm_compiler": LLVM_TEST_FLAGS,
-    "//conditions:default": GCC_TEST_FLAGS,
-})
-
-ABSL_EXCEPTIONS_FLAG = select({
-    "//absl:windows": ["/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"],
-    "//conditions:default": ["-fexceptions"],
-})
-
-ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
-    "//conditions:default": [],
-})
diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake
new file mode 100644
index 0000000..5084958
--- /dev/null
+++ b/absl/copts/AbseilConfigureCopts.cmake
@@ -0,0 +1,52 @@
+# See absl/copts/copts.py and absl/copts/generate_copts.py
+include(GENERATED_AbseilCopts)
+
+set(ABSL_LSAN_LINKOPTS "")
+set(ABSL_HAVE_LSAN OFF)
+
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+  set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}")
+  set(ABSL_TEST_COPTS "${ABSL_GCC_FLAGS};${ABSL_GCC_TEST_FLAGS}")
+  set(ABSL_EXCEPTIONS_FLAG "${ABSL_GCC_EXCEPTIONS_FLAGS}")
+elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+  # MATCHES so we get both Clang and AppleClang
+  if (MSVC)
+    # clang-cl is half MSVC, half LLVM
+    set(ABSL_DEFAULT_COPTS "${ABSL_CLANG_CL_FLAGS}")
+    set(ABSL_TEST_COPTS "${ABSL_CLANG_CL_FLAGS};${ABSL_CLANG_CL_TEST_FLAGS}")
+    set(ABSL_EXCEPTIONS_FLAG "${ABSL_CLANG_CL_EXCEPTIONS_FLAGS}")
+  else()
+    set(ABSL_DEFAULT_COPTS "${ABSL_LLVM_FLAGS}")
+    set(ABSL_TEST_COPTS "${ABSL_LLVM_FLAGS};${ABSL_LLVM_TEST_FLAGS}")
+    set(ABSL_EXCEPTIONS_FLAG "${ABSL_LLVM_EXCEPTIONS_FLAGS}")
+    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+      # AppleClang doesn't have lsan
+      # https://developer.apple.com/documentation/code_diagnostics
+      if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5)
+        set(ABSL_LSAN_LINKOPTS "-fsanitize=leak")
+        set(ABSL_HAVE_LSAN ON)
+      endif()
+    endif()
+  endif()
+elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+  set(ABSL_DEFAULT_COPTS "${ABSL_MSVC_FLAGS}")
+  set(ABSL_TEST_COPTS "${ABSL_MSVC_FLAGS};${ABSL_MSVC_TEST_FLAGS}")
+  set(ABSL_EXCEPTIONS_FLAG "${ABSL_MSVC_EXCEPTIONS_FLAGS}")
+else()
+  message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}.  Building with no default flags")
+  set(ABSL_DEFAULT_COPTS "")
+  set(ABSL_TEST_COPTS "")
+  set(ABSL_EXCEPTIONS_FLAG "")
+endif()
+
+# This flag is used internally for Bazel builds and is kept here for consistency
+set(ABSL_EXCEPTIONS_FLAG_LINKOPTS "")
+
+if("${CMAKE_CXX_STANDARD}" EQUAL 98)
+  message(FATAL_ERROR "Abseil requires at least C++11")
+elseif(NOT "${CMAKE_CXX_STANDARD}")
+  message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
+  set(ABSL_CXX_STANDARD 11)
+else()
+  set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
+endif()
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
new file mode 100644
index 0000000..9031bfa
--- /dev/null
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -0,0 +1,208 @@
+# GENERATED! DO NOT MANUALLY EDIT THIS FILE.
+#
+# (1) Edit absl/copts/copts.py.
+# (2) Run `python <path_to_absl>/copts/generate_copts.py`.
+
+list(APPEND ABSL_CLANG_CL_EXCEPTIONS_FLAGS
+    "/U_HAS_EXCEPTIONS"
+    "/D_HAS_EXCEPTIONS=1"
+    "/EHsc"
+)
+
+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-nested-anon-types"
+    "-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-undef"
+    "-Wno-unknown-warning-option"
+    "-Wno-unreachable-code"
+    "-Wno-unused-macros"
+    "-Wno-weak-vtables"
+    "-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"
+    "/D_SCL_SECURE_NO_WARNINGS"
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+)
+
+list(APPEND ABSL_CLANG_CL_TEST_FLAGS
+    "-Wno-c99-extensions"
+    "-Wno-missing-noreturn"
+    "-Wno-missing-prototypes"
+    "-Wno-missing-variable-declarations"
+    "-Wno-null-conversion"
+    "-Wno-shadow"
+    "-Wno-shift-sign-overflow"
+    "-Wno-sign-compare"
+    "-Wno-unused-function"
+    "-Wno-unused-member-function"
+    "-Wno-unused-parameter"
+    "-Wno-unused-private-field"
+    "-Wno-unused-template"
+    "-Wno-used-but-marked-unused"
+    "-Wno-zero-as-null-pointer-constant"
+    "-Wno-gnu-zero-variadic-macro-arguments"
+)
+
+list(APPEND ABSL_GCC_EXCEPTIONS_FLAGS
+    "-fexceptions"
+)
+
+list(APPEND ABSL_GCC_FLAGS
+    "-Wall"
+    "-Wextra"
+    "-Wcast-qual"
+    "-Wconversion-null"
+    "-Wmissing-declarations"
+    "-Woverlength-strings"
+    "-Wpointer-arith"
+    "-Wunused-local-typedefs"
+    "-Wunused-result"
+    "-Wvarargs"
+    "-Wvla"
+    "-Wwrite-strings"
+    "-Wno-missing-field-initializers"
+    "-Wno-sign-compare"
+)
+
+list(APPEND ABSL_GCC_TEST_FLAGS
+    "-Wno-conversion-null"
+    "-Wno-missing-declarations"
+    "-Wno-sign-compare"
+    "-Wno-unused-function"
+    "-Wno-unused-parameter"
+    "-Wno-unused-private-field"
+)
+
+list(APPEND ABSL_LLVM_EXCEPTIONS_FLAGS
+    "-fexceptions"
+)
+
+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-nested-anon-types"
+    "-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-undef"
+    "-Wno-unknown-warning-option"
+    "-Wno-unreachable-code"
+    "-Wno-unused-macros"
+    "-Wno-weak-vtables"
+    "-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"
+)
+
+list(APPEND ABSL_LLVM_TEST_FLAGS
+    "-Wno-c99-extensions"
+    "-Wno-missing-noreturn"
+    "-Wno-missing-prototypes"
+    "-Wno-missing-variable-declarations"
+    "-Wno-null-conversion"
+    "-Wno-shadow"
+    "-Wno-shift-sign-overflow"
+    "-Wno-sign-compare"
+    "-Wno-unused-function"
+    "-Wno-unused-member-function"
+    "-Wno-unused-parameter"
+    "-Wno-unused-private-field"
+    "-Wno-unused-template"
+    "-Wno-used-but-marked-unused"
+    "-Wno-zero-as-null-pointer-constant"
+    "-Wno-gnu-zero-variadic-macro-arguments"
+)
+
+list(APPEND ABSL_MSVC_EXCEPTIONS_FLAGS
+    "/U_HAS_EXCEPTIONS"
+    "/D_HAS_EXCEPTIONS=1"
+    "/EHsc"
+)
+
+list(APPEND ABSL_MSVC_FLAGS
+    "/W3"
+    "/DNOMINMAX"
+    "/DWIN32_LEAN_AND_MEAN"
+    "/D_CRT_SECURE_NO_WARNINGS"
+    "/D_SCL_SECURE_NO_WARNINGS"
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+    "/wd4005"
+    "/wd4068"
+    "/wd4180"
+    "/wd4244"
+    "/wd4267"
+    "/wd4800"
+)
+
+list(APPEND ABSL_MSVC_TEST_FLAGS
+    "/wd4018"
+    "/wd4101"
+    "/wd4503"
+)
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
new file mode 100644
index 0000000..e05a58e
--- /dev/null
+++ b/absl/copts/GENERATED_copts.bzl
@@ -0,0 +1,209 @@
+"""GENERATED! DO NOT MANUALLY EDIT THIS FILE.
+
+(1) Edit absl/copts/copts.py.
+(2) Run `python <path_to_absl>/copts/generate_copts.py`.
+"""
+
+ABSL_CLANG_CL_EXCEPTIONS_FLAGS = [
+    "/U_HAS_EXCEPTIONS",
+    "/D_HAS_EXCEPTIONS=1",
+    "/EHsc",
+]
+
+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-nested-anon-types",
+    "-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-undef",
+    "-Wno-unknown-warning-option",
+    "-Wno-unreachable-code",
+    "-Wno-unused-macros",
+    "-Wno-weak-vtables",
+    "-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",
+    "/D_SCL_SECURE_NO_WARNINGS",
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
+ABSL_CLANG_CL_TEST_FLAGS = [
+    "-Wno-c99-extensions",
+    "-Wno-missing-noreturn",
+    "-Wno-missing-prototypes",
+    "-Wno-missing-variable-declarations",
+    "-Wno-null-conversion",
+    "-Wno-shadow",
+    "-Wno-shift-sign-overflow",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-member-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+    "-Wno-unused-template",
+    "-Wno-used-but-marked-unused",
+    "-Wno-zero-as-null-pointer-constant",
+    "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+ABSL_GCC_EXCEPTIONS_FLAGS = [
+    "-fexceptions",
+]
+
+ABSL_GCC_FLAGS = [
+    "-Wall",
+    "-Wextra",
+    "-Wcast-qual",
+    "-Wconversion-null",
+    "-Wmissing-declarations",
+    "-Woverlength-strings",
+    "-Wpointer-arith",
+    "-Wunused-local-typedefs",
+    "-Wunused-result",
+    "-Wvarargs",
+    "-Wvla",
+    "-Wwrite-strings",
+    "-Wno-missing-field-initializers",
+    "-Wno-sign-compare",
+]
+
+ABSL_GCC_TEST_FLAGS = [
+    "-Wno-conversion-null",
+    "-Wno-missing-declarations",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+]
+
+ABSL_LLVM_EXCEPTIONS_FLAGS = [
+    "-fexceptions",
+]
+
+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-nested-anon-types",
+    "-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-undef",
+    "-Wno-unknown-warning-option",
+    "-Wno-unreachable-code",
+    "-Wno-unused-macros",
+    "-Wno-weak-vtables",
+    "-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",
+]
+
+ABSL_LLVM_TEST_FLAGS = [
+    "-Wno-c99-extensions",
+    "-Wno-missing-noreturn",
+    "-Wno-missing-prototypes",
+    "-Wno-missing-variable-declarations",
+    "-Wno-null-conversion",
+    "-Wno-shadow",
+    "-Wno-shift-sign-overflow",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-member-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+    "-Wno-unused-template",
+    "-Wno-used-but-marked-unused",
+    "-Wno-zero-as-null-pointer-constant",
+    "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+ABSL_MSVC_EXCEPTIONS_FLAGS = [
+    "/U_HAS_EXCEPTIONS",
+    "/D_HAS_EXCEPTIONS=1",
+    "/EHsc",
+]
+
+ABSL_MSVC_FLAGS = [
+    "/W3",
+    "/DNOMINMAX",
+    "/DWIN32_LEAN_AND_MEAN",
+    "/D_CRT_SECURE_NO_WARNINGS",
+    "/D_SCL_SECURE_NO_WARNINGS",
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+    "/wd4005",
+    "/wd4068",
+    "/wd4180",
+    "/wd4244",
+    "/wd4267",
+    "/wd4800",
+]
+
+ABSL_MSVC_TEST_FLAGS = [
+    "/wd4018",
+    "/wd4101",
+    "/wd4503",
+]
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
new file mode 100644
index 0000000..1655add
--- /dev/null
+++ b/absl/copts/configure_copts.bzl
@@ -0,0 +1,42 @@
+"""absl specific copts.
+
+This file simply selects the correct options from the generated files.  To
+change Abseil copts, edit absl/copts/copts.py
+"""
+
+load(
+    "//absl:copts/GENERATED_copts.bzl",
+    "ABSL_GCC_EXCEPTIONS_FLAGS",
+    "ABSL_GCC_FLAGS",
+    "ABSL_GCC_TEST_FLAGS",
+    "ABSL_LLVM_EXCEPTIONS_FLAGS",
+    "ABSL_LLVM_FLAGS",
+    "ABSL_LLVM_TEST_FLAGS",
+    "ABSL_MSVC_EXCEPTIONS_FLAGS",
+    "ABSL_MSVC_FLAGS",
+    "ABSL_MSVC_TEST_FLAGS",
+)
+
+ABSL_DEFAULT_COPTS = select({
+    "//absl:windows": ABSL_MSVC_FLAGS,
+    "//absl:llvm_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,
+    "//conditions:default": ABSL_GCC_TEST_FLAGS,
+})
+
+ABSL_EXCEPTIONS_FLAG = select({
+    "//absl:windows": ABSL_MSVC_EXCEPTIONS_FLAGS,
+    "//absl:llvm_compiler": ABSL_LLVM_EXCEPTIONS_FLAGS,
+    "//conditions:default": ABSL_GCC_EXCEPTIONS_FLAGS,
+})
+
+ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
+    "//conditions:default": [],
+})
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
new file mode 100644
index 0000000..3c9d429
--- /dev/null
+++ b/absl/copts/copts.py
@@ -0,0 +1,178 @@
+"""Abseil compiler options.
+
+This is the source of truth for Abseil compiler options.  To modify Abseil
+compilation options:
+
+  (1) Edit the appropriate list in this file based on the platform the flag is
+      needed on.
+  (2) Run `<path_to_absl>/copts/generate_copts.py`.
+
+The generated copts are consumed by configure_copts.bzl and
+AbseilConfigureCopts.cmake.
+"""
+
+# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
+MSVC_BIG_WARNING_FLAGS = [
+    "/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-nested-anon-types",
+    "-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-undef",
+    "-Wno-unknown-warning-option",
+    "-Wno-unreachable-code",
+    # Causes warnings on include guards
+    "-Wno-unused-macros",
+    "-Wno-weak-vtables",
+    ###
+    # 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-missing-noreturn",
+    "-Wno-missing-prototypes",
+    "-Wno-missing-variable-declarations",
+    "-Wno-null-conversion",
+    "-Wno-shadow",
+    "-Wno-shift-sign-overflow",
+    "-Wno-sign-compare",
+    "-Wno-unused-function",
+    "-Wno-unused-member-function",
+    "-Wno-unused-parameter",
+    "-Wno-unused-private-field",
+    "-Wno-unused-template",
+    "-Wno-used-but-marked-unused",
+    "-Wno-zero-as-null-pointer-constant",
+    # gtest depends on this GNU extension being offered.
+    "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+MSVC_STYLE_EXCEPTIONS_FLAGS = [
+    "/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"
+]
+
+MSVC_DEFINES = [
+    "/DNOMINMAX",  # Don't define min and max macros (windows.h)
+    # Don't bloat namespace with incompatible winsock versions.
+    "/DWIN32_LEAN_AND_MEAN",
+    # Don't warn about usage of insecure C functions.
+    "/D_CRT_SECURE_NO_WARNINGS",
+    "/D_SCL_SECURE_NO_WARNINGS",
+    # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage
+    "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
+COPT_VARS = {
+    "ABSL_GCC_FLAGS": [
+        "-Wall",
+        "-Wextra",
+        "-Wcast-qual",
+        "-Wconversion-null",
+        "-Wmissing-declarations",
+        "-Woverlength-strings",
+        "-Wpointer-arith",
+        "-Wunused-local-typedefs",
+        "-Wunused-result",
+        "-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",
+    ],
+    "ABSL_GCC_TEST_FLAGS": [
+        "-Wno-conversion-null",
+        "-Wno-missing-declarations",
+        "-Wno-sign-compare",
+        "-Wno-unused-function",
+        "-Wno-unused-parameter",
+        "-Wno-unused-private-field",
+    ],
+    "ABSL_GCC_EXCEPTIONS_FLAGS": ["-fexceptions"],
+    "ABSL_LLVM_FLAGS": LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS,
+    "ABSL_LLVM_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS,
+    "ABSL_LLVM_EXCEPTIONS_FLAGS": ["-fexceptions"],
+    "ABSL_CLANG_CL_FLAGS": (MSVC_BIG_WARNING_FLAGS +
+                            LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES),
+    "ABSL_CLANG_CL_TEST_FLAGS": LLVM_TEST_DISABLE_WARNINGS_FLAGS,
+    "ABSL_CLANG_CL_EXCEPTIONS_FLAGS": MSVC_STYLE_EXCEPTIONS_FLAGS,
+    "ABSL_MSVC_FLAGS": MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + [
+        "/wd4005",  # macro-redefinition
+        "/wd4068",  # unknown pragma
+        "/wd4180",  # qualifier applied to function type has no meaning; ignored
+        "/wd4244",  # conversion from 'type1' to 'type2', possible loss of data
+        "/wd4267",  # conversion from 'size_t' to 'type', possible loss of data
+        # forcing value to bool 'true' or 'false' (performance warning)
+        "/wd4800",
+    ],
+    "ABSL_MSVC_TEST_FLAGS": [
+        "/wd4018",  # signed/unsigned mismatch
+        "/wd4101",  # unreferenced local variable
+        "/wd4503",  # decorated name length exceeded, name was truncated
+    ],
+    "ABSL_MSVC_EXCEPTIONS_FLAGS": MSVC_STYLE_EXCEPTIONS_FLAGS,
+}
diff --git a/absl/copts/generate_copts.py b/absl/copts/generate_copts.py
new file mode 100755
index 0000000..28b677e
--- /dev/null
+++ b/absl/copts/generate_copts.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+"""Generate Abseil compile compile option configs.
+
+Usage: <path_to_absl>/copts/generate_copts.py
+
+The configs are generated from copts.py.
+"""
+
+from os import path
+import sys
+from copts import COPT_VARS
+
+
+# Helper functions
+def file_header_lines():
+  return [
+      "GENERATED! DO NOT MANUALLY EDIT THIS FILE.", "",
+      "(1) Edit absl/copts/copts.py.",
+      "(2) Run `python <path_to_absl>/copts/generate_copts.py`."
+  ]
+
+
+def flatten(*lists):
+  return [item for sublist in lists for item in sublist]
+
+
+def relative_filename(filename):
+  return path.join(path.dirname(__file__), filename)
+
+
+# Style classes.  These contain all the syntactic styling needed to generate a
+# copt file for different build tools.
+class CMakeStyle(object):
+  """Style object for CMake copts file."""
+
+  def separator(self):
+    return ""
+
+  def list_introducer(self, name):
+    return "list(APPEND " + name
+
+  def list_closer(self):
+    return ")\n"
+
+  def docstring(self):
+    return "\n".join((("# " + line).strip() for line in file_header_lines()))
+
+  def filename(self):
+    return "GENERATED_AbseilCopts.cmake"
+
+
+class StarlarkStyle(object):
+  """Style object for Starlark copts file."""
+
+  def separator(self):
+    return ","
+
+  def list_introducer(self, name):
+    return name + " = ["
+
+  def list_closer(self):
+    return "]\n"
+
+  def docstring(self):
+    docstring_quotes = "\"\"\""
+    return docstring_quotes + "\n".join(
+        flatten(file_header_lines(), [docstring_quotes]))
+
+  def filename(self):
+    return "GENERATED_copts.bzl"
+
+
+# Copt file generation
+def copt_list(name, arg_list, style):
+  make_line = lambda s: "    \"" + s + "\"" + style.separator()
+  external_str_list = [make_line(s) for s in arg_list]
+
+  return "\n".join(
+      flatten(
+          [style.list_introducer(name)],
+          external_str_list,
+          [style.list_closer()]))
+
+
+def generate_copt_file(style):
+  """Creates a generated copt file using the given style object.
+
+  Args:
+    style: either StarlarkStyle() or CMakeStyle()
+  """
+  with open(relative_filename(style.filename()), "w") as f:
+    f.write(style.docstring())
+    f.write("\n")
+    for var_name, arg_list in sorted(COPT_VARS.items()):
+      f.write("\n")
+      f.write(copt_list(var_name, arg_list, style))
+
+
+def main(argv):
+  if len(argv) > 1:
+    raise RuntimeError("generate_copts needs no command line args")
+
+  generate_copt_file(StarlarkStyle())
+  generate_copt_file(CMakeStyle())
+
+
+if __name__ == "__main__":
+  main(sys.argv)
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index e1e7fce..c9184f9 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -149,6 +149,7 @@
     copts = ABSL_DEFAULT_COPTS,
     deps = [
         "//absl/base",
+        "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
     ],
 )
@@ -180,22 +181,8 @@
 
 cc_library(
     name = "leak_check",
-    srcs = select({
-        # The leak checking interface depends on weak function
-        # declarations that may not necessarily have definitions.
-        # Windows doesn't support this, and ios requires
-        # guaranteed definitions for weak symbols.
-        "//absl:ios": [],
-        "//absl:windows": [],
-        "//conditions:default": [
-            "leak_check.cc",
-        ],
-    }),
-    hdrs = select({
-        "//absl:ios": [],
-        "//absl:windows": [],
-        "//conditions:default": ["leak_check.h"],
-    }),
+    srcs = ["leak_check.cc"],
+    hdrs = ["leak_check.h"],
     deps = ["//absl/base:core_headers"],
 )
 
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index 4af2ec8..dccd4a5 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,204 +14,292 @@
 # limitations under the License.
 #
 
-list(APPEND DEBUGGING_PUBLIC_HEADERS
-  "failure_signal_handler.h"
-  "leak_check.h"
-  "stacktrace.h"
-  "symbolize.h"
-)
-
-# TODO(cohenjon) The below is all kinds of wrong.  Make this match what we do in
-# Bazel
-list(APPEND DEBUGGING_INTERNAL_HEADERS
-  "internal/address_is_readable.h"
-  "internal/demangle.h"
-  "internal/elf_mem_image.h"
-  "internal/examine_stack.h"
-  "internal/stacktrace_config.h"
-  "internal/symbolize.h"
-  "internal/vdso_support.h"
-)
-
-list(APPEND DEBUGGING_INTERNAL_SRC
-  "internal/address_is_readable.cc"
-  "internal/elf_mem_image.cc"
-  "internal/vdso_support.cc"
-)
-
-
-list(APPEND STACKTRACE_SRC
-  "stacktrace.cc"
-  ${DEBUGGING_INTERNAL_SRC}
-  ${DEBUGGING_PUBLIC_HEADERS}
-  ${DEBUGGING_INTERNAL_HEADERS}
-)
-
-list(APPEND SYMBOLIZE_SRC
-  "symbolize.cc"
-  "symbolize_elf.inc"
-  "symbolize_unimplemented.inc"
-  "symbolize_win32.inc"
-  "internal/demangle.cc"
-  ${DEBUGGING_PUBLIC_HEADERS}
-  ${DEBUGGING_INTERNAL_HEADERS}
-  ${DEBUGGING_INTERNAL_SRC}
-)
-
-list(APPEND FAILURE_SIGNAL_HANDLER_SRC
-  "failure_signal_handler.cc"
-  ${DEBUGGING_PUBLIC_HEADERS}
-)
-
-list(APPEND EXAMINE_STACK_SRC
-  "internal/examine_stack.cc"
-  ${DEBUGGING_PUBLIC_HEADERS}
-  ${DEBUGGING_INTERNAL_HEADERS}
-)
-
-absl_library(
-  TARGET
-    absl_stacktrace
-  SOURCES
-    ${STACKTRACE_SRC}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     stacktrace
+  HDRS
+    "stacktrace.h"
+  SRCS
+    "stacktrace.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::debugging_internal
+    absl::base
+    absl::core_headers
+  PUBLIC
 )
 
-absl_library(
-  TARGET
-    absl_symbolize
-  SOURCES
-    ${SYMBOLIZE_SRC}
-  PUBLIC_LIBRARIES
-    absl::base
-    absl_malloc_internal
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     symbolize
-)
-
-absl_library(
-  TARGET
-    absl_failure_signal_handler
-  SOURCES
-    ${FAILURE_SIGNAL_HANDLER_SRC}
-  PUBLIC_LIBRARIES
-    absl_base absl::examine_stack absl::stacktrace absl_synchronization
-  EXPORT_NAME
-    failure_signal_handler
-)
-
-# Internal-only. Projects external to Abseil should not depend
-# directly on this library.
-absl_library(
-  TARGET
-    absl_examine_stack
-  SOURCES
-    ${EXAMINE_STACK_SRC}
-  EXPORT_NAME
-    examine_stack
-)
-
-list(APPEND LEAK_CHECK_SRC
-  "leak_check.cc"
-)
-
-
-# leak_check library
-absl_library(
-  TARGET
-    absl_leak_check
-  SOURCES
-    ${LEAK_CHECK_SRC}
-  PUBLIC_LIBRARIES
-    absl_base
-  EXPORT_NAME
-    leak_check
-)
-
-
-# component target
-absl_header_library(
-  TARGET
-    absl_debugging
-  PUBLIC_LIBRARIES
-    absl_stacktrace absl_leak_check
-  EXPORT_NAME
-    debugging
-)
-
-#
-## TESTS
-#
-
-list(APPEND STACK_CONSUMPTION_SRC
-  "internal/stack_consumption.cc"
-  "internal/stack_consumption.h"
-)
-
-absl_library(
-  TARGET
-    absl_stack_consumption
-  SOURCES
-    ${STACK_CONSUMPTION_SRC}
-)
-
-absl_test(
-  TARGET
-    absl_stack_consumption_test
-  SOURCES
-    "internal/stack_consumption_test.cc"
-  PUBLIC_LIBRARIES
-    absl_stack_consumption
+  HDRS
+    "symbolize.h"
+    "internal/symbolize.h"
+  SRCS
+    "symbolize.cc"
+    "symbolize_elf.inc"
+    "symbolize_unimplemented.inc"
+    "symbolize_win32.inc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::debugging_internal
+    absl::demangle_internal
     absl::base
+    absl::core_headers
+    absl::malloc_internal
+  PUBLIC
 )
 
-list(APPEND DEMANGLE_TEST_SRC "internal/demangle_test.cc")
-
-absl_test(
-  TARGET
-    demangle_test
-  SOURCES
-    ${DEMANGLE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl_symbolize absl_stack_consumption
-)
-
-list(APPEND SYMBOLIZE_TEST_SRC "symbolize_test.cc")
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     symbolize_test
-  SOURCES
-    ${SYMBOLIZE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl::base absl::memory absl_symbolize absl_stack_consumption
+  SRCS
+    "symbolize_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::stack_consumption
+    absl::symbolize
+    absl::base
+    absl::core_headers
+    absl::memory
+    gmock
 )
 
-list(APPEND FAILURE_SIGNAL_HANDLER_TEST_SRC "failure_signal_handler_test.cc")
+absl_cc_library(
+  NAME
+    examine_stack
+  HDRS
+    "internal/examine_stack.h"
+  SRCS
+    "internal/examine_stack.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::stacktrace
+    absl::symbolize
+    absl::base
+    absl::core_headers
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    failure_signal_handler
+  HDRS
+    "failure_signal_handler.h"
+  SRCS
+    "failure_signal_handler.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::examine_stack
+    absl::stacktrace
+    absl::base
+    absl::config
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
     failure_signal_handler_test
-  SOURCES
-    ${FAILURE_SIGNAL_HANDLER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl_examine_stack
-    absl_failure_signal_handler
-    absl_stacktrace
-    absl_symbolize
+  SRCS
+    "failure_signal_handler_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::failure_signal_handler
+    absl::stacktrace
+    absl::symbolize
     absl::base
     absl::strings
+    Threads::Threads
+    gmock
 )
 
-# test leak_check_test
-list(APPEND LEAK_CHECK_TEST_SRC "leak_check_test.cc")
+absl_cc_library(
+  NAME
+    debugging_internal
+  HDRS
+    "internal/address_is_readable.h"
+    "internal/elf_mem_image.h"
+    "internal/stacktrace_aarch64-inl.inc"
+    "internal/stacktrace_arm-inl.inc"
+    "internal/stacktrace_config.h"
+    "internal/stacktrace_generic-inl.inc"
+    "internal/stacktrace_powerpc-inl.inc"
+    "internal/stacktrace_unimplemented-inl.inc"
+    "internal/stacktrace_win32-inl.inc"
+    "internal/stacktrace_x86-inl.inc"
+    "internal/vdso_support.h"
+  SRCS
+    "internal/address_is_readable.cc"
+    "internal/elf_mem_image.cc"
+    "internal/vdso_support.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::dynamic_annotations
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    demangle_internal
+  HDRS
+    "internal/demangle.h"
+  SRCS
+    "internal/demangle.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    demangle_test
+  SRCS
+    "internal/demangle_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::demangle_internal
+    absl::stack_consumption
+    absl::base
+    absl::core_headers
+    absl::memory
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    leak_check
+  HDRS
+    "leak_check.h"
+  SRCS
+    "leak_check.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    leak_check_disable
+  SRCS
+    "leak_check_disable.cc"
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    leak_check_api_enabled_for_testing
+  HDRS
+    "leak_check.h"
+  SRCS
+    "leak_check.cc"
+  COPTS
+    $<$<BOOL:${ABSL_HAVE_LSAN}>:-DLEAK_SANITIZER>
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    leak_check_api_disabled_for_testing
+  HDRS
+    "leak_check.h"
+  SRCS
+    "leak_check.cc"
+  COPTS
+    "-ULEAK_SANITIZER"
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
     leak_check_test
-  SOURCES
-    ${LEAK_CHECK_TEST_SRC}
-  PUBLIC_LIBRARIES
-    absl_leak_check
+  SRCS
+    "leak_check_test.cc"
+  COPTS
+    "$<$<BOOL:${ABSL_HAVE_LSAN}>:-DABSL_EXPECT_LEAK_SANITIZER>"
+  LINKOPTS
+    "${ABSL_LSAN_LINKOPTS}"
+  DEPS
+    absl::leak_check_api_enabled_for_testing
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    leak_check_no_lsan_test
+  SRCS
+    "leak_check_test.cc"
+  COPTS
+    "-UABSL_EXPECT_LEAK_SANITIZER"
+  DEPS
+    absl::leak_check_api_disabled_for_testing
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    disabled_leak_check_test
+  SRCS
+    "leak_check_fail_test.cc"
+  LINKOPTS
+    "${ABSL_LSAN_LINKOPTS}"
+  DEPS
+    absl::leak_check_api_enabled_for_testing
+    absl::leak_check_disable
+    absl::base
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    stack_consumption
+  HDRS
+    "internal/stack_consumption.h"
+  SRCS
+    "internal/stack_consumption.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    stack_consumption_test
+  SRCS
+    "internal/stack_consumption_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::stack_consumption
+    absl::base
+    absl::core_headers
+    gmock_main
+)
+
+# component target
+absl_cc_library(
+  NAME
+    debugging
+  DEPS
+    absl::stacktrace
+    absl::leak_check
+  PUBLIC
 )
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc
index d4b957b..c6a4d96 100644
--- a/absl/debugging/failure_signal_handler.cc
+++ b/absl/debugging/failure_signal_handler.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -119,7 +119,11 @@
 #ifndef _WIN32
 
 static bool SetupAlternateStackOnce() {
+#if defined(__wasm__) || defined (__asjms__)
   const size_t page_mask = getpagesize() - 1;
+#else
+  const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
+#endif
   size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
     defined(THREAD_SANITIZER)
diff --git a/absl/debugging/failure_signal_handler.h b/absl/debugging/failure_signal_handler.h
index c57954e..1beb78b 100644
--- a/absl/debugging/failure_signal_handler.h
+++ b/absl/debugging/failure_signal_handler.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/failure_signal_handler_test.cc b/absl/debugging/failure_signal_handler_test.cc
index ba52091..bb2cc48 100644
--- a/absl/debugging/failure_signal_handler_test.cc
+++ b/absl/debugging/failure_signal_handler_test.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -133,16 +133,17 @@
 };
 
 std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
-  std::string result = absl::debugging_internal::FailureSignalToString(info.param);
+  std::string result =
+      absl::debugging_internal::FailureSignalToString(info.param);
   if (result.empty()) {
     result = absl::StrCat(info.param);
   }
   return result;
 }
 
-INSTANTIATE_TEST_CASE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
-                        ::testing::ValuesIn(kFailureSignals),
-                        SignalParamToString);
+INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
+                         ::testing::ValuesIn(kFailureSignals),
+                         SignalParamToString);
 
 #endif  // GTEST_HAS_DEATH_TEST
 
diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc
index 7455aa0..99c4c64 100644
--- a/absl/debugging/internal/address_is_readable.cc
+++ b/absl/debugging/internal/address_is_readable.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h
index 9d48030..ca8003e 100644
--- a/absl/debugging/internal/address_is_readable.h
+++ b/absl/debugging/internal/address_is_readable.h
@@ -4,14 +4,13 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
 #define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 4835445..52a553f 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -749,8 +749,8 @@
 // <local-source-name> ::= L <source-name> [<discriminator>]
 //
 // References:
-//   http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
-//   http://gcc.gnu.org/viewcvs?view=rev&revision=124467
+//   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
+//   https://gcc.gnu.org/viewcvs?view=rev&revision=124467
 static bool ParseLocalSourceName(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
@@ -1168,6 +1168,12 @@
   }
   state->parse_state = copy;
 
+  // nullptr_t, i.e. decltype(nullptr).
+  if (ParseTwoCharToken(state, "Dn")) {
+    return true;
+  }
+  state->parse_state = copy;
+
   if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
       ParseType(state)) {
     return true;
@@ -1636,6 +1642,15 @@
   }
   state->parse_state = copy;
 
+  // Pointer-to-member access expressions.  This parses the same as a binary
+  // operator, but it's implemented separately because "ds" shouldn't be
+  // accepted in other contexts that parse an operator name.
+  if (ParseTwoCharToken(state, "ds") && ParseExpression(state) &&
+      ParseExpression(state)) {
+    return true;
+  }
+  state->parse_state = copy;
+
   // Parameter pack expansion
   if (ParseTwoCharToken(state, "sp") && ParseExpression(state)) {
     return true;
diff --git a/absl/debugging/internal/demangle.h b/absl/debugging/internal/demangle.h
index 2e75564..81bb0df 100644
--- a/absl/debugging/internal/demangle.h
+++ b/absl/debugging/internal/demangle.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index b9d9008..883b92d 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -176,6 +176,7 @@
 TEST(DemangleRegression, NegativeLength) {
   TestOnInput("_ZZn4");
 }
+
 TEST(DemangleRegression, DeeplyNestedArrayType) {
   const int depth = 100000;
   std::string data = "_ZStI";
diff --git a/absl/debugging/internal/elf_mem_image.cc b/absl/debugging/internal/elf_mem_image.cc
index 3f747e7..e7408bc 100644
--- a/absl/debugging/internal/elf_mem_image.cc
+++ b/absl/debugging/internal/elf_mem_image.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/elf_mem_image.h b/absl/debugging/internal/elf_mem_image.h
index 3b57726..99b3758 100644
--- a/absl/debugging/internal/elf_mem_image.h
+++ b/absl/debugging/internal/elf_mem_image.h
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *      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,
diff --git a/absl/debugging/internal/examine_stack.cc b/absl/debugging/internal/examine_stack.cc
index faf8883..1ebc788 100644
--- a/absl/debugging/internal/examine_stack.cc
+++ b/absl/debugging/internal/examine_stack.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/examine_stack.h b/absl/debugging/internal/examine_stack.h
index a16c03b..56c9763 100644
--- a/absl/debugging/internal/examine_stack.h
+++ b/absl/debugging/internal/examine_stack.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/stack_consumption.cc b/absl/debugging/internal/stack_consumption.cc
index 2b3b972..4b05f49 100644
--- a/absl/debugging/internal/stack_consumption.cc
+++ b/absl/debugging/internal/stack_consumption.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/stack_consumption.h b/absl/debugging/internal/stack_consumption.h
index 4c5fa0f..b860a3c 100644
--- a/absl/debugging/internal/stack_consumption.h
+++ b/absl/debugging/internal/stack_consumption.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/stack_consumption_test.cc b/absl/debugging/internal/stack_consumption_test.cc
index 5ce3846..68bfa12 100644
--- a/absl/debugging/internal/stack_consumption_test.cc
+++ b/absl/debugging/internal/stack_consumption_test.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index dd713da..d4e8480 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *      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,
@@ -41,8 +41,9 @@
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_aarch64-inl.inc"
 # elif defined(__arm__)
+// Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_arm-inl.inc"
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
 # else
 #define ABSL_STACKTRACE_INL_HEADER \
    "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc
index 2c9ca41..2e876fe 100644
--- a/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -12,13 +12,48 @@
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
 
 #include <execinfo.h>
+#include <atomic>
 #include <cstring>
 
 #include "absl/debugging/stacktrace.h"
 
+// Sometimes, we can try to get a stack trace from within a stack
+// trace, because we don't block signals inside this code (which would be too
+// expensive: the two extra system calls per stack trace do matter here).
+// That can cause a self-deadlock.
+// Protect against such reentrant call by failing to get a stack trace.
+//
+// We use __thread here because the code here is extremely low level -- it is
+// called while collecting stack traces from within malloc and mmap, and thus
+// can not call anything which might call malloc or mmap itself.
+static __thread int recursive = 0;
+
+// The stack trace function might be invoked very early in the program's
+// execution (e.g. from the very first malloc if using tcmalloc). Also, the
+// 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.
+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,
                       const void *ucp, int *min_dropped_frames) {
+  if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
+    return 0;
+  }
+  ++recursive;
+
+  static_cast<void>(ucp);  // Unused.
   static const int kStackLength = 64;
   void * stack[kStackLength];
   int size;
@@ -45,6 +80,8 @@
     }
   }
 
+  --recursive;
+
   return result_count;
 }
 
diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc
index 860ac2b..9e0f2aa 100644
--- a/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -14,8 +14,8 @@
 //
 // Produce stack trace.  I'm guessing (hoping!) the code is much like
 // for x86.  For apple machines, at least, it seems to be; see
-//    http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
-//    http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
+//    https://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
+//    https://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
 // Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
 
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
diff --git a/absl/debugging/internal/stacktrace_win32-inl.inc b/absl/debugging/internal/stacktrace_win32-inl.inc
index a8f8a56..b46491f 100644
--- a/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -32,7 +32,7 @@
 // server.
 //
 // This code is inspired by a patch from David Vitek:
-//   http://code.google.com/p/google-perftools/issues/detail?id=83
+//   https://code.google.com/p/google-perftools/issues/detail?id=83
 
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc
index ac85b92..25aa8bd 100644
--- a/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -33,6 +33,7 @@
 #include "absl/debugging/internal/address_is_readable.h"
 #include "absl/debugging/internal/vdso_support.h"  // a no-op on non-elf or non-glibc systems
 #include "absl/debugging/stacktrace.h"
+
 #include "absl/base/internal/raw_logging.h"
 
 #if defined(__linux__) && defined(__i386__)
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index 8d926fe..3e53789 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -20,7 +20,6 @@
 
 #include <cstddef>
 #include <cstdint>
-#include "absl/base/port.h"  // Needed for string vs std::string
 
 #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
 #error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set
@@ -42,9 +41,9 @@
 // Returns true on success; otherwise returns false in case of errors.
 //
 // This is not async-signal-safe.
-bool ForEachSection(
-    int fd, const std::function<bool(const std::string& name, const ElfW(Shdr) &)>&
-                callback);
+bool ForEachSection(int fd,
+                    const std::function<bool(const std::string& name,
+                                             const ElfW(Shdr) &)>& callback);
 
 // Gets the section header for the given name, if it exists. Returns true on
 // success. Otherwise, returns false.
diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc
index e8129e8..23c3084 100644
--- a/absl/debugging/internal/vdso_support.cc
+++ b/absl/debugging/internal/vdso_support.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/internal/vdso_support.h b/absl/debugging/internal/vdso_support.h
index 8002c74..9895b48 100644
--- a/absl/debugging/internal/vdso_support.h
+++ b/absl/debugging/internal/vdso_support.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc
index e01e5f8..ffe3d1b 100644
--- a/absl/debugging/leak_check.cc
+++ b/absl/debugging/leak_check.cc
@@ -4,13 +4,14 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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.
+
 // Wrappers around lsan_interface functions.
 // When lsan is not linked in, these functions are not available,
 // therefore Abseil code which depends on these functions is conditioned on the
diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h
index c930684..4d489c5 100644
--- a/absl/debugging/leak_check.h
+++ b/absl/debugging/leak_check.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/leak_check_disable.cc b/absl/debugging/leak_check_disable.cc
index df22c1c..924d6e3 100644
--- a/absl/debugging/leak_check_disable.cc
+++ b/absl/debugging/leak_check_disable.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/leak_check_fail_test.cc b/absl/debugging/leak_check_fail_test.cc
index bf541fe..2887cea 100644
--- a/absl/debugging/leak_check_fail_test.cc
+++ b/absl/debugging/leak_check_fail_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/leak_check_test.cc b/absl/debugging/leak_check_test.cc
index febd1ee..93a7edd 100644
--- a/absl/debugging/leak_check_test.cc
+++ b/absl/debugging/leak_check_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc
index 463fad2..9de8782 100644
--- a/absl/debugging/stacktrace.cc
+++ b/absl/debugging/stacktrace.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -46,6 +46,7 @@
 #include ABSL_STACKTRACE_INL_HEADER
 #else
 # error Cannot calculate stack trace: will need to write for your environment
+
 # include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
 # include "absl/debugging/internal/stacktrace_arm-inl.inc"
 # include "absl/debugging/internal/stacktrace_generic-inl.inc"
@@ -80,29 +81,29 @@
 
 }  // anonymous namespace
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackFrames(void** result, int* sizes, int max_depth, int skip_count) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(
+    void** result, int* sizes, int max_depth, int skip_count) {
   return Unwind<true, false>(result, sizes, max_depth, skip_count, nullptr,
                              nullptr);
 }
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
-                              int skip_count, const void* uc,
-                              int* min_dropped_frames) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
+GetStackFramesWithContext(void** result, int* sizes, int max_depth,
+                          int skip_count, const void* uc,
+                          int* min_dropped_frames) {
   return Unwind<true, true>(result, sizes, max_depth, skip_count, uc,
                             min_dropped_frames);
 }
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackTrace(void** result, int max_depth, int skip_count) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(
+    void** result, int max_depth, int skip_count) {
   return Unwind<false, false>(result, nullptr, max_depth, skip_count, nullptr,
                               nullptr);
 }
 
-ABSL_ATTRIBUTE_NOINLINE
-int GetStackTraceWithContext(void** result, int max_depth, int skip_count,
-                             const void* uc, int* min_dropped_frames) {
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
+GetStackTraceWithContext(void** result, int max_depth, int skip_count,
+                         const void* uc, int* min_dropped_frames) {
   return Unwind<false, true>(result, nullptr, max_depth, skip_count, uc,
                              min_dropped_frames);
 }
diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h
index 8b831e2..3fc1c03 100644
--- a/absl/debugging/stacktrace.h
+++ b/absl/debugging/stacktrace.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index a35e24c..24e3a7f 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/symbolize.h b/absl/debugging/symbolize.h
index 24e6e64..a73dbd9 100644
--- a/absl/debugging/symbolize.h
+++ b/absl/debugging/symbolize.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index b16a42a..34def5c 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -333,7 +333,11 @@
 }  // namespace
 
 static int SymbolizerSize() {
+#if defined(__wasm__) || defined(__asmjs__)
   int pagesize = getpagesize();
+#else
+  int pagesize = sysconf(_SC_PAGESIZE);
+#endif
   return ((sizeof(Symbolizer) - 1) / pagesize + 1) * pagesize;
 }
 
@@ -921,6 +925,14 @@
   return p;
 }
 
+// Normally we are only interested in "r?x" maps.
+// On the PowerPC, function pointers point to descriptors in the .opd
+// section.  The descriptors themselves are not executable code, so
+// we need to relax the check below to "r??".
+static bool ShouldUseMapping(const char *const flags) {
+  return flags[0] == 'r' && (kPlatformUsesOPDSections || flags[2] == 'x');
+}
+
 // Read /proc/self/maps and run "callback" for each mmapped file found.  If
 // "callback" returns false, stop scanning and return true. Else continue
 // scanning /proc/self/maps. Return true if no parse error is found.
@@ -990,12 +1002,8 @@
       return false;
     }
 
-    // Check flags.  Normally we are only interested in "r-x" maps.  On
-    // the PowerPC, function pointers point to descriptors in the .opd
-    // section.  The descriptors themselves are not executable code.  So
-    // we need to relax the check below to "r**".
-    if (memcmp(flags_start, "r-x", 3) != 0 &&  // Not a "r-x" map.
-        !(kPlatformUsesOPDSections && flags_start[0] == 'r')) {
+    // Check flags.
+    if (!ShouldUseMapping(flags_start)) {
       continue;  // We skip this map.
     }
     ++cursor;  // Skip ' '.
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index 8029fbe..fc3ed93 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -392,16 +392,20 @@
 extern "C" {
 inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {
   void *pc = nullptr;
-#if defined(__i386__) || defined(__x86_64__)
-  __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#if defined(__i386__)
+  __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
+#elif defined(__x86_64__)
+  __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
 #endif
   return pc;
 }
 
 void *ABSL_ATTRIBUTE_NOINLINE non_inline_func() {
   void *pc = nullptr;
-#if defined(__i386__) || defined(__x86_64__)
-  __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#if defined(__i386__)
+  __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
+#elif defined(__x86_64__)
+  __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
 #endif
   return pc;
 }
diff --git a/absl/debugging/symbolize_unimplemented.inc b/absl/debugging/symbolize_unimplemented.inc
index 2a3f4ac..7c580fe 100644
--- a/absl/debugging/symbolize_unimplemented.inc
+++ b/absl/debugging/symbolize_unimplemented.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -26,6 +26,9 @@
 bool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) {
   return false;
 }
+bool GetFileMappingHint(const void **, const void **, uint64_t *, const char **) {
+  return false;
+}
 
 }  // namespace debugging_internal
 
diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc
index e3fff74..17ea618 100644
--- a/absl/debugging/symbolize_win32.inc
+++ b/absl/debugging/symbolize_win32.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index 50aa550..69860d9 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -93,7 +93,6 @@
     srcs = ["internal/city.cc"],
     hdrs = [
         "internal/city.h",
-        "internal/city_crc.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
diff --git a/absl/hash/BUILD.gn b/absl/hash/BUILD.gn
index 40b6b3a..cbe3abf 100644
--- a/absl/hash/BUILD.gn
+++ b/absl/hash/BUILD.gn
@@ -91,7 +91,6 @@
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   public = [
     "internal/city.h",
-    "internal/city_crc.h",
   ]
   sources = [
     "internal/city.cc",
diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt
index 35081e3..4cafc13 100644
--- a/absl/hash/CMakeLists.txt
+++ b/absl/hash/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,67 +14,98 @@
 # limitations under the License.
 #
 
-list(APPEND HASH_PUBLIC_HEADERS
-  "hash.h"
-)
-
-list(APPEND HASH_INTERNAL_HEADERS
-  "internal/city.h"
-  "internal/city_crc.h"
-  "internal/hash.h"
-)
-
-# absl_hash library
-list(APPEND HASH_SRC
-  "internal/city.cc"
-  "internal/hash.cc"
-  ${HASH_PUBLIC_HEADERS}
-  ${HASH_INTERNAL_HEADERS}
-)
-
-set(HASH_PUBLIC_LIBRARIES absl::hash absl::container absl::strings absl::str_format absl::utility)
-
-absl_library(
-  TARGET
-    absl_hash
-  SOURCES
-    ${HASH_SRC}
-  PUBLIC_LIBRARIES
-    ${HASH_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     hash
+  HDRS
+    "hash.h"
+  SRCS
+    "internal/hash.cc"
+    "internal/hash.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::endian
+    absl::fixed_array
+    absl::meta
+    absl::int128
+    absl::strings
+    absl::optional
+    absl::variant
+    absl::utility
+    absl::city
+  PUBLIC
 )
 
-#
-## TESTS
-#
+absl_cc_library(
+  NAME
+    hash_testing
+  HDRS
+    "hash_testing.h"
+  DEPS
+    absl::spy_hash_state
+    absl::meta
+    absl::strings
+    absl::variant
+    gmock
+  TESTONLY
+)
 
-# testing support
-set(HASH_TEST_HEADERS hash_testing.h internal/spy_hash_state.h)
-set(HASH_TEST_PUBLIC_LIBRARIES absl::hash absl::container absl::numeric absl::strings absl::str_format)
-
-# hash_test
-set(HASH_TEST_SRC "hash_test.cc" ${HASH_TEST_HEADERS})
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     hash_test
-  SOURCES
-    ${HASH_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${HASH_TEST_PUBLIC_LIBRARIES}
+  SRCS
+   "hash_test.cc"
+  DEPS
+    absl::hash
+    absl::hash_testing
+    absl::core_headers
+    absl::flat_hash_set
+    absl::spy_hash_state
+    absl::meta
+    absl::int128
+    gmock_main
 )
 
-# hash_test
-set(CITY_TEST_SRC "internal/city_test.cc")
+absl_cc_library(
+  NAME
+    spy_hash_state
+  HDRS
+    "internal/spy_hash_state.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hash
+    absl::strings
+    absl::str_format
+  TESTONLY
+)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    city
+  HDRS
+    "internal/city.h"
+  SRCS
+    "internal/city.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::endian
+)
+
+absl_cc_test(
+  NAME
     city_test
-  SOURCES
-    ${CITY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${HASH_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/city_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::city
+    gmock_main
 )
 
-
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index c7ba4c2..c0ede35 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -25,8 +25,8 @@
 //   * `AbslHashValue`, an extension point that allows you to extend types to
 //     support Abseil hashing without requiring you to define a hashing
 //     algorithm.
-//   * `HashState`, a type-erased class which implement the manipulation of the
-//     hash state (H) itself. containing member functions `combine()` and
+//   * `HashState`, a type-erased class which implements the manipulation of the
+//     hash state (H) itself, contains member functions `combine()` and
 //     `combine_contiguous()`, which you can use to contribute to an existing
 //     hash state when hashing your types.
 //
@@ -69,7 +69,7 @@
 // `absl::Hash`
 // -----------------------------------------------------------------------------
 //
-// `absl::Hash<T>` is a convenient general-purpose hash functor for a type `T`
+// `absl::Hash<T>` is a convenient general-purpose hash functor for any type `T`
 // satisfying any of the following conditions (in order):
 //
 //  * T is an arithmetic or pointer type
@@ -98,7 +98,7 @@
 //    * absl::string_view
 //    * absl::InlinedVector
 //    * absl::FixedArray
-//    * absl::unit128
+//    * absl::uint128
 //    * absl::Time, absl::Duration, and absl::TimeZone
 //
 // Note: the list above is not meant to be exhaustive. Additional type support
@@ -142,7 +142,7 @@
 //
 // The "hash state" concept contains two member functions for mixing hash state:
 //
-// * `H::combine()`
+// * `H::combine(state, values...)`
 //
 //   Combines an arbitrary number of values into a hash state, returning the
 //   updated state. Note that the existing hash state is move-only and must be
@@ -160,7 +160,7 @@
 //     state = H::combine(std::move(state), value2);
 //     state = H::combine(std::move(state), value3);
 //
-// * `H::combine_contiguous()`
+// * `H::combine_contiguous(state, data, size)`
 //
 //    Combines a contiguous array of `size` elements into a hash state,
 //    returning the updated state. Note that the existing hash state is
@@ -243,7 +243,7 @@
 //       absl::HashState::combine(std::move(state), v1_, v2_);
 //     }
 //     int v1_;
-//     string v2_;
+//     std::string v2_;
 //   };
 class HashState : public hash_internal::HashStateBase<HashState> {
  public:
@@ -309,4 +309,5 @@
 };
 
 }  // namespace absl
+
 #endif  // ABSL_HASH_HASH_H_
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 7b6fb2e..af95938 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -15,6 +15,7 @@
 #include "absl/hash/hash.h"
 
 #include <array>
+#include <bitset>
 #include <cstring>
 #include <deque>
 #include <forward_list>
@@ -50,7 +51,7 @@
 template <typename T>
 class HashValueIntTest : public testing::Test {
 };
-TYPED_TEST_CASE_P(HashValueIntTest);
+TYPED_TEST_SUITE_P(HashValueIntTest);
 
 template <typename T>
 SpyHashState SpyHash(const T& value) {
@@ -84,6 +85,345 @@
                                 uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
 
+enum LegacyEnum { kValue1, kValue2, kValue3 };
+
+enum class EnumClass { kValue4, kValue5, kValue6 };
+
+TEST(HashValueTest, EnumAndBool) {
+  EXPECT_TRUE((is_hashable<LegacyEnum>::value));
+  EXPECT_TRUE((is_hashable<EnumClass>::value));
+  EXPECT_TRUE((is_hashable<bool>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(true, false)));
+}
+
+TEST(HashValueTest, FloatingPoint) {
+  EXPECT_TRUE((is_hashable<float>::value));
+  EXPECT_TRUE((is_hashable<double>::value));
+  EXPECT_TRUE((is_hashable<long double>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),
+                      -std::numeric_limits<float>::infinity())));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),
+                      -std::numeric_limits<double>::infinity())));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      // Add some values with small exponent to test that NORMAL values also
+      // append their category.
+      .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,
+      17 * static_cast<long double>(std::numeric_limits<double>::max()),
+      std::numeric_limits<long double>::infinity(),
+      -std::numeric_limits<long double>::infinity())));
+}
+
+TEST(HashValueTest, Pointer) {
+  EXPECT_TRUE((is_hashable<int*>::value));
+
+  int i;
+  int* ptr = &i;
+  int* n = nullptr;
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
+}
+
+TEST(HashValueTest, PointerAlignment) {
+  // We want to make sure that pointer alignment will not cause bits to be
+  // stuck.
+
+  constexpr size_t kTotalSize = 1 << 20;
+  std::unique_ptr<char[]> data(new char[kTotalSize]);
+  constexpr size_t kLog2NumValues = 5;
+  constexpr size_t kNumValues = 1 << kLog2NumValues;
+
+  for (size_t align = 1; align < kTotalSize / kNumValues;
+       align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
+    SCOPED_TRACE(align);
+    ASSERT_LE(align * kNumValues, kTotalSize);
+
+    size_t bits_or = 0;
+    size_t bits_and = ~size_t{};
+
+    for (size_t i = 0; i < kNumValues; ++i) {
+      size_t hash = absl::Hash<void*>()(data.get() + i * align);
+      bits_or |= hash;
+      bits_and &= hash;
+    }
+
+    // Limit the scope to the bits we would be using for Swisstable.
+    constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
+    size_t stuck_bits = (~bits_or | bits_and) & kMask;
+    EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits;
+  }
+}
+
+TEST(HashValueTest, PairAndTuple) {
+  EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
+  EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
+  EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));
+  EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),
+      std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),
+                      std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),
+                      std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),
+                      std::make_tuple(0, 0, -42))));
+
+  // Test that tuples of lvalue references work (so we need a few lvalues):
+  int a = 0, b = 1, c = 17, d = 23;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));
+
+  // Test that tuples of rvalue references work:
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),
+      std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),
+      std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
+      std::forward_as_tuple(0, 0, -42))));
+}
+
+TEST(HashValueTest, CombineContiguousWorks) {
+  std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
+  std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};
+
+  auto vh1 = SpyHash(v1);
+  auto vh2 = SpyHash(v2);
+  EXPECT_NE(vh1, vh2);
+}
+
+struct DummyDeleter {
+  template <typename T>
+  void operator() (T* ptr) {}
+};
+
+struct SmartPointerEq {
+  template <typename T, typename U>
+  bool operator()(const T& t, const U& u) const {
+    return GetPtr(t) == GetPtr(u);
+  }
+
+  template <typename T>
+  static auto GetPtr(const T& t) -> decltype(&*t) {
+    return t ? &*t : nullptr;
+  }
+
+  static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }
+};
+
+TEST(HashValueTest, SmartPointers) {
+  EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));
+  EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));
+  EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));
+
+  int i, j;
+  std::unique_ptr<int, DummyDeleter> unique1(&i);
+  std::unique_ptr<int, DummyDeleter> unique2(&i);
+  std::unique_ptr<int, DummyDeleter> unique_other(&j);
+  std::unique_ptr<int, DummyDeleter> unique_null;
+
+  std::shared_ptr<int> shared1(&i, DummyDeleter());
+  std::shared_ptr<int> shared2(&i, DummyDeleter());
+  std::shared_ptr<int> shared_other(&j, DummyDeleter());
+  std::shared_ptr<int> shared_null;
+
+  // Sanity check of the Eq function.
+  ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));
+  ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));
+  ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));
+  ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::forward_as_tuple(&i, nullptr,                    //
+                            unique1, unique2, unique_null,  //
+                            absl::make_unique<int>(),       //
+                            shared1, shared2, shared_null,  //
+                            std::make_shared<int>()),
+      SmartPointerEq{}));
+}
+
+TEST(HashValueTest, FunctionPointer) {
+  using Func = int (*)();
+  EXPECT_TRUE(is_hashable<Func>::value);
+
+  Func p1 = [] { return 2; }, p2 = [] { return 1; };
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(p1, p2, nullptr)));
+}
+
+struct WrapInTuple {
+  template <typename T>
+  std::tuple<int, T, size_t> operator()(const T& t) const {
+    return std::make_tuple(7, t, 0xdeadbeef);
+  }
+};
+
+TEST(HashValueTest, Strings) {
+  EXPECT_TRUE((is_hashable<std::string>::value));
+
+  const std::string small = "foo";
+  const std::string dup = "foofoo";
+  const std::string large = "large";
+  const std::string huge = std::string(5000, 'a');
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::string(), absl::string_view(),
+      std::string(""), absl::string_view(""),
+      std::string(small), absl::string_view(small),
+      std::string(dup), absl::string_view(dup),
+      std::string(large), absl::string_view(large),
+      std::string(huge), absl::string_view(huge))));
+
+  // Also check that nested types maintain the same hash.
+  const WrapInTuple t{};
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      //
+      t(std::string()), t(absl::string_view()),
+      t(std::string("")), t(absl::string_view("")),
+      t(std::string(small)), t(absl::string_view(small)),
+      t(std::string(dup)), t(absl::string_view(dup)),
+      t(std::string(large)), t(absl::string_view(large)),
+      t(std::string(huge)), t(absl::string_view(huge)))));
+
+  // Make sure that hashing a `const char*` does not use its std::string-value.
+  EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
+            SpyHash(absl::string_view("ABC")));
+}
+
+TEST(HashValueTest, StdArray) {
+  EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
+}
+
+TEST(HashValueTest, StdBitset) {
+  EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"),
+       std::bitset<2>("11")}));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()}));
+
+  constexpr int kNumBits = 256;
+  std::array<std::string, 6> bit_strings;
+  bit_strings.fill(std::string(kNumBits, '1'));
+  bit_strings[1][0] = '0';
+  bit_strings[2][1] = '0';
+  bit_strings[3][kNumBits / 3] = '0';
+  bit_strings[4][kNumBits - 2] = '0';
+  bit_strings[5][kNumBits - 1] = '0';
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {std::bitset<kNumBits>(bit_strings[0].c_str()),
+       std::bitset<kNumBits>(bit_strings[1].c_str()),
+       std::bitset<kNumBits>(bit_strings[2].c_str()),
+       std::bitset<kNumBits>(bit_strings[3].c_str()),
+       std::bitset<kNumBits>(bit_strings[4].c_str()),
+       std::bitset<kNumBits>(bit_strings[5].c_str())}));
+}  // namespace
+
+template <typename T>
+class HashValueSequenceTest : public testing::Test {
+};
+TYPED_TEST_SUITE_P(HashValueSequenceTest);
+
+TYPED_TEST_P(HashValueSequenceTest, BasicUsage) {
+  EXPECT_TRUE((is_hashable<TypeParam>::value));
+
+  using ValueType = typename TypeParam::value_type;
+  auto a = static_cast<ValueType>(0);
+  auto b = static_cast<ValueType>(23);
+  auto c = static_cast<ValueType>(42);
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(TypeParam(), TypeParam{}, TypeParam{a, b, c},
+                      TypeParam{a, b}, TypeParam{b, c})));
+}
+
+REGISTER_TYPED_TEST_CASE_P(HashValueSequenceTest, BasicUsage);
+using IntSequenceTypes =
+    testing::Types<std::deque<int>, std::forward_list<int>, std::list<int>,
+                   std::vector<int>, std::vector<bool>, std::set<int>,
+                   std::multiset<int>>;
+INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes);
+
+// Private type that only supports AbslHashValue to make sure our chosen hash
+// implentation is recursive within absl::Hash.
+// It uses std::abs() on the value to provide different bitwise representations
+// of the same logical value.
+struct Private {
+  int i;
+  template <typename H>
+  friend H AbslHashValue(H h, Private p) {
+    return H::combine(std::move(h), std::abs(p.i));
+  }
+
+  friend bool operator==(Private a, Private b) {
+    return std::abs(a.i) == std::abs(b.i);
+  }
+
+  friend std::ostream& operator<<(std::ostream& o, Private p) {
+    return o << p.i;
+  }
+};
+
+TEST(HashValueTest, PrivateSanity) {
+  // Sanity check that Private is working as the tests below expect it to work.
+  EXPECT_TRUE(is_hashable<Private>::value);
+  EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));
+  EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));
+}
+
+TEST(HashValueTest, Optional) {
+  EXPECT_TRUE(is_hashable<absl::optional<Private>>::value);
+
+  using O = absl::optional<Private>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));
+}
+
+TEST(HashValueTest, Variant) {
+  using V = absl::variant<Private, std::string>;
+  EXPECT_TRUE(is_hashable<V>::value);
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD"))));
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+  struct S {};
+  EXPECT_FALSE(is_hashable<absl::variant<S>>::value);
+#endif
+}
+
+TEST(HashValueTest, Maps) {
+  EXPECT_TRUE((is_hashable<std::map<int, std::string>>::value));
+
+  using M = std::map<int, std::string>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      M{}, M{{0, "foo"}}, M{{1, "foo"}}, M{{0, "bar"}}, M{{1, "bar"}},
+      M{{0, "foo"}, {42, "bar"}}, M{{1, "foo"}, {42, "bar"}},
+      M{{1, "foo"}, {43, "bar"}}, M{{1, "foo"}, {43, "baz"}})));
+
+  using MM = std::multimap<int, std::string>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      MM{}, MM{{0, "foo"}}, MM{{1, "foo"}}, MM{{0, "bar"}}, MM{{1, "bar"}},
+      MM{{0, "foo"}, {0, "bar"}}, MM{{0, "bar"}, {0, "foo"}},
+      MM{{0, "foo"}, {42, "bar"}}, MM{{1, "foo"}, {42, "bar"}},
+      MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}})));
+}
+
 template <typename T, typename = void>
 struct IsHashCallble : std::false_type {};
 
@@ -108,7 +448,8 @@
   EXPECT_TRUE(IsHashCallble<int>::value);
   EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
 }
-#if ABSL_HASH_INTERNAL_CAN_POISON_ && !defined(__APPLE__)
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 TEST(IsHashableTest, PoisonHash) {
   struct X {};
   EXPECT_FALSE((is_hashable<X>::value));
@@ -120,7 +461,7 @@
   EXPECT_FALSE(IsHashCallble<X>::value);
   EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
 }
-#endif  // ABSL_HASH_INTERNAL_CAN_POISON_
+#endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 
 // Hashable types
 //
@@ -159,8 +500,16 @@
                              Int(4));
   }
 };
+enum class InvokeTag {
+  kUniquelyRepresented,
+  kHashValue,
+#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+  kLegacyHash,
+#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+  kStdHash,
+  kNone
+};
 
-using InvokeTag = absl::hash_internal::InvokeHashTag;
 template <InvokeTag T>
 using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
 
@@ -245,13 +594,13 @@
 }
 
 void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {
-#if ABSL_HASH_INTERNAL_CAN_POISON_
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
   // is_hashable is false if we don't support any of the hooks.
   using type = CustomHashType<>;
   EXPECT_FALSE(is_hashable<type>());
   EXPECT_FALSE(is_hashable<const type>());
   EXPECT_FALSE(is_hashable<const type&>());
-#endif  // ABSL_HASH_INTERNAL_CAN_POISON_
+#endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 }
 
 template <InvokeTag Tag, typename... T>
@@ -273,7 +622,7 @@
 template <typename T>
 class HashIntTest : public testing::Test {
 };
-TYPED_TEST_CASE_P(HashIntTest);
+TYPED_TEST_SUITE_P(HashIntTest);
 
 TYPED_TEST_P(HashIntTest, BasicUsage) {
   EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));
@@ -352,7 +701,8 @@
 }
 
 TEST(HashTest, StandardHashContainerUsage) {
-  std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"}, { 42, "bar" }};
+  std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"},
+                                                         {42, "bar"}};
 
   EXPECT_NE(map.find(0), map.end());
   EXPECT_EQ(map.find(1), map.end());
@@ -422,4 +772,24 @@
             SpyHash(std::make_pair(size_t{7}, 17)));
 }
 
+struct ValueWithBoolConversion {
+  operator bool() const { return false; }
+  int i;
+};
+
+}  // namespace
+namespace std {
+template <>
+struct hash<ValueWithBoolConversion> {
+  size_t operator()(ValueWithBoolConversion v) { return v.i; }
+};
+}  // namespace std
+
+namespace {
+
+TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
+  EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),
+            absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
+}
+
 }  // namespace
diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h
index 1e3cda6..c45bc15 100644
--- a/absl/hash/hash_testing.h
+++ b/absl/hash/hash_testing.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -90,7 +90,7 @@
 //   template <typename H>
 //   friend H AbslHashValue(H state, Bad2 x) {
 //     // Uses a and b.
-//     return H::combine(x.a, x.b);
+//     return H::combine(std::move(state), x.a, x.b);
 //   }
 //   friend bool operator==(Bad2 x, Bad2 y) {
 //     // Only uses a.
@@ -107,7 +107,7 @@
 //   template <typename H>
 //   friend H AbslHashValue(H state, Bad3 x) {
 //     // Only uses a.
-//     return H::combine(x.a);
+//     return H::combine(std::move(state), x.a);
 //   }
 //   friend bool operator==(Bad3 x, Bad3 y) {
 //     // Uses a and b.
@@ -123,19 +123,21 @@
 //   int *p, size;
 //   template <typename H>
 //   friend H AbslHashValue(H state, Bad4 x) {
-//     return H::combine_range(x.p, x.p + x.size);
+//     return H::combine_contiguous(std::move(state), x.p, x.p + x.size);
 //   }
 //   friend bool operator==(Bad4 x, Bad4 y) {
-//     return std::equal(x.p, x.p + x.size, y.p, y.p + y.size);
+//    // Compare two ranges for equality. C++14 code can instead use std::equal.
+//     return absl::equal(x.p, x.p + x.size, y.p, y.p + y.size);
 //   }
 // };
 //
 // An easy solution to this is to combine the size after combining the range,
 // like so:
-//   template <typename H>
-//   friend H AbslHashValue(H state, Bad4 x) {
-//     return H::combine(H::combine_range(x.p, x.p + x.size), x.size);
-//   }
+// template <typename H>
+// friend H AbslHashValue(H state, Bad4 x) {
+//   return H::combine(
+//       H::combine_contiguous(std::move(state), x.p, x.p + x.size), x.size);
+// }
 //
 template <int&... ExplicitBarrier, typename Container>
 ABSL_MUST_USE_RESULT testing::AssertionResult
@@ -188,7 +190,9 @@
   struct Info {
     const V& value;
     size_t index;
-    std::string ToString() const { return absl::visit(PrintVisitor{index}, value); }
+    std::string ToString() const {
+      return absl::visit(PrintVisitor{index}, value);
+    }
     SpyHashState expand() const { return absl::visit(ExpandVisitor{}, value); }
   };
 
@@ -227,7 +231,8 @@
   // Now we verify that AbslHashValue is also correctly implemented.
 
   for (const auto& c : classes) {
-    // All elements of the equivalence class must have the same hash expansion.
+    // All elements of the equivalence class must have the same hash
+    // expansion.
     const SpyHashState expected = c[0].expand();
     for (const Info& v : c) {
       if (v.expand() != v.expand()) {
@@ -285,7 +290,7 @@
 };
 
 template <typename... T>
-struct MakeTypeSet : TypeSet<>{};
+struct MakeTypeSet : TypeSet<> {};
 template <typename T, typename... Ts>
 struct MakeTypeSet<T, Ts...> : MakeTypeSet<Ts...>::template Insert<T>::type {};
 
@@ -346,8 +351,7 @@
 ABSL_MUST_USE_RESULT testing::AssertionResult
 VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
-      hash_internal::ContainerAsVector<Container>::Do(values),
-      equals);
+      hash_internal::ContainerAsVector<Container>::Do(values), equals);
 }
 
 template <int&..., typename T>
diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc
index 8f72dd1..dc7650a 100644
--- a/absl/hash/internal/city.cc
+++ b/absl/hash/internal/city.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -340,251 +340,5 @@
   return HashLen16(CityHash64(s, len) - seed0, seed1);
 }
 
-// A subroutine for CityHash128().  Returns a decent 128-bit hash for strings
-// of any length representable in signed long.  Based on City and Murmur.
-static uint128 CityMurmur(const char *s, size_t len, uint128 seed) {
-  uint64_t a = Uint128Low64(seed);
-  uint64_t b = Uint128High64(seed);
-  uint64_t c = 0;
-  uint64_t d = 0;
-  int64_t l = len - 16;
-  if (l <= 0) {  // len <= 16
-    a = ShiftMix(a * k1) * k1;
-    c = b * k1 + HashLen0to16(s, len);
-    d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
-  } else {  // len > 16
-    c = HashLen16(Fetch64(s + len - 8) + k1, a);
-    d = HashLen16(b + len, c + Fetch64(s + len - 16));
-    a += d;
-    do {
-      a ^= ShiftMix(Fetch64(s) * k1) * k1;
-      a *= k1;
-      b ^= a;
-      c ^= ShiftMix(Fetch64(s + 8) * k1) * k1;
-      c *= k1;
-      d ^= c;
-      s += 16;
-      l -= 16;
-    } while (l > 0);
-  }
-  a = HashLen16(a, c);
-  b = HashLen16(d, b);
-  return uint128(a ^ b, HashLen16(b, a));
-}
-
-uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) {
-  if (len < 128) {
-    return CityMurmur(s, len, seed);
-  }
-
-  // We expect len >= 128 to be the common case.  Keep 56 bytes of state:
-  // v, w, x, y, and z.
-  std::pair<uint64_t, uint64_t> v, w;
-  uint64_t x = Uint128Low64(seed);
-  uint64_t y = Uint128High64(seed);
-  uint64_t z = len * k1;
-  v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s);
-  v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8);
-  w.first = Rotate(y + z, 35) * k1 + x;
-  w.second = Rotate(x + Fetch64(s + 88), 53) * k1;
-
-  // This is the same inner loop as CityHash64(), manually unrolled.
-  do {
-    x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
-    y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
-    x ^= w.second;
-    y += v.first + Fetch64(s + 40);
-    z = Rotate(z + w.first, 33) * k1;
-    v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
-    w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
-    std::swap(z, x);
-    s += 64;
-    x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1;
-    y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1;
-    x ^= w.second;
-    y += v.first + Fetch64(s + 40);
-    z = Rotate(z + w.first, 33) * k1;
-    v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
-    w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));
-    std::swap(z, x);
-    s += 64;
-    len -= 128;
-  } while (ABSL_PREDICT_TRUE(len >= 128));
-  x += Rotate(v.first + z, 49) * k0;
-  y = y * k0 + Rotate(w.second, 37);
-  z = z * k0 + Rotate(w.first, 27);
-  w.first *= 9;
-  v.first *= k0;
-  // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
-  for (size_t tail_done = 0; tail_done < len;) {
-    tail_done += 32;
-    y = Rotate(x + y, 42) * k0 + v.second;
-    w.first += Fetch64(s + len - tail_done + 16);
-    x = x * k0 + w.first;
-    z += w.second + Fetch64(s + len - tail_done);
-    w.second += v.first;
-    v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
-    v.first *= k0;
-  }
-  // At this point our 56 bytes of state should contain more than
-  // enough information for a strong 128-bit hash.  We use two
-  // different 56-byte-to-8-byte hashes to get a 16-byte final result.
-  x = HashLen16(x, v.first);
-  y = HashLen16(y + z, w.first);
-  return uint128(HashLen16(x + v.second, w.second) + y,
-                 HashLen16(x + w.second, y + v.second));
-}
-
-uint128 CityHash128(const char *s, size_t len) {
-  return len >= 16
-             ? CityHash128WithSeed(s + 16, len - 16,
-                                   uint128(Fetch64(s), Fetch64(s + 8) + k0))
-             : CityHash128WithSeed(s, len, uint128(k0, k1));
-}
 }  // namespace hash_internal
 }  // namespace absl
-
-#ifdef __SSE4_2__
-#include <nmmintrin.h>
-#include "absl/hash/internal/city_crc.h"
-
-namespace absl {
-namespace hash_internal {
-
-// Requires len >= 240.
-static void CityHashCrc256Long(const char *s, size_t len, uint32_t seed,
-                               uint64_t *result) {
-  uint64_t a = Fetch64(s + 56) + k0;
-  uint64_t b = Fetch64(s + 96) + k0;
-  uint64_t c = result[0] = HashLen16(b, len);
-  uint64_t d = result[1] = Fetch64(s + 120) * k0 + len;
-  uint64_t e = Fetch64(s + 184) + seed;
-  uint64_t f = 0;
-  uint64_t g = 0;
-  uint64_t h = c + d;
-  uint64_t x = seed;
-  uint64_t y = 0;
-  uint64_t z = 0;
-
-  // 240 bytes of input per iter.
-  size_t iters = len / 240;
-  len -= iters * 240;
-  do {
-#undef CHUNK
-#define CHUNK(r)               \
-  PERMUTE3(x, z, y);           \
-  b += Fetch64(s);             \
-  c += Fetch64(s + 8);         \
-  d += Fetch64(s + 16);        \
-  e += Fetch64(s + 24);        \
-  f += Fetch64(s + 32);        \
-  a += b;                      \
-  h += f;                      \
-  b += c;                      \
-  f += d;                      \
-  g += e;                      \
-  e += z;                      \
-  g += x;                      \
-  z = _mm_crc32_u64(z, b + g); \
-  y = _mm_crc32_u64(y, e + h); \
-  x = _mm_crc32_u64(x, f + a); \
-  e = Rotate(e, r);            \
-  c += e;                      \
-  s += 40
-
-    CHUNK(0);
-    PERMUTE3(a, h, c);
-    CHUNK(33);
-    PERMUTE3(a, h, f);
-    CHUNK(0);
-    PERMUTE3(b, h, f);
-    CHUNK(42);
-    PERMUTE3(b, h, d);
-    CHUNK(0);
-    PERMUTE3(b, h, e);
-    CHUNK(33);
-    PERMUTE3(a, h, e);
-  } while (--iters > 0);
-
-  while (len >= 40) {
-    CHUNK(29);
-    e ^= Rotate(a, 20);
-    h += Rotate(b, 30);
-    g ^= Rotate(c, 40);
-    f += Rotate(d, 34);
-    PERMUTE3(c, h, g);
-    len -= 40;
-  }
-  if (len > 0) {
-    s = s + len - 40;
-    CHUNK(33);
-    e ^= Rotate(a, 43);
-    h += Rotate(b, 42);
-    g ^= Rotate(c, 41);
-    f += Rotate(d, 40);
-  }
-  result[0] ^= h;
-  result[1] ^= g;
-  g += h;
-  a = HashLen16(a, g + z);
-  x += y << 32;
-  b += x;
-  c = HashLen16(c, z) + h;
-  d = HashLen16(d, e + result[0]);
-  g += e;
-  h += HashLen16(x, f);
-  e = HashLen16(a, d) + g;
-  z = HashLen16(b, c) + a;
-  y = HashLen16(g, h) + c;
-  result[0] = e + z + y + x;
-  a = ShiftMix((a + y) * k0) * k0 + b;
-  result[1] += a + result[0];
-  a = ShiftMix(a * k0) * k0 + c;
-  result[2] = a + result[1];
-  a = ShiftMix((a + e) * k0) * k0;
-  result[3] = a + result[2];
-}
-
-// Requires len < 240.
-static void CityHashCrc256Short(const char *s, size_t len, uint64_t *result) {
-  char buf[240];
-  memcpy(buf, s, len);
-  memset(buf + len, 0, 240 - len);
-  CityHashCrc256Long(buf, 240, ~static_cast<uint32_t>(len), result);
-}
-
-void CityHashCrc256(const char *s, size_t len, uint64_t *result) {
-  if (ABSL_PREDICT_TRUE(len >= 240)) {
-    CityHashCrc256Long(s, len, 0, result);
-  } else {
-    CityHashCrc256Short(s, len, result);
-  }
-}
-
-uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) {
-  if (len <= 900) {
-    return CityHash128WithSeed(s, len, seed);
-  } else {
-    uint64_t result[4];
-    CityHashCrc256(s, len, result);
-    uint64_t u = Uint128High64(seed) + result[0];
-    uint64_t v = Uint128Low64(seed) + result[1];
-    return uint128(HashLen16(u, v + result[2]),
-                   HashLen16(Rotate(v, 32), u * k0 + result[3]));
-  }
-}
-
-uint128 CityHashCrc128(const char *s, size_t len) {
-  if (len <= 900) {
-    return CityHash128(s, len);
-  } else {
-    uint64_t result[4];
-    CityHashCrc256(s, len, result);
-    return uint128(result[2], result[3]);
-  }
-}
-
-}  // namespace hash_internal
-}  // namespace absl
-
-#endif
diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h
index 55b37b8..b43d340 100644
--- a/absl/hash/internal/city.h
+++ b/absl/hash/internal/city.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-// http://code.google.com/p/cityhash/
+// https://code.google.com/p/cityhash/
 //
 // This file provides a few functions for hashing strings.  All of them are
 // high-quality functions in the sense that they pass standard tests such
@@ -23,15 +23,6 @@
 // is Murmur3.  For 64-bit x86 code, CityHash64 is an excellent choice for hash
 // tables and most other hashing (excluding cryptography).
 //
-// For 64-bit x86 code, on long strings, the picture is more complicated.
-// On many recent Intel CPUs, such as Nehalem, Westmere, Sandy Bridge, etc.,
-// CityHashCrc128 appears to be faster than all competitors of comparable
-// quality.  CityHash128 is also good but not quite as fast.  We believe our
-// nearest competitor is Bob Jenkins' Spooky.  We don't have great data for
-// other 64-bit CPUs, but for long strings we know that Spooky is slightly
-// faster than CityHash on some relatively recent AMD x86-64 CPUs, for example.
-// Note that CityHashCrc128 is declared in citycrc.h.
-//
 // For 32-bit x86 code, we don't know of anything faster than CityHash32 that
 // is of comparable quality.  We believe our nearest competitor is Murmur3A.
 // (On 64-bit CPUs, it is typically faster to use the other CityHash variants.)
@@ -58,7 +49,6 @@
 #include <stdlib.h>  // for size_t.
 #include <utility>
 
-
 namespace absl {
 namespace hash_internal {
 
@@ -79,13 +69,6 @@
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
                            uint64_t seed1);
 
-// Hash function for a byte array.
-uint128 CityHash128(const char *s, size_t len);
-
-// Hash function for a byte array.  For convenience, a 128-bit seed is also
-// hashed into the result.
-uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed);
-
 // 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/city_crc.h b/absl/hash/internal/city_crc.h
deleted file mode 100644
index 6be6557..0000000
--- a/absl/hash/internal/city_crc.h
+++ /dev/null
@@ -1,41 +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
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// This file declares the subset of the CityHash functions that require
-// _mm_crc32_u64().  See the CityHash README for details.
-//
-// Functions in the CityHash family are not suitable for cryptography.
-
-#ifndef ABSL_HASH_INTERNAL_CITY_CRC_H_
-#define ABSL_HASH_INTERNAL_CITY_CRC_H_
-
-#include "absl/hash/internal/city.h"
-
-namespace absl {
-namespace hash_internal {
-
-// Hash function for a byte array.
-uint128 CityHashCrc128(const char *s, size_t len);
-
-// Hash function for a byte array.  For convenience, a 128-bit seed is also
-// hashed into the result.
-uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed);
-
-// Hash function for a byte array.  Sets result[0] ... result[3].
-void CityHashCrc256(const char *s, size_t len, uint64_t *result);
-
-}  // namespace hash_internal
-}  // namespace absl
-
-#endif  // ABSL_HASH_INTERNAL_CITY_CRC_H_
diff --git a/absl/hash/internal/city_test.cc b/absl/hash/internal/city_test.cc
index 678da53..71b4ecc 100644
--- a/absl/hash/internal/city_test.cc
+++ b/absl/hash/internal/city_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -18,9 +18,6 @@
 #include <cstdio>
 #include <iostream>
 #include "gtest/gtest.h"
-#ifdef __SSE4_2__
-#include "absl/hash/internal/city_crc.h"
-#endif
 
 namespace absl {
 namespace hash_internal {
@@ -28,7 +25,6 @@
 static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
 static const uint64_t kSeed0 = 1234567;
 static const uint64_t kSeed1 = k0;
-static const uint128 kSeed128(kSeed0, kSeed1);
 static const int kDataSize = 1 << 20;
 static const int kTestSize = 300;
 
@@ -49,1754 +45,539 @@
 }
 
 #define C(x) 0x##x##ULL
-static const uint64_t testdata[kTestSize][16] = {
+static const uint64_t testdata[kTestSize][4] = {
     {C(9ae16a3b2f90404f), C(75106db890237a4a), C(3feac5f636039766),
-     C(3df09dfc64c09a2b), C(3cb540c392e51e29), C(6b56343feac0663),
-     C(5b7bc50fd8e8ad92), C(3df09dfc64c09a2b), C(3cb540c392e51e29),
-     C(6b56343feac0663), C(5b7bc50fd8e8ad92), C(95162f24e6a5f930),
-     C(6808bdf4f1eb06e0), C(b3b1f3a67b624d82), C(c9a62f12bd4cd80b),
      C(dc56d17a)},
     {C(541150e87f415e96), C(1aef0d24b3148a1a), C(bacc300e1e82345a),
-     C(c3cdc41e1df33513), C(2c138ff2596d42f6), C(f58e9082aed3055f),
-     C(162e192b2957163d), C(c3cdc41e1df33513), C(2c138ff2596d42f6),
-     C(f58e9082aed3055f), C(162e192b2957163d), C(fb99e85e0d16f90c),
-     C(608462c15bdf27e8), C(e7d2c5c943572b62), C(1baaa9327642798c),
      C(99929334)},
-    {C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2),
-     C(3149ba1dac77270d), C(70e2e076e30703c), C(59bcc9659bc5296),
-     C(9ecbc8132ae2f1d7), C(3149ba1dac77270d), C(70e2e076e30703c),
-     C(59bcc9659bc5296), C(9ecbc8132ae2f1d7), C(a01d30789bad7cf2),
-     C(ae03fe371981a0e0), C(127e3883b8788934), C(d0ac3d4c0a6fca32),
-     C(4252edb7)},
+    {C(f3786a4b25827c1), C(34ee1a2bf767bd1c), C(2f15ca2ebfb631f2), C(4252edb7)},
     {C(ef923a7a1af78eab), C(79163b1e1e9a9b18), C(df3b2aca6e1e4a30),
-     C(2193fb7620cbf23b), C(8b6a8ff06cda8302), C(1a44469afd3e091f),
-     C(8b0449376612506), C(2193fb7620cbf23b), C(8b6a8ff06cda8302),
-     C(1a44469afd3e091f), C(8b0449376612506), C(e9d9d41c32ad91d1),
-     C(b44ab09f58e3c608), C(19e9175f9fcf784), C(839b3c9581b4a480), C(ebc34f3c)},
+     C(ebc34f3c)},
     {C(11df592596f41d88), C(843ec0bce9042f9c), C(cce2ea1e08b1eb30),
-     C(4d09e42f09cc3495), C(666236631b9f253b), C(d28b3763cd02b6a3),
-     C(43b249e57c4d0c1b), C(4d09e42f09cc3495), C(666236631b9f253b),
-     C(d28b3763cd02b6a3), C(43b249e57c4d0c1b), C(3887101c8adea101),
-     C(8a9355d4efc91df0), C(3e610944cc9fecfd), C(5bf9eb60b08ac0ce),
      C(26f2b463)},
     {C(831f448bdc5600b3), C(62a24be3120a6919), C(1b44098a41e010da),
-     C(dc07df53b949c6b), C(d2b11b2081aeb002), C(d212b02c1b13f772),
-     C(c0bed297b4be1912), C(dc07df53b949c6b), C(d2b11b2081aeb002),
-     C(d212b02c1b13f772), C(c0bed297b4be1912), C(682d3d2ad304e4af),
-     C(40e9112a655437a1), C(268b09f7ee09843f), C(6b9698d43859ca47),
      C(b042c047)},
-    {C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d),
-     C(d183dcda5f73edfa), C(3a93cbf40f30128c), C(1a92544d0b41dbda),
-     C(aec2c4bee81975e1), C(d183dcda5f73edfa), C(3a93cbf40f30128c),
-     C(1a92544d0b41dbda), C(aec2c4bee81975e1), C(5f91814d1126ba4b),
-     C(f8ac57eee87fcf1f), C(c55c644a5d0023cd), C(adb761e827825ff2),
-     C(e73bb0a8)},
+    {C(3eca803e70304894), C(d80de767e4a920a), C(a51cfbb292efd53d), C(e73bb0a8)},
     {C(1b5a063fb4c7f9f1), C(318dbc24af66dee9), C(10ef7b32d5c719af),
-     C(b140a02ef5c97712), C(b7d00ef065b51b33), C(635121d532897d98),
-     C(532daf21b312a6d6), C(b140a02ef5c97712), C(b7d00ef065b51b33),
-     C(635121d532897d98), C(532daf21b312a6d6), C(c0b09b75d943910),
-     C(8c84dfb5ef2a8e96), C(e5c06034b0353433), C(3170faf1c33a45dd),
      C(91dfdd75)},
     {C(a0f10149a0e538d6), C(69d008c20f87419f), C(41b36376185b3e9e),
-     C(26b6689960ccf81d), C(55f23b27bb9efd94), C(3a17f6166dd765db),
-     C(c891a8a62931e782), C(26b6689960ccf81d), C(55f23b27bb9efd94),
-     C(3a17f6166dd765db), C(c891a8a62931e782), C(23852dc37ddd2607),
-     C(8b7f1b1ec897829e), C(d1d69452a54eed8a), C(56431f2bd766ec24),
      C(c87f95de)},
     {C(fb8d9c70660b910b), C(a45b0cc3476bff1b), C(b28d1996144f0207),
-     C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7), C(bcf5c8fe4465b7c8),
-     C(b1ea3a8243996f15), C(98ec31113e5e35d2), C(5e4aeb853f1b9aa7),
-     C(bcf5c8fe4465b7c8), C(b1ea3a8243996f15), C(cabbccedb6407571),
-     C(d1e40a84c445ec3a), C(33302aa908cf4039), C(9f15f79211b5cdf8),
      C(3f5538ef)},
     {C(236827beae282a46), C(e43970221139c946), C(4f3ac6faa837a3aa),
-     C(71fec0f972248915), C(2170ec2061f24574), C(9eb346b6caa36e82),
-     C(2908f0fdbca48e73), C(71fec0f972248915), C(2170ec2061f24574),
-     C(9eb346b6caa36e82), C(2908f0fdbca48e73), C(8101c99f07c64abb),
-     C(b9f4b02b1b6a96a7), C(583a2b10cd222f88), C(199dae4cf9db24c), C(70eb1a1f)},
+     C(70eb1a1f)},
     {C(c385e435136ecf7c), C(d9d17368ff6c4a08), C(1b31eed4e5251a67),
-     C(df01a322c43a6200), C(298b65a1714b5a7e), C(933b83f0aedf23c),
-     C(157bcb44d63f765a), C(df01a322c43a6200), C(298b65a1714b5a7e),
-     C(933b83f0aedf23c), C(157bcb44d63f765a), C(d6e9fc7a272d8b51),
-     C(3ee5073ef1a9b777), C(63149e31fac02c59), C(2f7979ff636ba1d8),
      C(cfd63b83)},
     {C(e3f6828b6017086d), C(21b4d1900554b3b0), C(bef38be1809e24f1),
-     C(d93251758985ee6c), C(32a9e9f82ba2a932), C(3822aacaa95f3329),
-     C(db349b2f90a490d8), C(d93251758985ee6c), C(32a9e9f82ba2a932),
-     C(3822aacaa95f3329), C(db349b2f90a490d8), C(8d49194a894a19ca),
-     C(79a78b06e42738e6), C(7e0f1eda3d390c66), C(1c291d7e641100a5),
      C(894a52ef)},
     {C(851fff285561dca0), C(4d1277d73cdf416f), C(28ccffa61010ebe2),
-     C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa), C(70b9e3051383fa45),
-     C(582d0120425caba), C(77a4ccacd131d9ee), C(e1d08eeb2f0e29aa),
-     C(70b9e3051383fa45), C(582d0120425caba), C(a740eef1846e4564),
-     C(572dddb74ac3ae00), C(fdb5ca9579163bbd), C(a649b9b799c615d2),
      C(9cde6a54)},
     {C(61152a63595a96d9), C(d1a3a91ef3a7ba45), C(443b6bb4a493ad0c),
-     C(a154296d11362d06), C(d0f0bf1f1cb02fc1), C(ccb87e09309f90d1),
-     C(b24a8e4881911101), C(a154296d11362d06), C(d0f0bf1f1cb02fc1),
-     C(ccb87e09309f90d1), C(b24a8e4881911101), C(1a481b4528559f58),
-     C(bf837a3150896995), C(4989ef6b941a3757), C(2e725ab72d0b2948),
      C(6c4898d5)},
     {C(44473e03be306c88), C(30097761f872472a), C(9fd1b669bfad82d7),
-     C(3bab18b164396783), C(47e385ff9d4c06f), C(18062081bf558df),
-     C(63416eb68f104a36), C(3bab18b164396783), C(47e385ff9d4c06f),
-     C(18062081bf558df), C(63416eb68f104a36), C(4abda1560c47ac80),
-     C(1ea0e63dc6587aee), C(33ec79d92ebc1de), C(94f9dccef771e048), C(13e1978e)},
-    {C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303),
-     C(ac059617f5906673), C(94d50d3dcd3069a7), C(2b26c3b92dea0f0),
-     C(99b7374cc78fc3fb), C(ac059617f5906673), C(94d50d3dcd3069a7),
-     C(2b26c3b92dea0f0), C(99b7374cc78fc3fb), C(1a8e3c73cdd40ee8),
-     C(cbb5fca06747f45b), C(ceec44238b291841), C(28bf35cce9c90a25), C(51b4ba8)},
+     C(13e1978e)},
+    {C(3ead5f21d344056), C(fb6420393cfb05c3), C(407932394cbbd303), C(51b4ba8)},
     {C(6abbfde37ee03b5b), C(83febf188d2cc113), C(cda7b62d94d5b8ee),
-     C(a4375590b8ae7c82), C(168fd42f9ecae4ff), C(23bbde43de2cb214),
-     C(a8c333112a243c8c), C(a4375590b8ae7c82), C(168fd42f9ecae4ff),
-     C(23bbde43de2cb214), C(a8c333112a243c8c), C(10ac012e8c518b49),
-     C(64a44605d8b29458), C(a67e701d2a679075), C(3a3a20f43ec92303),
      C(b6b06e40)},
-    {C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a),
-     C(6b54fc38d6a84108), C(32f4212a47a4665), C(6b5a9a8f64ee1da6),
-     C(9f74e86c6da69421), C(6b54fc38d6a84108), C(32f4212a47a4665),
-     C(6b5a9a8f64ee1da6), C(9f74e86c6da69421), C(946dd0cb30c1a08e),
-     C(fdf376956907eaaa), C(a59074c6eec03028), C(b1a3abcf283f34ac), C(240a2f2)},
+    {C(943e7ed63b3c080), C(1ef207e9444ef7f8), C(ef4a9f9f8c6f9b4a), C(240a2f2)},
     {C(d72ce05171ef8a1a), C(c6bd6bd869203894), C(c760e6396455d23a),
-     C(f86af0b40dcce7b), C(8d3c15d613394d3c), C(491e400491cd4ece),
-     C(7c19d3530ea3547f), C(f86af0b40dcce7b), C(8d3c15d613394d3c),
-     C(491e400491cd4ece), C(7c19d3530ea3547f), C(1362963a1dc32af9),
-     C(fb9bc11762e1385c), C(9e164ef1f5376083), C(6c15819b5e828a7e),
      C(5dcefc30)},
     {C(4182832b52d63735), C(337097e123eea414), C(b5a72ca0456df910),
-     C(7ebc034235bc122f), C(d9a7783d4edd8049), C(5f8b04a15ae42361),
-     C(fc193363336453dd), C(7ebc034235bc122f), C(d9a7783d4edd8049),
-     C(5f8b04a15ae42361), C(fc193363336453dd), C(9b6c50224ef8c4f8),
-     C(ba225c7942d16c3f), C(6f6d55226a73c412), C(abca061fe072152a),
      C(7a48b105)},
     {C(d6cdae892584a2cb), C(58de0fa4eca17dcd), C(43df30b8f5f1cb00),
-     C(9e4ea5a4941e097d), C(547e048d5a9daaba), C(eb6ecbb0b831d185),
-     C(e0168df5fad0c670), C(9e4ea5a4941e097d), C(547e048d5a9daaba),
-     C(eb6ecbb0b831d185), C(e0168df5fad0c670), C(afa9705f98c2c96a),
-     C(749436f48137a96b), C(759c041fc21df486), C(b23bf400107aa2ec),
      C(fd55007b)},
     {C(5c8e90bc267c5ee4), C(e9ae044075d992d9), C(f234cbfd1f0a1e59),
-     C(ce2744521944f14c), C(104f8032f99dc152), C(4e7f425bfac67ca7),
-     C(9461b911a1c6d589), C(ce2744521944f14c), C(104f8032f99dc152),
-     C(4e7f425bfac67ca7), C(9461b911a1c6d589), C(5e5ecc726db8b60d),
-     C(cce68b0586083b51), C(8a7f8e54a9cba0fc), C(42f010181d16f049),
      C(6b95894c)},
     {C(bbd7f30ac310a6f3), C(b23b570d2666685f), C(fb13fb08c9814fe7),
-     C(4ee107042e512374), C(1e2c8c0d16097e13), C(210c7500995aa0e6),
-     C(6c13190557106457), C(4ee107042e512374), C(1e2c8c0d16097e13),
-     C(210c7500995aa0e6), C(6c13190557106457), C(a99b31c96777f381),
-     C(8312ae8301d386c0), C(ed5042b2a4fa96a3), C(d71d1bb23907fe97),
      C(3360e827)},
-    {C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a),
-     C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca), C(6bc63c666b5100e2),
-     C(e0b056f1821752af), C(6ee1f817ce0b7aee), C(e9dcb3507f0596ca),
-     C(6bc63c666b5100e2), C(e0b056f1821752af), C(8ea1114e60292678),
-     C(904b80b46becc77), C(46cd9bb6e9dff52f), C(4c91e3b698355540), C(45177e0b)},
-    {C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5),
-     C(d367ff54952a958), C(cdad930657371147), C(aa24dc2a9573d5fe),
-     C(eb136daa89da5110), C(d367ff54952a958), C(cdad930657371147),
-     C(aa24dc2a9573d5fe), C(eb136daa89da5110), C(de623005f6d46057),
-     C(b50c0c92b95e9b7f), C(a8aa54050b81c978), C(573fb5c7895af9b5),
-     C(7c6fffe4)},
+    {C(36a097aa49519d97), C(8204380a73c4065), C(77c2004bdd9e276a), C(45177e0b)},
+    {C(dc78cb032c49217), C(112464083f83e03a), C(96ae53e28170c0f5), C(7c6fffe4)},
     {C(441593e0da922dfe), C(936ef46061469b32), C(204a1921197ddd87),
-     C(50d8a70e7a8d8f56), C(256d150ae75dab76), C(e81f4c4a1989036a),
-     C(d0f8db365f9d7e00), C(50d8a70e7a8d8f56), C(256d150ae75dab76),
-     C(e81f4c4a1989036a), C(d0f8db365f9d7e00), C(753d686677b14522),
-     C(9f76e0cb6f2d0a66), C(ab14f95988ec0d39), C(97621d9da9c9812f),
      C(bbc78da4)},
     {C(2ba3883d71cc2133), C(72f2bbb32bed1a3c), C(27e1bd96d4843251),
-     C(a90f761e8db1543a), C(c339e23c09703cd8), C(f0c6624c4b098fd3),
-     C(1bae2053e41fa4d9), C(a90f761e8db1543a), C(c339e23c09703cd8),
-     C(f0c6624c4b098fd3), C(1bae2053e41fa4d9), C(3589e273c22ba059),
-     C(63798246e5911a0b), C(18e710ec268fc5dc), C(714a122de1d074f3),
      C(c5c25d39)},
     {C(f2b6d2adf8423600), C(7514e2f016a48722), C(43045743a50396ba),
-     C(23dacb811652ad4f), C(c982da480e0d4c7d), C(3a9c8ed5a399d0a9),
-     C(951b8d084691d4e4), C(23dacb811652ad4f), C(c982da480e0d4c7d),
-     C(3a9c8ed5a399d0a9), C(951b8d084691d4e4), C(d9f87b4988cff2f7),
-     C(217a191d986aa3bc), C(6ad23c56b480350), C(dd78673938ceb2e7), C(b6e5d06e)},
+     C(b6e5d06e)},
     {C(38fffe7f3680d63c), C(d513325255a7a6d1), C(31ed47790f6ca62f),
-     C(c801faaa0a2e331f), C(491dbc58279c7f88), C(9c0178848321c97a),
-     C(9d934f814f4d6a3c), C(c801faaa0a2e331f), C(491dbc58279c7f88),
-     C(9c0178848321c97a), C(9d934f814f4d6a3c), C(606a3e4fc8763192),
-     C(bc15cb36a677ee84), C(52d5904157e1fe71), C(1588dd8b1145b79b),
      C(6178504e)},
-    {C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac),
-     C(68dd76db9d64eca7), C(36297682b64b67), C(42b192d71f414b7a),
-     C(79692cef44fa0206), C(68dd76db9d64eca7), C(36297682b64b67),
-     C(42b192d71f414b7a), C(79692cef44fa0206), C(f0979252f4776d07),
-     C(4b87cd4f1c9bbf52), C(51b84bbc6312c710), C(150720fbf85428a7),
-     C(bd4c3637)},
+    {C(b7477bf0b9ce37c6), C(63b1c580a7fd02a4), C(f6433b9f10a5dac), C(bd4c3637)},
     {C(55bdb0e71e3edebd), C(c7ab562bcf0568bc), C(43166332f9ee684f),
-     C(b2e25964cd409117), C(a010599d6287c412), C(fa5d6461e768dda2),
-     C(cb3ce74e8ec4f906), C(b2e25964cd409117), C(a010599d6287c412),
-     C(fa5d6461e768dda2), C(cb3ce74e8ec4f906), C(6120abfd541a2610),
-     C(aa88b148cc95794d), C(2686ca35df6590e3), C(c6b02d18616ce94d),
      C(6e7ac474)},
-    {C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e),
-     C(9a8c431f500ef06e), C(d848581a580b6c12), C(fecfe11e13a2bdb4),
-     C(6c4fa0273d7db08c), C(9a8c431f500ef06e), C(d848581a580b6c12),
-     C(fecfe11e13a2bdb4), C(6c4fa0273d7db08c), C(482f43bf5ae59fcb),
-     C(f651fbca105d79e6), C(f09f78695d865817), C(7a99d0092085cf47),
-     C(1fb4b518)},
+    {C(782fa1b08b475e7), C(fb7138951c61b23b), C(9829105e234fb11e), C(1fb4b518)},
     {C(c5dc19b876d37a80), C(15ffcff666cfd710), C(e8c30c72003103e2),
-     C(7870765b470b2c5d), C(78a9103ff960d82), C(7bb50ffc9fac74b3),
-     C(477e70ab2b347db2), C(7870765b470b2c5d), C(78a9103ff960d82),
-     C(7bb50ffc9fac74b3), C(477e70ab2b347db2), C(a625238bdf7c07cf),
-     C(1128d515174809f5), C(b0f1647e82f45873), C(17792d1c4f222c39),
      C(31d13d6d)},
     {C(5e1141711d2d6706), C(b537f6dee8de6933), C(3af0a1fbbe027c54),
-     C(ea349dbc16c2e441), C(38a7455b6a877547), C(5f97b9750e365411),
-     C(e8cde7f93af49a3), C(ea349dbc16c2e441), C(38a7455b6a877547),
-     C(5f97b9750e365411), C(e8cde7f93af49a3), C(ba101925ec1f7e26),
-     C(d5e84cab8192c71e), C(e256427726fdd633), C(a4f38e2c6116890d),
      C(26fa72e3)},
-    {C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32),
-     C(5d9dde77353b1a6d), C(11f58c54581fa8b1), C(da90fa7c28c37478),
-     C(5e9a2eafc670a88a), C(5d9dde77353b1a6d), C(11f58c54581fa8b1),
-     C(da90fa7c28c37478), C(5e9a2eafc670a88a), C(e35e1bc172e011ef),
-     C(bf9255a4450ae7fe), C(55f85194e26bc55f), C(4f327873e14d0e54),
-     C(6a7433bf)},
+    {C(782edf6da001234f), C(f48cbd5c66c48f3), C(808754d1e64e2a32), C(6a7433bf)},
     {C(d26285842ff04d44), C(8f38d71341eacca9), C(5ca436f4db7a883c),
-     C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9), C(f4b70a971855e732),
-     C(40c7695aa3662afd), C(bf41e5376b9f0eec), C(2252d21eb7e1c0e9),
-     C(f4b70a971855e732), C(40c7695aa3662afd), C(770fe19e16ab73bb),
-     C(d603ebda6393d749), C(e58c62439aa50dbd), C(96d51e5a02d2d7cf),
      C(4e6df758)},
     {C(c6ab830865a6bae6), C(6aa8e8dd4b98815c), C(efe3846713c371e5),
-     C(a1924cbf0b5f9222), C(7f4872369c2b4258), C(cd6da30530f3ea89),
-     C(b7f8b9a704e6cea1), C(a1924cbf0b5f9222), C(7f4872369c2b4258),
-     C(cd6da30530f3ea89), C(b7f8b9a704e6cea1), C(fa06ff40433fd535),
-     C(fb1c36fe8f0737f1), C(bb7050561171f80), C(b1bc23235935d897), C(d57f63ea)},
-    {C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964),
-     C(f7dbc8433c89b274), C(2f5f70581c9b7d32), C(39bf5e5fec82dcca),
-     C(8ade56388901a619), C(f7dbc8433c89b274), C(2f5f70581c9b7d32),
-     C(39bf5e5fec82dcca), C(8ade56388901a619), C(c1c6a725caab3ea9),
-     C(c1c7906c2f80b898), C(9c3871a04cc884e6), C(df01813cbbdf217f),
-     C(52ef73b3)},
-    {C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a),
-     C(8ffe870ef4adc087), C(65bea2be41f55b54), C(82f3503f636aef1),
-     C(5f78a282378b6bb0), C(8ffe870ef4adc087), C(65bea2be41f55b54),
-     C(82f3503f636aef1), C(5f78a282378b6bb0), C(7bf2422c0beceddb),
-     C(9d238d4780114bd), C(7ad198311906597f), C(ec8f892c0422aca3), C(3cb36c3)},
+     C(d57f63ea)},
+    {C(44b3a1929232892), C(61dca0e914fc217), C(a607cc142096b964), C(52ef73b3)},
+    {C(4b603d7932a8de4f), C(fae64c464b8a8f45), C(8fafab75661d602a), C(3cb36c3)},
     {C(4ec0b54cf1566aff), C(30d2c7269b206bf4), C(77c22e82295e1061),
-     C(3df9b04434771542), C(feddce785ccb661f), C(a644aff716928297),
-     C(dd46aee73824b4ed), C(3df9b04434771542), C(feddce785ccb661f),
-     C(a644aff716928297), C(dd46aee73824b4ed), C(bf8d71879da29b02),
-     C(fc82dccbfc8022a0), C(31bfcd0d9f48d1d3), C(c64ee24d0e7b5f8b),
      C(72c39bea)},
     {C(ed8b7a4b34954ff7), C(56432de31f4ee757), C(85bd3abaa572b155),
-     C(7d2c38a926dc1b88), C(5245b9eb4cd6791d), C(fb53ab03b9ad0855),
-     C(3664026c8fc669d7), C(7d2c38a926dc1b88), C(5245b9eb4cd6791d),
-     C(fb53ab03b9ad0855), C(3664026c8fc669d7), C(45024d5080bc196),
-     C(b236ebec2cc2740), C(27231ad0e3443be4), C(145780b63f809250), C(a65aa25c)},
+     C(a65aa25c)},
     {C(5d28b43694176c26), C(714cc8bc12d060ae), C(3437726273a83fe6),
-     C(864b1b28ec16ea86), C(6a78a5a4039ec2b9), C(8e959533e35a766),
-     C(347b7c22b75ae65f), C(864b1b28ec16ea86), C(6a78a5a4039ec2b9),
-     C(8e959533e35a766), C(347b7c22b75ae65f), C(5005892bb61e647c),
-     C(fe646519b4a1894d), C(cd801026f74a8a53), C(8713463e9a1ab9ce),
      C(74740539)},
     {C(6a1ef3639e1d202e), C(919bc1bd145ad928), C(30f3f7e48c28a773),
-     C(2e8c49d7c7aaa527), C(5e2328fc8701db7c), C(89ef1afca81f7de8),
-     C(b1857db11985d296), C(2e8c49d7c7aaa527), C(5e2328fc8701db7c),
-     C(89ef1afca81f7de8), C(b1857db11985d296), C(17763d695f616115),
-     C(b8f7bf1fcdc8322c), C(cf0c61938ab07a27), C(1122d3e6edb4e866),
      C(c3ae3c26)},
-    {C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51),
-     C(3b69edadf357432b), C(3a2e311c121e6bf2), C(380fad1e288d57e5),
-     C(bf7c7e8ef0e3b83a), C(3b69edadf357432b), C(3a2e311c121e6bf2),
-     C(380fad1e288d57e5), C(bf7c7e8ef0e3b83a), C(92966d5f4356ae9b),
-     C(2a03fc66c4d6c036), C(2516d8bddb0d5259), C(b3ffe9737ff5090), C(f29db8a2)},
+    {C(159f4d9e0307b111), C(3e17914a5675a0c), C(af849bd425047b51), C(f29db8a2)},
     {C(cc0a840725a7e25b), C(57c69454396e193a), C(976eaf7eee0b4540),
-     C(cd7a46850b95e901), C(c57f7d060dda246f), C(6b9406ead64079bf),
-     C(11b28e20a573b7bd), C(cd7a46850b95e901), C(c57f7d060dda246f),
-     C(6b9406ead64079bf), C(11b28e20a573b7bd), C(2d6db356e9369ace),
-     C(dc0afe10fba193), C(5cdb10885dbbfce), C(5c700e205782e35a), C(1ef4cbf4)},
+     C(1ef4cbf4)},
     {C(a2b27ee22f63c3f1), C(9ebde0ce1b3976b2), C(2fe6a92a257af308),
-     C(8c1df927a930af59), C(a462f4423c9e384e), C(236542255b2ad8d9),
-     C(595d201a2c19d5bc), C(8c1df927a930af59), C(a462f4423c9e384e),
-     C(236542255b2ad8d9), C(595d201a2c19d5bc), C(22c87d4604a67f3),
-     C(585a06eb4bc44c4f), C(b4175a7ac7eabcd8), C(a457d3eeba14ab8c),
      C(a9be6c41)},
-    {C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f),
-     C(9498fefb890287ce), C(ae68c2be5b1a69a6), C(6189dfba34ed656c),
-     C(91658f95836e5206), C(9498fefb890287ce), C(ae68c2be5b1a69a6),
-     C(6189dfba34ed656c), C(91658f95836e5206), C(c0bb4fff32aecd4d),
-     C(94125f505a50eef9), C(6ac406e7cfbce5bb), C(344a4b1dcdb7f5d8), C(fa31801)},
+    {C(d8f2f234899bcab3), C(b10b037297c3a168), C(debea2c510ceda7f), C(fa31801)},
     {C(584f28543864844f), C(d7cee9fc2d46f20d), C(a38dca5657387205),
-     C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4), C(a674d85812c7cf6),
-     C(63538c0351049940), C(7a0b6dbab9a14e69), C(c6d0a9d6b0e31ac4),
-     C(a674d85812c7cf6), C(63538c0351049940), C(9710e5f0bc93d1d),
-     C(c2bea5bd7c54ddd4), C(48739af2bed0d32d), C(ba2c4e09e21fba85),
      C(8331c5d8)},
-    {C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f),
-     C(843b58463c8df0ae), C(74b258324e916045), C(bdd7353230eb2b38),
-     C(fad31fced7abade5), C(843b58463c8df0ae), C(74b258324e916045),
-     C(bdd7353230eb2b38), C(fad31fced7abade5), C(2436aeafb0046f85),
-     C(65bc9af9e5e33161), C(92733b1b3ae90628), C(f48143eaf78a7a89),
-     C(e9876db8)},
+    {C(a94be46dd9aa41af), C(a57e5b7723d3f9bd), C(34bf845a52fd2f), C(e9876db8)},
     {C(9a87bea227491d20), C(a468657e2b9c43e7), C(af9ba60db8d89ef7),
-     C(cc76f429ea7a12bb), C(5f30eaf2bb14870a), C(434e824cb3e0cd11),
-     C(431a4d382e39d16e), C(cc76f429ea7a12bb), C(5f30eaf2bb14870a),
-     C(434e824cb3e0cd11), C(431a4d382e39d16e), C(9e51f913c4773a8),
-     C(32ab1925823d0add), C(99c61b54c1d8f69d), C(38cfb80f02b43b1f),
      C(27b0604e)},
     {C(27688c24958d1a5c), C(e3b4a1c9429cf253), C(48a95811f70d64bc),
-     C(328063229db22884), C(67e9c95f8ba96028), C(7c6bf01c60436075),
-     C(fa55161e7d9030b2), C(328063229db22884), C(67e9c95f8ba96028),
-     C(7c6bf01c60436075), C(fa55161e7d9030b2), C(dadbc2f0dab91681),
-     C(da39d7a4934ca11), C(162e845d24c1b45c), C(eb5b9dcd8c6ed31b), C(dcec07f2)},
+     C(dcec07f2)},
     {C(5d1d37790a1873ad), C(ed9cd4bcc5fa1090), C(ce51cde05d8cd96a),
-     C(f72c26e624407e66), C(a0eb541bdbc6d409), C(c3f40a2f40b3b213),
-     C(6a784de68794492d), C(f72c26e624407e66), C(a0eb541bdbc6d409),
-     C(c3f40a2f40b3b213), C(6a784de68794492d), C(10a38a23dbef7937),
-     C(6a5560f853252278), C(c3387bbf3c7b82ba), C(fbee7c12eb072805),
      C(cff0a82a)},
     {C(1f03fd18b711eea9), C(566d89b1946d381a), C(6e96e83fc92563ab),
-     C(405f66cf8cae1a32), C(d7261740d8f18ce6), C(fea3af64a413d0b2),
-     C(d64d1810e83520fe), C(405f66cf8cae1a32), C(d7261740d8f18ce6),
-     C(fea3af64a413d0b2), C(d64d1810e83520fe), C(e1334a00a580c6e8),
-     C(454049e1b52c15f), C(8895d823d9778247), C(efa7f2e88b826618), C(fec83621)},
-    {C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71),
-     C(d4eccebe9393ee8a), C(2eb7867c2318cc59), C(1ce621fd700fe396),
-     C(686450d7a346878a), C(d4eccebe9393ee8a), C(2eb7867c2318cc59),
-     C(1ce621fd700fe396), C(686450d7a346878a), C(75a5f37579f8b4cb),
-     C(500cc16eb6541dc7), C(b7b02317b539d9a6), C(3519ddff5bc20a29), C(743d8dc)},
+     C(fec83621)},
+    {C(f0316f286cf527b6), C(f84c29538de1aa5a), C(7612ed3c923d4a71), C(743d8dc)},
     {C(297008bcb3e3401d), C(61a8e407f82b0c69), C(a4a35bff0524fa0e),
-     C(7a61d8f552a53442), C(821d1d8d8cfacf35), C(7cc06361b86d0559),
-     C(119b617a8c2be199), C(7a61d8f552a53442), C(821d1d8d8cfacf35),
-     C(7cc06361b86d0559), C(119b617a8c2be199), C(2996487da6721759),
-     C(61a901376070b91d), C(d88dee12ae9c9b3c), C(5665491be1fa53a7),
      C(64d41d26)},
-    {C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f),
-     C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0), C(deb85613995c06ed),
-     C(cbe1d957485a3ccd), C(2247a4b2058d1c50), C(1b3fa184b1d7bcc0),
-     C(deb85613995c06ed), C(cbe1d957485a3ccd), C(dfe241f8f33c96b6),
-     C(6597eb05019c2109), C(da344b2a63a219cf), C(79b8e3887612378a),
-     C(acd90c81)},
+    {C(43c6252411ee3be), C(b4ca1b8077777168), C(2746dc3f7da1737f), C(acd90c81)},
     {C(ce38a9a54fad6599), C(6d6f4a90b9e8755e), C(c3ecc79ff105de3f),
-     C(e8b9ee96efa2d0e), C(90122905c4ab5358), C(84f80c832d71979c),
-     C(229310f3ffbbf4c6), C(e8b9ee96efa2d0e), C(90122905c4ab5358),
-     C(84f80c832d71979c), C(229310f3ffbbf4c6), C(cc9eb42100cd63a7),
-     C(7a283f2f3da7b9f), C(359b061d314e7a72), C(d0d959720028862), C(7c746a4b)},
-    {C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1),
-     C(2e091b85660f1298), C(bfe37fae1cdd64c9), C(8dddfbab930f6494),
-     C(2ccf4b08f5d417a), C(2e091b85660f1298), C(bfe37fae1cdd64c9),
-     C(8dddfbab930f6494), C(2ccf4b08f5d417a), C(365c2ee85582fe6),
-     C(dee027bcd36db62a), C(b150994d3c7e5838), C(fdfd1a0e692e436d),
-     C(b1047e99)},
+     C(7c746a4b)},
+    {C(270a9305fef70cf), C(600193999d884f3a), C(f4d49eae09ed8a1), C(b1047e99)},
     {C(e71be7c28e84d119), C(eb6ace59932736e6), C(70c4397807ba12c5),
-     C(7a9d77781ac53509), C(4489c3ccfda3b39c), C(fa722d4f243b4964),
-     C(25f15800bffdd122), C(7a9d77781ac53509), C(4489c3ccfda3b39c),
-     C(fa722d4f243b4964), C(25f15800bffdd122), C(ed85e4157fbd3297),
-     C(aab1967227d59efd), C(2199631212eb3839), C(3e4c19359aae1cc2),
      C(d1fd1068)},
     {C(b5b58c24b53aaa19), C(d2a6ab0773dd897f), C(ef762fe01ecb5b97),
-     C(9deefbcfa4cab1f1), C(b58f5943cd2492ba), C(a96dcc4d1f4782a7),
-     C(102b62a82309dde5), C(9deefbcfa4cab1f1), C(b58f5943cd2492ba),
-     C(a96dcc4d1f4782a7), C(102b62a82309dde5), C(35fe52684763b338),
-     C(afe2616651eaad1f), C(43e38715bdfa05e7), C(83c9ba83b5ec4a40),
      C(56486077)},
     {C(44dd59bd301995cf), C(3ccabd76493ada1a), C(540db4c87d55ef23),
-     C(cfc6d7adda35797), C(14c7d1f32332cf03), C(2d553ffbff3be99d),
-     C(c91c4ee0cb563182), C(cfc6d7adda35797), C(14c7d1f32332cf03),
-     C(2d553ffbff3be99d), C(c91c4ee0cb563182), C(9aa5e507f49136f0),
-     C(760c5dd1a82c4888), C(beea7e974a1cfb5c), C(640b247774fe4bf7),
      C(6069be80)},
-    {C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3),
-     C(bce905900c1ec6ea), C(c30f304f4045487d), C(a5c550166b3a142b),
-     C(2f482b4e35327287), C(bce905900c1ec6ea), C(c30f304f4045487d),
-     C(a5c550166b3a142b), C(2f482b4e35327287), C(15b21ddddf355438),
-     C(496471fa3006bab), C(2a8fd458d06c1a32), C(db91e8ae812f0b8d), C(2078359b)},
+    {C(b4d4789eb6f2630b), C(bf6973263ce8ef0e), C(d1c75c50844b9d3), C(2078359b)},
     {C(12807833c463737c), C(58e927ea3b3776b4), C(72dd20ef1c2f8ad0),
-     C(910b610de7a967bf), C(801bc862120f6bf5), C(9653efeed5897681),
-     C(f5367ff83e9ebbb3), C(910b610de7a967bf), C(801bc862120f6bf5),
-     C(9653efeed5897681), C(f5367ff83e9ebbb3), C(cf56d489afd1b0bf),
-     C(c7c793715cae3de8), C(631f91d64abae47c), C(5f1f42fb14a444a2),
      C(9ea21004)},
     {C(e88419922b87176f), C(bcf32f41a7ddbf6f), C(d6ebefd8085c1a0f),
-     C(d1d44fe99451ef72), C(ec951ba8e51e3545), C(c0ca86b360746e96),
-     C(aa679cc066a8040b), C(d1d44fe99451ef72), C(ec951ba8e51e3545),
-     C(c0ca86b360746e96), C(aa679cc066a8040b), C(51065861ece6ffc1),
-     C(76777368a2997e11), C(87f278f46731100c), C(bbaa4140bdba4527),
      C(9c9cfe88)},
     {C(105191e0ec8f7f60), C(5918dbfcca971e79), C(6b285c8a944767b9),
-     C(d3e86ac4f5eccfa4), C(e5399df2b106ca1), C(814aadfacd217f1d),
-     C(2754e3def1c405a9), C(d3e86ac4f5eccfa4), C(e5399df2b106ca1),
-     C(814aadfacd217f1d), C(2754e3def1c405a9), C(99290323b9f06e74),
-     C(a9782e043f271461), C(13c8b3b8c275a860), C(6038d620e581e9e7),
      C(b70a6ddd)},
     {C(a5b88bf7399a9f07), C(fca3ddfd96461cc4), C(ebe738fdc0282fc6),
-     C(69afbc800606d0fb), C(6104b97a9db12df7), C(fcc09198bb90bf9f),
-     C(c5e077e41a65ba91), C(69afbc800606d0fb), C(6104b97a9db12df7),
-     C(fcc09198bb90bf9f), C(c5e077e41a65ba91), C(db261835ee8aa08e),
-     C(db0ee662e5796dc9), C(fc1880ecec499e5f), C(648866fbe1502034),
      C(dea37298)},
     {C(d08c3f5747d84f50), C(4e708b27d1b6f8ac), C(70f70fd734888606),
-     C(909ae019d761d019), C(368bf4aab1b86ef9), C(308bd616d5460239),
-     C(4fd33269f76783ea), C(909ae019d761d019), C(368bf4aab1b86ef9),
-     C(308bd616d5460239), C(4fd33269f76783ea), C(7d53b37c19713eab),
-     C(6bba6eabda58a897), C(91abb50efc116047), C(4e902f347e0e0e35),
      C(8f480819)},
-    {C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36),
-     C(ef79f28d874b9e2d), C(b512089e8e63b76c), C(24dc06833bf193a9),
-     C(3c23308ba8e99d7e), C(ef79f28d874b9e2d), C(b512089e8e63b76c),
-     C(24dc06833bf193a9), C(3c23308ba8e99d7e), C(5ceff7b85cacefb7),
-     C(ef390338898cd73), C(b12967d7d2254f54), C(de874cbd8aef7b75), C(30b3b16)},
+    {C(2f72d12a40044b4b), C(889689352fec53de), C(f03e6ad87eb2f36), C(30b3b16)},
     {C(aa1f61fdc5c2e11e), C(c2c56cd11277ab27), C(a1e73069fdf1f94f),
-     C(8184bab36bb79df0), C(c81929ce8655b940), C(301b11bf8a4d8ce8),
-     C(73126fd45ab75de9), C(8184bab36bb79df0), C(c81929ce8655b940),
-     C(301b11bf8a4d8ce8), C(73126fd45ab75de9), C(4bd6f76e4888229a),
-     C(9aae355b54a756d5), C(ca3de9726f6e99d5), C(83f80cac5bc36852),
      C(f31bc4e8)},
     {C(9489b36fe2246244), C(3355367033be74b8), C(5f57c2277cbce516),
-     C(bc61414f9802ecaf), C(8edd1e7a50562924), C(48f4ab74a35e95f2),
-     C(cc1afcfd99a180e7), C(bc61414f9802ecaf), C(8edd1e7a50562924),
-     C(48f4ab74a35e95f2), C(cc1afcfd99a180e7), C(517dd5e3acf66110),
-     C(7dd3ad9e8978b30d), C(1f6d5dfc70de812b), C(947daaba6441aaf3),
      C(419f953b)},
     {C(358d7c0476a044cd), C(e0b7b47bcbd8854f), C(ffb42ec696705519),
-     C(d45e44c263e95c38), C(df61db53923ae3b1), C(f2bc948cc4fc027c),
-     C(8a8000c6066772a3), C(d45e44c263e95c38), C(df61db53923ae3b1),
-     C(f2bc948cc4fc027c), C(8a8000c6066772a3), C(9fd93c942d31fa17),
-     C(d7651ecebe09cbd3), C(68682cefb6a6f165), C(541eb99a2dcee40e),
      C(20e9e76d)},
     {C(b0c48df14275265a), C(9da4448975905efa), C(d716618e414ceb6d),
-     C(30e888af70df1e56), C(4bee54bd47274f69), C(178b4059e1a0afe5),
-     C(6e2c96b7f58e5178), C(30e888af70df1e56), C(4bee54bd47274f69),
-     C(178b4059e1a0afe5), C(6e2c96b7f58e5178), C(bb429d3b9275e9bc),
-     C(c198013f09cafdc6), C(ec0a6ee4fb5de348), C(744e1e8ed2eb1eb0),
      C(646f0ff8)},
     {C(daa70bb300956588), C(410ea6883a240c6d), C(f5c8239fb5673eb3),
-     C(8b1d7bb4903c105f), C(cfb1c322b73891d4), C(5f3b792b22f07297),
-     C(fd64061f8be86811), C(8b1d7bb4903c105f), C(cfb1c322b73891d4),
-     C(5f3b792b22f07297), C(fd64061f8be86811), C(1d2db712921cfc2b),
-     C(cd1b2b2f2cee18ae), C(6b6f8790dc7feb09), C(46c179efa3f0f518),
      C(eeb7eca8)},
-    {C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685),
-     C(852c9499156a8f3), C(3a180a6abfb79016), C(9fc3c4764037c3c9),
-     C(2890c42fc0d972cf), C(852c9499156a8f3), C(3a180a6abfb79016),
-     C(9fc3c4764037c3c9), C(2890c42fc0d972cf), C(1f92231d4e537651),
-     C(fab8bb07aa54b7b9), C(e05d2d771c485ed4), C(d50b34bf808ca731), C(8112bb9)},
+    {C(4ec97a20b6c4c7c2), C(5913b1cd454f29fd), C(a9629f9daf06d685), C(8112bb9)},
     {C(5c3323628435a2e8), C(1bea45ce9e72a6e3), C(904f0a7027ddb52e),
-     C(939f31de14dcdc7b), C(a68fdf4379df068), C(f169e1f0b835279d),
-     C(7498e432f9619b27), C(939f31de14dcdc7b), C(a68fdf4379df068),
-     C(f169e1f0b835279d), C(7498e432f9619b27), C(1aa2a1f11088e785),
-     C(d6ad72f45729de78), C(9a63814157c80267), C(55538e35c648e435),
      C(85a6d477)},
     {C(c1ef26bea260abdb), C(6ee423f2137f9280), C(df2118b946ed0b43),
-     C(11b87fb1b900cc39), C(e33e59b90dd815b1), C(aa6cb5c4bafae741),
-     C(739699951ca8c713), C(11b87fb1b900cc39), C(e33e59b90dd815b1),
-     C(aa6cb5c4bafae741), C(739699951ca8c713), C(2b4389a967310077),
-     C(1d5382568a31c2c9), C(55d1e787fbe68991), C(277c254bc31301e7),
      C(56f76c84)},
     {C(6be7381b115d653a), C(ed046190758ea511), C(de6a45ffc3ed1159),
-     C(a64760e4041447d0), C(e3eac49f3e0c5109), C(dd86c4d4cb6258e2),
-     C(efa9857afd046c7f), C(a64760e4041447d0), C(e3eac49f3e0c5109),
-     C(dd86c4d4cb6258e2), C(efa9857afd046c7f), C(fab793dae8246f16),
-     C(c9e3b121b31d094c), C(a2a0f55858465226), C(dba6f0ff39436344),
      C(9af45d55)},
     {C(ae3eece1711b2105), C(14fd3f4027f81a4a), C(abb7e45177d151db),
-     C(501f3e9b18861e44), C(465201170074e7d8), C(96d5c91970f2cb12),
-     C(40fd28c43506c95d), C(501f3e9b18861e44), C(465201170074e7d8),
-     C(96d5c91970f2cb12), C(40fd28c43506c95d), C(e86c4b07802aaff3),
-     C(f317d14112372a70), C(641b13e587711650), C(4915421ab1090eaa),
      C(d1c33760)},
     {C(376c28588b8fb389), C(6b045e84d8491ed2), C(4e857effb7d4e7dc),
-     C(154dd79fd2f984b4), C(f11171775622c1c3), C(1fbe30982e78e6f0),
-     C(a460a15dcf327e44), C(154dd79fd2f984b4), C(f11171775622c1c3),
-     C(1fbe30982e78e6f0), C(a460a15dcf327e44), C(f359e0900cc3d582),
-     C(7e11070447976d00), C(324e6daf276ea4b5), C(7aa6e2df0cc94fa2),
      C(c56bbf69)},
     {C(58d943503bb6748f), C(419c6c8e88ac70f6), C(586760cbf3d3d368),
-     C(b7e164979d5ccfc1), C(12cb4230d26bf286), C(f1bf910d44bd84cb),
-     C(b32c24c6a40272), C(b7e164979d5ccfc1), C(12cb4230d26bf286),
-     C(f1bf910d44bd84cb), C(b32c24c6a40272), C(11ed12e34c48c039),
-     C(b0c2538e51d0a6ac), C(4269bb773e1d553a), C(e35a9dbabd34867), C(abecfb9b)},
+     C(abecfb9b)},
     {C(dfff5989f5cfd9a1), C(bcee2e7ea3a96f83), C(681c7874adb29017),
-     C(3ff6c8ac7c36b63a), C(48bc8831d849e326), C(30b078e76b0214e2),
-     C(42954e6ad721b920), C(3ff6c8ac7c36b63a), C(48bc8831d849e326),
-     C(30b078e76b0214e2), C(42954e6ad721b920), C(f9aeb33d164b4472),
-     C(7b353b110831dbdc), C(16f64c82f44ae17b), C(b71244cc164b3b2b),
      C(8de13255)},
     {C(7fb19eb1a496e8f5), C(d49e5dfdb5c0833f), C(c0d5d7b2f7c48dc7),
-     C(1a57313a32f22dde), C(30af46e49850bf8b), C(aa0fe8d12f808f83),
-     C(443e31d70873bb6b), C(1a57313a32f22dde), C(30af46e49850bf8b),
-     C(aa0fe8d12f808f83), C(443e31d70873bb6b), C(bbeb67c49c9fdc13),
-     C(18f1e2a88f59f9d5), C(fb1b05038e5def11), C(d0450b5ce4c39c52),
      C(a98ee299)},
     {C(5dba5b0dadccdbaa), C(4ba8da8ded87fcdc), C(f693fdd25badf2f0),
-     C(e9029e6364286587), C(ae69f49ecb46726c), C(18e002679217c405),
-     C(bd6d66e85332ae9f), C(e9029e6364286587), C(ae69f49ecb46726c),
-     C(18e002679217c405), C(bd6d66e85332ae9f), C(6bf330b1c353dd2a),
-     C(74e9f2e71e3a4152), C(3f85560b50f6c413), C(d33a52a47eaed2b4),
      C(3015f556)},
     {C(688bef4b135a6829), C(8d31d82abcd54e8e), C(f95f8a30d55036d7),
-     C(3d8c90e27aa2e147), C(2ec937ce0aa236b4), C(89b563996d3a0b78),
-     C(39b02413b23c3f08), C(3d8c90e27aa2e147), C(2ec937ce0aa236b4),
-     C(89b563996d3a0b78), C(39b02413b23c3f08), C(8d475a2e64faf2d2),
-     C(48567f7dca46ecaf), C(254cda08d5f87a6d), C(ec6ae9f729c47039),
      C(5a430e29)},
     {C(d8323be05433a412), C(8d48fa2b2b76141d), C(3d346f23978336a5),
-     C(4d50c7537562033f), C(57dc7625b61dfe89), C(9723a9f4c08ad93a),
-     C(5309596f48ab456b), C(4d50c7537562033f), C(57dc7625b61dfe89),
-     C(9723a9f4c08ad93a), C(5309596f48ab456b), C(7e453088019d220f),
-     C(8776067ba6ab9714), C(67e1d06bd195de39), C(74a1a32f8994b918),
      C(2797add0)},
     {C(3b5404278a55a7fc), C(23ca0b327c2d0a81), C(a6d65329571c892c),
-     C(45504801e0e6066b), C(86e6c6d6152a3d04), C(4f3db1c53eca2952),
-     C(d24d69b3e9ef10f3), C(45504801e0e6066b), C(86e6c6d6152a3d04),
-     C(4f3db1c53eca2952), C(d24d69b3e9ef10f3), C(93a0de2219e66a70),
-     C(8932c7115ccb1f8a), C(5ef503fdf2841a8c), C(38064dd9efa80a41),
      C(27d55016)},
     {C(2a96a3f96c5e9bbc), C(8caf8566e212dda8), C(904de559ca16e45e),
-     C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd), C(37b2cbdd973a3ac9),
-     C(7b3223cd9c9497be), C(f13bc2d9c2fe222e), C(be4ccec9a6cdccfd),
-     C(37b2cbdd973a3ac9), C(7b3223cd9c9497be), C(d5904440f376f889),
-     C(62b13187699c473c), C(4751b89251f26726), C(9500d84fa3a61ba8),
      C(84945a82)},
     {C(22bebfdcc26d18ff), C(4b4d8dcb10807ba1), C(40265eee30c6b896),
-     C(3752b423073b119a), C(377dc5eb7c662bdb), C(2b9f07f93a6c25b9),
-     C(96f24ede2bdc0718), C(3752b423073b119a), C(377dc5eb7c662bdb),
-     C(2b9f07f93a6c25b9), C(96f24ede2bdc0718), C(f7699b12c31417bd),
-     C(17b366f401c58b2), C(bf60188d5f437b37), C(484436e56df17f04), C(3ef7e224)},
+     C(3ef7e224)},
     {C(627a2249ec6bbcc2), C(c0578b462a46735a), C(4974b8ee1c2d4f1f),
-     C(ebdbb918eb6d837f), C(8fb5f218dd84147c), C(c77dd1f881df2c54),
-     C(62eac298ec226dc3), C(ebdbb918eb6d837f), C(8fb5f218dd84147c),
-     C(c77dd1f881df2c54), C(62eac298ec226dc3), C(43eded83c4b60bd0),
-     C(9a0a403b5487503b), C(25f305d9147f0bda), C(3ad417f511bc1e64),
      C(35ed8dc8)},
-    {C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4),
-     C(f1b9b413df9d79ed), C(a7621b6fd02db503), C(d92f7ba9928a4ffe),
-     C(53f56babdcae96a6), C(f1b9b413df9d79ed), C(a7621b6fd02db503),
-     C(d92f7ba9928a4ffe), C(53f56babdcae96a6), C(5302b89fc48713ab),
-     C(d03e3b04dbe7a2f2), C(fa74ef8af6d376a7), C(103c8cdea1050ef2),
-     C(6a75e43d)},
+    {C(3abaf1667ba2f3e0), C(ee78476b5eeadc1), C(7e56ac0a6ca4f3f4), C(6a75e43d)},
     {C(3931ac68c5f1b2c9), C(efe3892363ab0fb0), C(40b707268337cd36),
-     C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b), C(7bab08fdd26ba0a4),
-     C(7587743c18fe2475), C(a53a6b64b1ac85c9), C(d50e7f86ee1b832b),
-     C(7bab08fdd26ba0a4), C(7587743c18fe2475), C(e3b5d5d490cf5761),
-     C(dfc053f7d065edd5), C(42ffd8d5fb70129f), C(599ca38677cccdc3),
      C(235d9805)},
-    {C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2),
-     C(dbfaae9642b3205a), C(f676a1339402bcb9), C(f4f12a5b1ac11f29),
-     C(7db8bad81249dee4), C(dbfaae9642b3205a), C(f676a1339402bcb9),
-     C(f4f12a5b1ac11f29), C(7db8bad81249dee4), C(b26e46f2da95922e),
-     C(2aaedd5e12e3c611), C(a0e2d9082966074), C(c64da8a167add63d), C(f7d69572)},
+    {C(b98fb0606f416754), C(46a6e5547ba99c1e), C(c909d82112a8ed2), C(f7d69572)},
     {C(7f7729a33e58fcc4), C(2e4bc1e7a023ead4), C(e707008ea7ca6222),
-     C(47418a71800334a0), C(d10395d8fc64d8a4), C(8257a30062cb66f),
-     C(6786f9b2dc1ff18a), C(47418a71800334a0), C(d10395d8fc64d8a4),
-     C(8257a30062cb66f), C(6786f9b2dc1ff18a), C(5633f437bb2f180f),
-     C(e5a3a405737d22d6), C(ca0ff1ef6f7f0b74), C(d0ae600684b16df8),
      C(bacd0199)},
     {C(42a0aa9ce82848b3), C(57232730e6bee175), C(f89bb3f370782031),
-     C(caa33cf9b4f6619c), C(b2c8648ad49c209f), C(9e89ece0712db1c0),
-     C(101d8274a711a54b), C(caa33cf9b4f6619c), C(b2c8648ad49c209f),
-     C(9e89ece0712db1c0), C(101d8274a711a54b), C(538e79f1e70135cd),
-     C(e1f5a76f983c844e), C(653c082fd66088fc), C(1b9c9b464b654958),
      C(e428f50e)},
     {C(6b2c6d38408a4889), C(de3ef6f68fb25885), C(20754f456c203361),
-     C(941f5023c0c943f9), C(dfdeb9564fd66f24), C(2140cec706b9d406),
-     C(7b22429b131e9c72), C(941f5023c0c943f9), C(dfdeb9564fd66f24),
-     C(2140cec706b9d406), C(7b22429b131e9c72), C(94215c22eb940f45),
-     C(d28b9ed474f7249a), C(6f25e88f2fbf9f56), C(b6718f9e605b38ac),
      C(81eaaad3)},
     {C(930380a3741e862a), C(348d28638dc71658), C(89dedcfd1654ea0d),
-     C(7e7f61684080106), C(837ace9794582976), C(5ac8ca76a357eb1b),
-     C(32b58308625661fb), C(7e7f61684080106), C(837ace9794582976),
-     C(5ac8ca76a357eb1b), C(32b58308625661fb), C(c09705c4572025d9),
-     C(f9187f6af0291303), C(1c0edd8ee4b02538), C(e6cb105daa0578a), C(addbd3e3)},
+     C(addbd3e3)},
     {C(94808b5d2aa25f9a), C(cec72968128195e0), C(d9f4da2bdc1e130f),
-     C(272d8dd74f3006cc), C(ec6c2ad1ec03f554), C(4ad276b249a5d5dd),
-     C(549a22a17c0cde12), C(272d8dd74f3006cc), C(ec6c2ad1ec03f554),
-     C(4ad276b249a5d5dd), C(549a22a17c0cde12), C(602119cb824d7cde),
-     C(f4d3cef240ef35fa), C(e889895e01911bc7), C(785a7e5ac20e852b),
      C(e66dbca0)},
     {C(b31abb08ae6e3d38), C(9eb9a95cbd9e8223), C(8019e79b7ee94ea9),
-     C(7b2271a7a3248e22), C(3b4f700e5a0ba523), C(8ebc520c227206fe),
-     C(da3f861490f5d291), C(7b2271a7a3248e22), C(3b4f700e5a0ba523),
-     C(8ebc520c227206fe), C(da3f861490f5d291), C(d08a689f9f3aa60e),
-     C(547c1b97a068661f), C(4b15a67fa29172f0), C(eaf40c085191d80f),
      C(afe11fd5)},
     {C(dccb5534a893ea1a), C(ce71c398708c6131), C(fe2396315457c164),
-     C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2), C(e42693d5b34e63ab),
-     C(2f4ef2be67f62104), C(3f1229f4d0fd96fb), C(33130aa5fa9d43f2),
-     C(e42693d5b34e63ab), C(2f4ef2be67f62104), C(372e5153516e37b9),
-     C(af9ec142ab12cc86), C(777920c09345e359), C(e7c4a383bef8adc6),
      C(a71a406f)},
     {C(6369163565814de6), C(8feb86fb38d08c2f), C(4976933485cc9a20),
-     C(7d3e82d5ba29a90d), C(d5983cc93a9d126a), C(37e9dfd950e7b692),
-     C(80673be6a7888b87), C(7d3e82d5ba29a90d), C(d5983cc93a9d126a),
-     C(37e9dfd950e7b692), C(80673be6a7888b87), C(57f732dc600808bc),
-     C(59477199802cc78b), C(f824810eb8f2c2de), C(c4a3437f05b3b61c),
      C(9d90eaf5)},
     {C(edee4ff253d9f9b3), C(96ef76fb279ef0ad), C(a4d204d179db2460),
-     C(1f3dcdfa513512d6), C(4dc7ec07283117e4), C(4438bae88ae28bf9),
-     C(aa7eae72c9244a0d), C(1f3dcdfa513512d6), C(4dc7ec07283117e4),
-     C(4438bae88ae28bf9), C(aa7eae72c9244a0d), C(b9aedc8d3ecc72df),
-     C(b75a8eb090a77d62), C(6b15677f9cd91507), C(51d8282cb3a9ddbf),
      C(6665db10)},
     {C(941993df6e633214), C(929bc1beca5b72c6), C(141fc52b8d55572d),
-     C(b3b782ad308f21ed), C(4f2676485041dee0), C(bfe279aed5cb4bc8),
-     C(2a62508a467a22ff), C(b3b782ad308f21ed), C(4f2676485041dee0),
-     C(bfe279aed5cb4bc8), C(2a62508a467a22ff), C(e74d29eab742385d),
-     C(56b05cd90ecfc293), C(c603728ea73f8844), C(8638fcd21bc692c4),
      C(9c977cbf)},
     {C(859838293f64cd4c), C(484403b39d44ad79), C(bf674e64d64b9339),
-     C(44d68afda9568f08), C(478568ed51ca1d65), C(679c204ad3d9e766),
-     C(b28e788878488dc1), C(44d68afda9568f08), C(478568ed51ca1d65),
-     C(679c204ad3d9e766), C(b28e788878488dc1), C(d001a84d3a84fae6),
-     C(d376958fe4cb913e), C(17435277e36c86f0), C(23657b263c347aa6),
      C(ee83ddd4)},
-    {C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51),
-     C(c3314e362764ddb8), C(6481c084ee9ec6b5), C(ede23fb9a251771),
-     C(bd617f2643324590), C(c3314e362764ddb8), C(6481c084ee9ec6b5),
-     C(ede23fb9a251771), C(bd617f2643324590), C(d2d30c9b95e030f5),
-     C(8a517312ffc5795e), C(8b1f325033bd535e), C(3ee6e867e03f2892), C(26519cc)},
+    {C(c19b5648e0d9f555), C(328e47b2b7562993), C(e756b92ba4bd6a51), C(26519cc)},
     {C(f963b63b9006c248), C(9e9bf727ffaa00bc), C(c73bacc75b917e3a),
-     C(2c6aa706129cc54c), C(17a706f59a49f086), C(c7c1eec455217145),
-     C(6adfdc6e07602d42), C(2c6aa706129cc54c), C(17a706f59a49f086),
-     C(c7c1eec455217145), C(6adfdc6e07602d42), C(fb75fca30d848dd2),
-     C(5228c9ed14653ed4), C(953958910153b1a2), C(a430103a24f42a5d),
      C(a485a53f)},
     {C(6a8aa0852a8c1f3b), C(c8f1e5e206a21016), C(2aa554aed1ebb524),
-     C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb), C(fcd6da5e5fae833a),
-     C(51ed3c41f87f9118), C(fc3e3c322cd5d89b), C(b7e3911dc2bd4ebb),
-     C(fcd6da5e5fae833a), C(51ed3c41f87f9118), C(f31750cbc19c420a),
-     C(186dab1abada1d86), C(ca7f88cb894b3cd7), C(2859eeb1c373790c),
      C(f62bc412)},
     {C(740428b4d45e5fb8), C(4c95a4ce922cb0a5), C(e99c3ba78feae796),
-     C(914f1ea2fdcebf5c), C(9566453c07cd0601), C(9841bf66d0462cd),
-     C(79140c1c18536aeb), C(914f1ea2fdcebf5c), C(9566453c07cd0601),
-     C(9841bf66d0462cd), C(79140c1c18536aeb), C(a963b930b05820c2),
-     C(6a7d9fa0c8c45153), C(64214c40d07cf39b), C(7057daf1d806c014),
      C(8975a436)},
-    {C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1),
-     C(99468a917986162b), C(7b31434aac6e0af0), C(f6915c1562c7d82f),
-     C(e4071d82a6dd71db), C(99468a917986162b), C(7b31434aac6e0af0),
-     C(f6915c1562c7d82f), C(e4071d82a6dd71db), C(5f5331f077b5d996),
-     C(7b314ba21b747a4f), C(5a73cb9521da17f5), C(12ed435fae286d86),
-     C(94ff7f41)},
-    {C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680),
-     C(8799e4740e573c50), C(9e739b52d0f341e8), C(cdfd34ba7d7b03eb),
-     C(5061812ce6c88499), C(8799e4740e573c50), C(9e739b52d0f341e8),
-     C(cdfd34ba7d7b03eb), C(5061812ce6c88499), C(612b8d8f2411dc5c),
-     C(878bd883d29c7787), C(47a846727182bb), C(ec4949508c8b3b9a), C(760aa031)},
-    {C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4),
-     C(8063d80ab26f3d6d), C(4177b4b9b4f0393f), C(6de42ba8672b9640),
-     C(d0bccdb72c51c18), C(8063d80ab26f3d6d), C(4177b4b9b4f0393f),
-     C(6de42ba8672b9640), C(d0bccdb72c51c18), C(af3f611b7f22cf12),
-     C(3863c41492645755), C(928c7a616a8f14f9), C(a82c78eb2eadc58b),
-     C(3bda76df)},
+    {C(658b883b3a872b86), C(2f0e303f0f64827a), C(975337e23dc45e1), C(94ff7f41)},
+    {C(6df0a977da5d27d4), C(891dd0e7cb19508), C(fd65434a0b71e680), C(760aa031)},
+    {C(a900275464ae07ef), C(11f2cfda34beb4a3), C(9abf91e5a1c38e4), C(3bda76df)},
     {C(810bc8aa0c40bcb0), C(448a019568d01441), C(f60ec52f60d3aeae),
-     C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b), C(345b793ccfa93055),
-     C(932160fe802ca975), C(52c44837aa6dfc77), C(15d8d8fccdd6dc5b),
-     C(345b793ccfa93055), C(932160fe802ca975), C(a624b0dd93fc18cd),
-     C(d955b254c2037f1e), C(e540533d370a664c), C(2ba4ec12514e9d7), C(498e2e65)},
+     C(498e2e65)},
     {C(22036327deb59ed7), C(adc05ceb97026a02), C(48bff0654262672b),
-     C(c791b313aba3f258), C(443c7757a4727bee), C(e30e4b2372171bdf),
-     C(f3db986c4156f3cb), C(c791b313aba3f258), C(443c7757a4727bee),
-     C(e30e4b2372171bdf), C(f3db986c4156f3cb), C(a939aefab97c6e15),
-     C(dbeb8acf1d5b0e6c), C(1e0eab667a795bba), C(80dd539902df4d50),
      C(d38deb48)},
     {C(7d14dfa9772b00c8), C(595735efc7eeaed7), C(29872854f94c3507),
-     C(bc241579d8348401), C(16dc832804d728f0), C(e9cc71ae64e3f09e),
-     C(bef634bc978bac31), C(bc241579d8348401), C(16dc832804d728f0),
-     C(e9cc71ae64e3f09e), C(bef634bc978bac31), C(7f64b1fa2a9129e),
-     C(71d831bd530ac7f3), C(c7ad0a8a6d5be6f1), C(82a7d3a815c7aaab),
      C(82b3fb6b)},
     {C(2d777cddb912675d), C(278d7b10722a13f9), C(f5c02bfb7cc078af),
-     C(4283001239888836), C(f44ca39a6f79db89), C(ed186122d71bcc9f),
-     C(8620017ab5f3ba3b), C(4283001239888836), C(f44ca39a6f79db89),
-     C(ed186122d71bcc9f), C(8620017ab5f3ba3b), C(e787472187f176c),
-     C(267e64c4728cf181), C(f1ba4b3007c15e30), C(8e3a75d5b02ecfc0),
      C(e500e25f)},
     {C(f2ec98824e8aa613), C(5eb7e3fb53fe3bed), C(12c22860466e1dd4),
-     C(374dd4288e0b72e5), C(ff8916db706c0df4), C(cb1a9e85de5e4b8d),
-     C(d4d12afb67a27659), C(374dd4288e0b72e5), C(ff8916db706c0df4),
-     C(cb1a9e85de5e4b8d), C(d4d12afb67a27659), C(feb69095d1ba175a),
-     C(e2003aab23a47fad), C(8163a3ecab894b49), C(46d356674ce041f6),
      C(bd2bb07c)},
     {C(5e763988e21f487f), C(24189de8065d8dc5), C(d1519d2403b62aa0),
-     C(9136456740119815), C(4d8ff7733b27eb83), C(ea3040bc0c717ef8),
-     C(7617ab400dfadbc), C(9136456740119815), C(4d8ff7733b27eb83),
-     C(ea3040bc0c717ef8), C(7617ab400dfadbc), C(fb336770c10b17a1),
-     C(6123b68b5b31f151), C(1e147d5f295eccf2), C(9ecbb1333556f977),
      C(3a2b431d)},
     {C(48949dc327bb96ad), C(e1fd21636c5c50b4), C(3f6eb7f13a8712b4),
-     C(14cf7f02dab0eee8), C(6d01750605e89445), C(4f1cf4006e613b78),
-     C(57c40c4db32bec3b), C(14cf7f02dab0eee8), C(6d01750605e89445),
-     C(4f1cf4006e613b78), C(57c40c4db32bec3b), C(1fde5a347f4a326e),
-     C(cb5a54308adb0e3f), C(14994b2ba447a23c), C(7067d0abb4257b68),
      C(7322a83d)},
     {C(b7c4209fb24a85c5), C(b35feb319c79ce10), C(f0d3de191833b922),
-     C(570d62758ddf6397), C(5e0204fb68a7b800), C(4383a9236f8b5a2b),
-     C(7bc1a64641d803a4), C(570d62758ddf6397), C(5e0204fb68a7b800),
-     C(4383a9236f8b5a2b), C(7bc1a64641d803a4), C(5434d61285099f7a),
-     C(d49449aacdd5dd67), C(97855ba0e9a7d75d), C(da67328062f3a62f),
      C(a645ca1c)},
     {C(9c9e5be0943d4b05), C(b73dc69e45201cbb), C(aab17180bfe5083d),
-     C(c738a77a9a55f0e2), C(705221addedd81df), C(fd9bd8d397abcfa3),
-     C(8ccf0004aa86b795), C(c738a77a9a55f0e2), C(705221addedd81df),
-     C(fd9bd8d397abcfa3), C(8ccf0004aa86b795), C(2bb5db2280068206),
-     C(8c22d29f307a01d), C(274a22de02f473c8), C(b8791870f4268182), C(8909a45a)},
+     C(8909a45a)},
     {C(3898bca4dfd6638d), C(f911ff35efef0167), C(24bdf69e5091fc88),
-     C(9b82567ab6560796), C(891b69462b41c224), C(8eccc7e4f3af3b51),
-     C(381e54c3c8f1c7d0), C(9b82567ab6560796), C(891b69462b41c224),
-     C(8eccc7e4f3af3b51), C(381e54c3c8f1c7d0), C(c80fbc489a558a55),
-     C(1ba88e062a663af7), C(af7b1ef1c0116303), C(bd20e1a5a6b1a0cd),
      C(bd30074c)},
-    {C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb),
-     C(3c13e894365dc6c2), C(26fc7bbcda3f0ef), C(dbb71106cdbfea36),
-     C(785239a742c6d26d), C(3c13e894365dc6c2), C(26fc7bbcda3f0ef),
-     C(dbb71106cdbfea36), C(785239a742c6d26d), C(f810c415ae05b2f4),
-     C(bb9b9e7398526088), C(70128f1bf830a32b), C(bcc73f82b6410899),
-     C(c17cf001)},
+    {C(5b5d2557400e68e7), C(98d610033574cee), C(dfd08772ce385deb), C(c17cf001)},
     {C(a927ed8b2bf09bb6), C(606e52f10ae94eca), C(71c2203feb35a9ee),
-     C(6e65ec14a8fb565), C(34bff6f2ee5a7f79), C(2e329a5be2c011b),
-     C(73161c93331b14f9), C(6e65ec14a8fb565), C(34bff6f2ee5a7f79),
-     C(2e329a5be2c011b), C(73161c93331b14f9), C(15d13f2408aecf88),
-     C(9f5b61b8a4b55b31), C(8fe25a43b296dba6), C(bdad03b7300f284e),
      C(26ffd25a)},
     {C(8d25746414aedf28), C(34b1629d28b33d3a), C(4d5394aea5f82d7b),
-     C(379f76458a3c8957), C(79dd080f9843af77), C(c46f0a7847f60c1d),
-     C(af1579c5797703cc), C(379f76458a3c8957), C(79dd080f9843af77),
-     C(c46f0a7847f60c1d), C(af1579c5797703cc), C(8b7d31f338755c14),
-     C(2eff97679512aaa8), C(df07d68e075179ed), C(c8fa6c7a729e7f1f),
      C(f1d8ce3c)},
     {C(b5bbdb73458712f2), C(1ff887b3c2a35137), C(7f7231f702d0ace9),
-     C(1e6f0910c3d25bd8), C(ad9e250862102467), C(1c842a07abab30cd),
-     C(cd8124176bac01ac), C(1e6f0910c3d25bd8), C(ad9e250862102467),
-     C(1c842a07abab30cd), C(cd8124176bac01ac), C(ea6ebe7a79b67edc),
-     C(73f598ac9db26713), C(4f4e72d7460b8fc), C(365dc4b9fdf13f21), C(3ee8fb17)},
+     C(3ee8fb17)},
     {C(3d32a26e3ab9d254), C(fc4070574dc30d3a), C(f02629579c2b27c9),
-     C(b1cf09b0184a4834), C(5c03db48eb6cc159), C(f18c7fcf34d1df47),
-     C(dfb043419ecf1fa9), C(b1cf09b0184a4834), C(5c03db48eb6cc159),
-     C(f18c7fcf34d1df47), C(dfb043419ecf1fa9), C(dcd78d13f9ca658f),
-     C(4355d408ffe8e49f), C(81eefee908b593b4), C(590c213c20e981a3),
      C(a77acc2a)},
-    {C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c),
-     C(ceaf1a0d15234f15), C(1450a54e45ba9b9), C(65e9c1fd885aa932),
-     C(354d4bc034ba8cbe), C(ceaf1a0d15234f15), C(1450a54e45ba9b9),
-     C(65e9c1fd885aa932), C(354d4bc034ba8cbe), C(8fd4ff484c08fb4b),
-     C(bf46749866f69ba0), C(cf1c21ede82c9477), C(4217548c43da109), C(f4556dee)},
-    {C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9),
-     C(85b8e53f22e19507), C(bb57137739ca486b), C(c77f131cca38f761),
-     C(c56ac3cf275be121), C(85b8e53f22e19507), C(bb57137739ca486b),
-     C(c77f131cca38f761), C(c56ac3cf275be121), C(9ec1a6c9109d2685),
-     C(3dad0922e76afdb0), C(fd58cbf952958103), C(7b04c908e78639a1),
-     C(de287a64)},
+    {C(9371d3c35fa5e9a5), C(42967cf4d01f30), C(652d1eeae704145c), C(f4556dee)},
+    {C(cbaa3cb8f64f54e0), C(76c3b48ee5c08417), C(9f7d24e87e61ce9), C(de287a64)},
     {C(b2e23e8116c2ba9f), C(7e4d9c0060101151), C(3310da5e5028f367),
-     C(adc52dddb76f6e5e), C(4aad4e925a962b68), C(204b79b7f7168e64),
-     C(df29ed6671c36952), C(adc52dddb76f6e5e), C(4aad4e925a962b68),
-     C(204b79b7f7168e64), C(df29ed6671c36952), C(e02927cac396d210),
-     C(5d500e71742b638a), C(5c9998af7f27b124), C(3fba9a2573dc2f7), C(878e55b9)},
-    {C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5),
-     C(ce030d15b5fe2f4), C(86b4a7a0780c2431), C(ee070a9ae5b51db7),
-     C(edc293d9595be5d8), C(ce030d15b5fe2f4), C(86b4a7a0780c2431),
-     C(ee070a9ae5b51db7), C(edc293d9595be5d8), C(3dfc5ec108260a2b),
-     C(8afe28c7123bf4e2), C(da82ef38023a7a5f), C(3e1f77b0174b77c3), C(7648486)},
+     C(878e55b9)},
+    {C(8aa77f52d7868eb9), C(4d55bd587584e6e2), C(d2db37041f495f5), C(7648486)},
     {C(858fea922c7fe0c3), C(cfe8326bf733bc6f), C(4e5e2018cf8f7dfc),
-     C(64fd1bc011e5bab7), C(5c9e858728015568), C(97ac42c2b00b29b1),
-     C(7f89caf08c109aee), C(64fd1bc011e5bab7), C(5c9e858728015568),
-     C(97ac42c2b00b29b1), C(7f89caf08c109aee), C(9a8af34fd0e9dacf),
-     C(bbc54161aa1507e0), C(7cda723ccbbfe5ee), C(2c289d839fb93f58),
      C(57ac0fb1)},
     {C(46ef25fdec8392b1), C(e48d7b6d42a5cd35), C(56a6fe1c175299ca),
-     C(fdfa836b41dcef62), C(2f8db8030e847e1b), C(5ba0a49ac4f9b0f8),
-     C(dae897ed3e3fce44), C(fdfa836b41dcef62), C(2f8db8030e847e1b),
-     C(5ba0a49ac4f9b0f8), C(dae897ed3e3fce44), C(9c432e31aef626e7),
-     C(9a36e1c6cd6e3dd), C(5095a167c34d19d), C(a70005cfa6babbea), C(d01967ca)},
+     C(d01967ca)},
     {C(8d078f726b2df464), C(b50ee71cdcabb299), C(f4af300106f9c7ba),
-     C(7d222caae025158a), C(cc028d5fd40241b9), C(dd42515b639e6f97),
-     C(e08e86531a58f87f), C(7d222caae025158a), C(cc028d5fd40241b9),
-     C(dd42515b639e6f97), C(e08e86531a58f87f), C(d93612c835b37d7b),
-     C(91dd61729b2fa7f4), C(ba765a1bdda09db7), C(55258b451b2b1297),
      C(96ecdf74)},
     {C(35ea86e6960ca950), C(34fe1fe234fc5c76), C(a00207a3dc2a72b7),
-     C(80395e48739e1a67), C(74a67d8f7f43c3d7), C(dd2bdd1d62246c6e),
-     C(a1f44298ba80acf6), C(80395e48739e1a67), C(74a67d8f7f43c3d7),
-     C(dd2bdd1d62246c6e), C(a1f44298ba80acf6), C(ad86d86c187bf38),
-     C(26feea1f2eee240d), C(ed7f1fd066b23897), C(a768cf1e0fbb502), C(779f5506)},
+     C(779f5506)},
     {C(8aee9edbc15dd011), C(51f5839dc8462695), C(b2213e17c37dca2d),
-     C(133b299a939745c5), C(796e2aac053f52b3), C(e8d9fe1521a4a222),
-     C(819a8863e5d1c290), C(133b299a939745c5), C(796e2aac053f52b3),
-     C(e8d9fe1521a4a222), C(819a8863e5d1c290), C(c0737f0fe34d36ad),
-     C(e6d6d4a267a5cc31), C(98300a7911674c23), C(bef189661c257098),
      C(3c94c2de)},
     {C(c3e142ba98432dda), C(911d060cab126188), C(b753fbfa8365b844),
-     C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533), C(b543161ff177188a),
-     C(492fc08a6186f3f4), C(fd1a9ba5e71b08a2), C(7ac0dc2ed7778533),
-     C(b543161ff177188a), C(492fc08a6186f3f4), C(fc4745f516afd3b6),
-     C(88c30370a53080e), C(65a1bb34abc465e2), C(abbd14662911c8b3), C(39f98faf)},
+     C(39f98faf)},
     {C(123ba6b99c8cd8db), C(448e582672ee07c4), C(cebe379292db9e65),
-     C(938f5bbab544d3d6), C(d2a95f9f2d376d73), C(68b2f16149e81aa3),
-     C(ad7e32f82d86c79d), C(938f5bbab544d3d6), C(d2a95f9f2d376d73),
-     C(68b2f16149e81aa3), C(ad7e32f82d86c79d), C(4574015ae8626ce2),
-     C(455aa6137386a582), C(658ad2542e8ec20), C(e31d7be2ca35d00), C(7af31199)},
+     C(7af31199)},
     {C(ba87acef79d14f53), C(b3e0fcae63a11558), C(d5ac313a593a9f45),
-     C(eea5f5a9f74af591), C(578710bcc36fbea2), C(7a8393432188931d),
-     C(705cfc5ec7cc172), C(eea5f5a9f74af591), C(578710bcc36fbea2),
-     C(7a8393432188931d), C(705cfc5ec7cc172), C(da85ebe5fc427976),
-     C(bfa5c7a454df54c8), C(4632b72a81bf66d2), C(5dd72877db539ee2),
      C(e341a9d6)},
-    {C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472),
-     C(2b826f1a2c08c289), C(da50f56863b55e74), C(b18712f6b3eed83b),
-     C(bdc7cc05ab4c685f), C(2b826f1a2c08c289), C(da50f56863b55e74),
-     C(b18712f6b3eed83b), C(bdc7cc05ab4c685f), C(9e45fb833d1b0af),
-     C(d7213081db29d82e), C(d2a6b6c6a09ed55e), C(98a7686cba323ca9),
-     C(ca24aeeb)},
+    {C(bcd3957d5717dc3), C(2da746741b03a007), C(873816f4b1ece472), C(ca24aeeb)},
     {C(61442ff55609168e), C(6447c5fc76e8c9cf), C(6a846de83ae15728),
-     C(effc2663cffc777f), C(93214f8f463afbed), C(a156ef06066f4e4e),
-     C(a407b6ed8769d51e), C(effc2663cffc777f), C(93214f8f463afbed),
-     C(a156ef06066f4e4e), C(a407b6ed8769d51e), C(bb2f9ed29745c02a),
-     C(981eecd435b36ad9), C(461a5a05fb9cdff4), C(bd6cb2a87b9f910c),
      C(b2252b57)},
-    {C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f),
-     C(5a4fc2728a9bb671), C(ebb971522ec38759), C(1a5a093e6cf1f72b),
-     C(729b057fe784f504), C(5a4fc2728a9bb671), C(ebb971522ec38759),
-     C(1a5a093e6cf1f72b), C(729b057fe784f504), C(71fcbf42a767f9cf),
-     C(114cfe772da6cdd), C(60cdf9cb629d9d7a), C(e270d10ad088b24e), C(72c81da1)},
+    {C(dbe4b1b2d174757f), C(506512da18712656), C(6857f3e0b8dd95f), C(72c81da1)},
     {C(531e8e77b363161c), C(eece0b43e2dae030), C(8294b82c78f34ed1),
-     C(e777b1fd580582f2), C(7b880f58da112699), C(562c6b189a6333f4),
-     C(139d64f88a611d4), C(e777b1fd580582f2), C(7b880f58da112699),
-     C(562c6b189a6333f4), C(139d64f88a611d4), C(53d8ef17eda64fa4),
-     C(bf3eded14dc60a04), C(2b5c559cf5ec07c5), C(8895f7339d03a48a),
      C(6b9fce95)},
     {C(f71e9c926d711e2b), C(d77af2853a4ceaa1), C(9aa0d6d76a36fae7),
-     C(dd16cd0fbc08393), C(29a414a5d8c58962), C(72793d8d1022b5b2),
-     C(2e8e69cf7cbffdf0), C(dd16cd0fbc08393), C(29a414a5d8c58962),
-     C(72793d8d1022b5b2), C(2e8e69cf7cbffdf0), C(3721c0473aa99c9a),
-     C(1cff4ed9c31cd91c), C(4990735033cc482b), C(7fdf8c701c72f577),
      C(19399857)},
     {C(cb20ac28f52df368), C(e6705ee7880996de), C(9b665cc3ec6972f2),
-     C(4260e8c254e9924b), C(f197a6eb4591572d), C(8e867ff0fb7ab27c),
-     C(f95502fb503efaf3), C(4260e8c254e9924b), C(f197a6eb4591572d),
-     C(8e867ff0fb7ab27c), C(f95502fb503efaf3), C(30c41876b08e3e22),
-     C(958e2419e3cd22f4), C(f0f3aa1fe119a107), C(481662310a379100),
      C(3c57a994)},
     {C(e4a794b4acb94b55), C(89795358057b661b), C(9c4cdcec176d7a70),
-     C(4890a83ee435bc8b), C(d8c1c00fceb00914), C(9e7111ba234f900f),
-     C(eb8dbab364d8b604), C(4890a83ee435bc8b), C(d8c1c00fceb00914),
-     C(9e7111ba234f900f), C(eb8dbab364d8b604), C(b3261452963eebb),
-     C(6cf94b02792c4f95), C(d88fa815ef1e8fc), C(2d687af66604c73), C(c053e729)},
+     C(c053e729)},
     {C(cb942e91443e7208), C(e335de8125567c2a), C(d4d74d268b86df1f),
-     C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f), C(c05b2717c59a8a28),
-     C(981188eab4fcc8fb), C(8ba0fdd2ffc8b239), C(f413b366c1ffe02f),
-     C(c05b2717c59a8a28), C(981188eab4fcc8fb), C(e563f49a1d9072ba),
-     C(3c6a3aa4a26367dc), C(ba0db13448653f34), C(31065d756074d7d6),
      C(51cbbba7)},
     {C(ecca7563c203f7ba), C(177ae2423ef34bb2), C(f60b7243400c5731),
-     C(cf1edbfe7330e94e), C(881945906bcb3cc6), C(4acf0293244855da),
-     C(65ae042c1c2a28c2), C(cf1edbfe7330e94e), C(881945906bcb3cc6),
-     C(4acf0293244855da), C(65ae042c1c2a28c2), C(b25fa0a1cab33559),
-     C(d98e8daa28124131), C(fce17f50b9c351b3), C(3f995ccf7386864b),
      C(1acde79a)},
     {C(1652cb940177c8b5), C(8c4fe7d85d2a6d6d), C(f6216ad097e54e72),
-     C(f6521b912b368ae6), C(a9fe4eff81d03e73), C(d6f623629f80d1a3),
-     C(2b9604f32cb7dc34), C(f6521b912b368ae6), C(a9fe4eff81d03e73),
-     C(d6f623629f80d1a3), C(2b9604f32cb7dc34), C(2a43d84dcf59c7e2),
-     C(d0a197c70c5dae0b), C(6e84d4bbc71d76a0), C(c7e94620378c6cb2),
      C(2d160d13)},
     {C(31fed0fc04c13ce8), C(3d5d03dbf7ff240a), C(727c5c9b51581203),
-     C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9), C(c4d5a32cd6aac22d),
-     C(d7e274ad22d4a79a), C(6b5ffc1f54fecb29), C(a8e8e7ad5b9a21d9),
-     C(c4d5a32cd6aac22d), C(d7e274ad22d4a79a), C(368841ea5731a112),
-     C(feaf7bc2e73ca48f), C(636fb272e9ea1f6), C(5d9cb7580c3f6207), C(787f5801)},
+     C(787f5801)},
     {C(e7b668947590b9b3), C(baa41ad32938d3fa), C(abcbc8d4ca4b39e4),
-     C(381ee1b7ea534f4e), C(da3759828e3de429), C(3e015d76729f9955),
-     C(cbbec51a6485fbde), C(381ee1b7ea534f4e), C(da3759828e3de429),
-     C(3e015d76729f9955), C(cbbec51a6485fbde), C(9b86605281f20727),
-     C(fc6fcf508676982a), C(3b135f7a813a1040), C(d3a4706bea1db9c9),
      C(c9629828)},
     {C(1de2119923e8ef3c), C(6ab27c096cf2fe14), C(8c3658edca958891),
-     C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e), C(9085b0a862084201),
-     C(a1894bde9e3dee21), C(4cc8ed3ada5f0f2), C(4a496b77c1f1c04e),
-     C(9085b0a862084201), C(a1894bde9e3dee21), C(367fb472dc5b277d),
-     C(7d39ccca16fc6745), C(763f988d70db9106), C(a8b66f7fecb70f02),
      C(be139231)},
     {C(1269df1e69e14fa7), C(992f9d58ac5041b7), C(e97fcf695a7cbbb4),
-     C(e5d0549802d15008), C(424c134ecd0db834), C(6fc44fd91be15c6c),
-     C(a1a5ef95d50e537d), C(e5d0549802d15008), C(424c134ecd0db834),
-     C(6fc44fd91be15c6c), C(a1a5ef95d50e537d), C(d1e3daf5d05f5308),
-     C(4c7f81600eaa1327), C(109d1b8d1f9d0d2b), C(871e8699e0aeb862),
      C(7df699ef)},
     {C(820826d7aba567ff), C(1f73d28e036a52f3), C(41c4c5a73f3b0893),
-     C(aa0d74d4a98db89b), C(36fd486d07c56e1d), C(d0ad23cbb6660d8a),
-     C(1264a84665b35e19), C(aa0d74d4a98db89b), C(36fd486d07c56e1d),
-     C(d0ad23cbb6660d8a), C(1264a84665b35e19), C(789682bf7d781b33),
-     C(6bfa6abd2fb5722d), C(6779cb3623d33900), C(435ca5214e1ee5f0),
      C(8ce6b96d)},
     {C(ffe0547e4923cef9), C(3534ed49b9da5b02), C(548a273700fba03d),
-     C(28ac84ca70958f7e), C(d8ae575a68faa731), C(2aaaee9b9dcffd4c),
-     C(6c7faab5c285c6da), C(28ac84ca70958f7e), C(d8ae575a68faa731),
-     C(2aaaee9b9dcffd4c), C(6c7faab5c285c6da), C(45d94235f99ba78f),
-     C(ab5ea16f39497f5b), C(fb4d6c86fccbdca3), C(8104e6310a5fd2c7),
      C(6f9ed99c)},
     {C(72da8d1b11d8bc8b), C(ba94b56b91b681c6), C(4e8cc51bd9b0fc8c),
-     C(43505ed133be672a), C(e8f2f9d973c2774e), C(677b9b9c7cad6d97),
-     C(4e1f5d56ef17b906), C(43505ed133be672a), C(e8f2f9d973c2774e),
-     C(677b9b9c7cad6d97), C(4e1f5d56ef17b906), C(eea3a6038f983767),
-     C(87109f077f86db01), C(ecc1ca41f74d61cc), C(34a87e86e83bed17),
      C(e0244796)},
-    {C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465),
-     C(4344a1a0134afe2), C(ff5c17f02b62341d), C(3214c6a587ce4644),
-     C(a905e7ed0629d05c), C(4344a1a0134afe2), C(ff5c17f02b62341d),
-     C(3214c6a587ce4644), C(a905e7ed0629d05c), C(b5c72690cd716e82),
-     C(7c6097649e6ebe7b), C(7ceee8c6e56a4dcd), C(80ca849dc53eb9e4),
-     C(4ccf7e75)},
+    {C(d62ab4e3f88fc797), C(ea86c7aeb6283ae4), C(b5b93e09a7fe465), C(4ccf7e75)},
     {C(d0f06c28c7b36823), C(1008cb0874de4bb8), C(d6c7ff816c7a737b),
-     C(489b697fe30aa65f), C(4da0fb621fdc7817), C(dc43583b82c58107),
-     C(4b0261debdec3cd6), C(489b697fe30aa65f), C(4da0fb621fdc7817),
-     C(dc43583b82c58107), C(4b0261debdec3cd6), C(a9748d7b6c0e016c),
-     C(7e8828f7ba4b034b), C(da0fa54348a2512a), C(ebf9745c0962f9ad),
      C(915cef86)},
     {C(99b7042460d72ec6), C(2a53e5e2b8e795c2), C(53a78132d9e1b3e3),
-     C(c043e67e6fc64118), C(ff0abfe926d844d3), C(f2a9fe5db2e910fe),
-     C(ce352cdc84a964dd), C(c043e67e6fc64118), C(ff0abfe926d844d3),
-     C(f2a9fe5db2e910fe), C(ce352cdc84a964dd), C(b89bc028aa5e6063),
-     C(a354e7fdac04459c), C(68d6547e6e980189), C(c968dddfd573773e),
      C(5cb59482)},
-    {C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3),
-     C(334c5a25b5903a8c), C(4c94fef443122128), C(743e7d8454655c40),
-     C(1ab1e6d1452ae2cd), C(334c5a25b5903a8c), C(4c94fef443122128),
-     C(743e7d8454655c40), C(1ab1e6d1452ae2cd), C(fec766de4a8e476c),
-     C(cc0929da9567e71b), C(5f9ef5b5f150c35a), C(87659cabd649768f),
-     C(6ca3f532)},
+    {C(4f4dfcfc0ec2bae5), C(841233148268a1b8), C(9248a76ab8be0d3), C(6ca3f532)},
     {C(fe86bf9d4422b9ae), C(ebce89c90641ef9c), C(1c84e2292c0b5659),
-     C(8bde625a10a8c50d), C(eb8271ded1f79a0b), C(14dc6844f0de7a3c),
-     C(f85b2f9541e7e6da), C(8bde625a10a8c50d), C(eb8271ded1f79a0b),
-     C(14dc6844f0de7a3c), C(f85b2f9541e7e6da), C(2fe22cfd1683b961),
-     C(ea1d75c5b7aa01ca), C(9eef60a44876bb95), C(950c818e505c6f7f),
      C(e24f3859)},
     {C(a90d81060932dbb0), C(8acfaa88c5fbe92b), C(7c6f3447e90f7f3f),
-     C(dd52fc14c8dd3143), C(1bc7508516e40628), C(3059730266ade626),
-     C(ffa526822f391c2), C(dd52fc14c8dd3143), C(1bc7508516e40628),
-     C(3059730266ade626), C(ffa526822f391c2), C(e25232d7afc8a406),
-     C(d2b8a5a3f3b5f670), C(6630f33edb7dfe32), C(c71250ba68c4ea86),
      C(adf5a9c7)},
     {C(17938a1b0e7f5952), C(22cadd2f56f8a4be), C(84b0d1183d5ed7c1),
-     C(c1336b92fef91bf6), C(80332a3945f33fa9), C(a0f68b86f726ff92),
-     C(a3db5282cf5f4c0b), C(c1336b92fef91bf6), C(80332a3945f33fa9),
-     C(a0f68b86f726ff92), C(a3db5282cf5f4c0b), C(82640b6fc4916607),
-     C(2dc2a3aa1a894175), C(8b4c852bdee7cc9), C(10b9d0a08b55ff83), C(32264b75)},
+     C(32264b75)},
     {C(de9e0cb0e16f6e6d), C(238e6283aa4f6594), C(4fb9c914c2f0a13b),
-     C(497cb912b670f3b), C(d963a3f02ff4a5b6), C(4fccefae11b50391),
-     C(42ba47db3f7672f), C(497cb912b670f3b), C(d963a3f02ff4a5b6),
-     C(4fccefae11b50391), C(42ba47db3f7672f), C(1d6b655a1889feef),
-     C(5f319abf8fafa19f), C(715c2e49deb14620), C(8d9153082ecdcea4),
      C(a64b3376)},
-    {C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5),
-     C(2fe9fabdbe7fdd4), C(755db249a2d81a69), C(f27929f360446d71),
-     C(79a1bf957c0c1b92), C(2fe9fabdbe7fdd4), C(755db249a2d81a69),
-     C(f27929f360446d71), C(79a1bf957c0c1b92), C(3c8a28d4c936c9cd),
-     C(df0d3d13b2c6a902), C(c76702dd97cd2edd), C(1aa220f7be16517), C(d33890e)},
+    {C(6d4b876d9b146d1a), C(aab2d64ce8f26739), C(d315f93600e83fe5), C(d33890e)},
     {C(e698fa3f54e6ea22), C(bd28e20e7455358c), C(9ace161f6ea76e66),
-     C(d53fb7e3c93a9e4), C(737ae71b051bf108), C(7ac71feb84c2df42),
-     C(3d8075cd293a15b4), C(d53fb7e3c93a9e4), C(737ae71b051bf108),
-     C(7ac71feb84c2df42), C(3d8075cd293a15b4), C(bf8cee5e095d8a7c),
-     C(e7086b3c7608143a), C(e55b0c2fa938d70c), C(fffb5f58e643649c),
      C(926d4b63)},
     {C(7bc0deed4fb349f7), C(1771aff25dc722fa), C(19ff0644d9681917),
-     C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f), C(b9064f5c3cb11b71),
-     C(237e39229b012b20), C(cf7d7f25bd70cd2c), C(9464ed9baeb41b4f),
-     C(b9064f5c3cb11b71), C(237e39229b012b20), C(dd54d3f5d982dffe),
-     C(7fc7562dbfc81dbf), C(5b0dd1924f70945), C(f1760537d8261135), C(d51ba539)},
+     C(d51ba539)},
     {C(db4b15e88533f622), C(256d6d2419b41ce9), C(9d7c5378396765d5),
-     C(9040e5b936b8661b), C(276e08fa53ac27fd), C(8c944d39c2bdd2cc),
-     C(e2514c9802a5743c), C(9040e5b936b8661b), C(276e08fa53ac27fd),
-     C(8c944d39c2bdd2cc), C(e2514c9802a5743c), C(e82107b11ac90386),
-     C(7d6a22bc35055e6), C(fd6ea9d1c438d8ae), C(be6015149e981553), C(7f37636d)},
+     C(7f37636d)},
     {C(922834735e86ecb2), C(363382685b88328e), C(e9c92960d7144630),
-     C(8431b1bfd0a2379c), C(90383913aea283f9), C(a6163831eb4924d2),
-     C(5f3921b4f9084aee), C(8431b1bfd0a2379c), C(90383913aea283f9),
-     C(a6163831eb4924d2), C(5f3921b4f9084aee), C(7a70061a1473e579),
-     C(5b19d80dcd2c6331), C(6196b97931faad27), C(869bf6828e237c3f),
      C(b98026c0)},
     {C(30f1d72c812f1eb8), C(b567cd4a69cd8989), C(820b6c992a51f0bc),
-     C(c54677a80367125e), C(3204fbdba462e606), C(8563278afc9eae69),
-     C(262147dd4bf7e566), C(c54677a80367125e), C(3204fbdba462e606),
-     C(8563278afc9eae69), C(262147dd4bf7e566), C(2178b63e7ee2d230),
-     C(e9c61ad81f5bff26), C(9af7a81b3c501eca), C(44104a3859f0238f),
      C(b877767e)},
-    {C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a),
-     C(9598f6ab0683fcc2), C(1c805abf7b80e1ee), C(dec9ac42ee0d0f32),
-     C(8cd72e3912d24663), C(9598f6ab0683fcc2), C(1c805abf7b80e1ee),
-     C(dec9ac42ee0d0f32), C(8cd72e3912d24663), C(1f025d405f1c1d87),
-     C(bf7b6221e1668f8f), C(52316f64e692dbb0), C(7bf43df61ec51b39), C(aefae77)},
-    {C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d),
-     C(6ba372f4b7ab268b), C(8c3237cf1fe243df), C(3833fc51012903df),
-     C(8e31310108c5683f), C(6ba372f4b7ab268b), C(8c3237cf1fe243df),
-     C(3833fc51012903df), C(8e31310108c5683f), C(126593715c2de429),
-     C(48ca8f35a3f54b90), C(b9322b632f4f8b0), C(926bb169b7337693), C(f686911)},
+    {C(168884267f3817e9), C(5b376e050f637645), C(1c18314abd34497a), C(aefae77)},
+    {C(82e78596ee3e56a7), C(25697d9c87f30d98), C(7600a8342834924d), C(f686911)},
     {C(aa2d6cf22e3cc252), C(9b4dec4f5e179f16), C(76fb0fba1d99a99a),
-     C(9a62af3dbba140da), C(27857ea044e9dfc1), C(33abce9da2272647),
-     C(b22a7993aaf32556), C(9a62af3dbba140da), C(27857ea044e9dfc1),
-     C(33abce9da2272647), C(b22a7993aaf32556), C(bf8f88f8019bedf0),
-     C(ed2d7f01fb273905), C(6b45f15901b481cd), C(f88ebb413ba6a8d5),
      C(3deadf12)},
     {C(7bf5ffd7f69385c7), C(fc077b1d8bc82879), C(9c04e36f9ed83a24),
-     C(82065c62e6582188), C(8ef787fd356f5e43), C(2922e53e36e17dfa),
-     C(9805f223d385010b), C(82065c62e6582188), C(8ef787fd356f5e43),
-     C(2922e53e36e17dfa), C(9805f223d385010b), C(692154f3491b787d),
-     C(e7e64700e414fbf), C(757d4d4ab65069a0), C(cd029446a8e348e2), C(ccf02a4e)},
+     C(ccf02a4e)},
     {C(e89c8ff9f9c6e34b), C(f54c0f669a49f6c4), C(fc3e46f5d846adef),
-     C(22f2aa3df2221cc), C(f66fea90f5d62174), C(b75defaeaa1dd2a7),
-     C(9b994cd9a7214fd5), C(22f2aa3df2221cc), C(f66fea90f5d62174),
-     C(b75defaeaa1dd2a7), C(9b994cd9a7214fd5), C(fac675a31804b773),
-     C(98bcb3b820c50fc6), C(e14af64d28cf0885), C(27466fbd2b360eb5),
      C(176c1722)},
-    {C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c),
-     C(229b79ab69ae97d), C(a87aabc2ec26e582), C(be2b053721eb26d2),
-     C(10febd7f0c3d6fcb), C(229b79ab69ae97d), C(a87aabc2ec26e582),
-     C(be2b053721eb26d2), C(10febd7f0c3d6fcb), C(9cc5b9b2f6e3bf7b),
-     C(655d8495fe624a86), C(6381a9f3d1f2bd7e), C(79ebabbfc25c83e2), C(26f82ad)},
+    {C(a18fbcdccd11e1f4), C(8248216751dfd65e), C(40c089f208d89d7c), C(26f82ad)},
     {C(2d54f40cc4088b17), C(59d15633b0cd1399), C(a8cc04bb1bffd15b),
-     C(d332cdb073d8dc46), C(272c56466868cb46), C(7e7fcbe35ca6c3f3),
-     C(ee8f51e5a70399d4), C(d332cdb073d8dc46), C(272c56466868cb46),
-     C(7e7fcbe35ca6c3f3), C(ee8f51e5a70399d4), C(16737a9c7581fe7b),
-     C(ed04bf52f4b75dcb), C(9707ffb36bd30c1a), C(1390f236fdc0de3e),
      C(b5244f42)},
     {C(69276946cb4e87c7), C(62bdbe6183be6fa9), C(3ba9773dac442a1a),
-     C(702e2afc7f5a1825), C(8c49b11ea8151fdc), C(caf3fef61f5a86fa),
-     C(ef0b2ee8649d7272), C(702e2afc7f5a1825), C(8c49b11ea8151fdc),
-     C(caf3fef61f5a86fa), C(ef0b2ee8649d7272), C(9e34a4e08d9441e1),
-     C(7bdc0cd64d5af533), C(a926b14d99e3d868), C(fca923a17788cce4),
      C(49a689e5)},
-    {C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28),
-     C(a590b202a7a5807b), C(968d2593f7ccb54e), C(9dd8d669e3e95dec),
-     C(ee0cc5dd58b6e93a), C(a590b202a7a5807b), C(968d2593f7ccb54e),
-     C(9dd8d669e3e95dec), C(ee0cc5dd58b6e93a), C(ac65d5a9466fb483),
-     C(221be538b2c9d806), C(5cbe9441784f9fd9), C(d4c7d5d6e3c122b8), C(59fcdd3)},
-    {C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf),
-     C(7432d63888e0c306), C(74bbceeed479cb71), C(6471586599575fdf),
-     C(6a859ad23365cba2), C(7432d63888e0c306), C(74bbceeed479cb71),
-     C(6471586599575fdf), C(6a859ad23365cba2), C(f9ceec84acd18dcc),
-     C(74a242ff1907437c), C(f70890194e1ee913), C(777dfcb4bb01f0ba),
-     C(4f4b04e9)},
+    {C(668174a3f443df1d), C(407299392da1ce86), C(c2a3f7d7f2c5be28), C(59fcdd3)},
+    {C(5e29be847bd5046), C(b561c7f19c8f80c3), C(5e5abd5021ccaeaf), C(4f4b04e9)},
     {C(cd0d79f2164da014), C(4c386bb5c5d6ca0c), C(8e771b03647c3b63),
-     C(69db23875cb0b715), C(ada8dd91504ae37f), C(46bf18dbf045ed6a),
-     C(e1b5f67b0645ab63), C(69db23875cb0b715), C(ada8dd91504ae37f),
-     C(46bf18dbf045ed6a), C(e1b5f67b0645ab63), C(877be8f5dcddff4),
-     C(6d471b5f9ca2e2d1), C(802c86d6f495b9bb), C(a1f9b9b22b3be704),
      C(8b00f891)},
     {C(e0e6fc0b1628af1d), C(29be5fb4c27a2949), C(1c3f781a604d3630),
-     C(c4af7faf883033aa), C(9bd296c4e9453cac), C(ca45426c1f7e33f9),
-     C(a6bbdcf7074d40c5), C(c4af7faf883033aa), C(9bd296c4e9453cac),
-     C(ca45426c1f7e33f9), C(a6bbdcf7074d40c5), C(e13a005d7142733b),
-     C(c02b7925c5eeefaf), C(d39119a60441e2d5), C(3c24c710df8f4d43),
      C(16e114f3)},
     {C(2058927664adfd93), C(6e8f968c7963baa5), C(af3dced6fff7c394),
-     C(42e34cf3d53c7876), C(9cddbb26424dc5e), C(64f6340a6d8eddad),
-     C(2196e488eb2a3a4b), C(42e34cf3d53c7876), C(9cddbb26424dc5e),
-     C(64f6340a6d8eddad), C(2196e488eb2a3a4b), C(c9e9da25911a16fd),
-     C(e21b4683f3e196a8), C(cb80bf1a4c6fdbb4), C(53792e9b3c3e67f8),
      C(d6b6dadc)},
     {C(dc107285fd8e1af7), C(a8641a0609321f3f), C(db06e89ffdc54466),
-     C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1), C(93605ec471aa37db),
-     C(a2a73f8a85a8e397), C(bcc7a81ed5432429), C(b6d7bdc6ad2e81f1),
-     C(93605ec471aa37db), C(a2a73f8a85a8e397), C(10a012b8ca7ac24b),
-     C(aac5fd63351595cf), C(5bb4c648a226dea0), C(9d11ecb2b5c05c5f),
      C(897e20ac)},
-    {C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a),
-     C(6226a32e25099848), C(ea895661ecf53004), C(4d7e0158db2228b9),
-     C(e5a7d82922f69842), C(6226a32e25099848), C(ea895661ecf53004),
-     C(4d7e0158db2228b9), C(e5a7d82922f69842), C(2cea7713b69840ca),
-     C(18de7b9ae938375b), C(f127cca08f3cc665), C(b1c22d727665ad2), C(f996e05d)},
+    {C(fbba1afe2e3280f1), C(755a5f392f07fce), C(9e44a9a15402809a), C(f996e05d)},
     {C(bfa10785ddc1011b), C(b6e1c4d2f670f7de), C(517d95604e4fcc1f),
-     C(ca6552a0dfb82c73), C(b024cdf09e34ba07), C(66cd8c5a95d7393b),
-     C(e3939acf790d4a74), C(ca6552a0dfb82c73), C(b024cdf09e34ba07),
-     C(66cd8c5a95d7393b), C(e3939acf790d4a74), C(97827541a1ef051e),
-     C(ac2fce47ebe6500c), C(b3f06d3bddf3bd6a), C(1d74afb25e1ce5fe),
      C(c4306af6)},
-    {C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363),
-     C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c), C(401d6c2f151b5a62),
-     C(e988460224108944), C(f14ef7f47d8a57a3), C(80d1f86f2e061d7c),
-     C(401d6c2f151b5a62), C(e988460224108944), C(7804d4135f68cd19),
-     C(5487b4b39e69fe8e), C(8cc5999015358a27), C(8f3729b61c2d5601),
-     C(6dcad433)},
-    {C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545),
-     C(c8389799445480db), C(5389f5df8aacd50d), C(d136581f22fab5f),
-     C(c2f31f85991da417), C(c8389799445480db), C(5389f5df8aacd50d),
-     C(d136581f22fab5f), C(c2f31f85991da417), C(aefbf9ff84035a43),
-     C(8accbaf44adadd7c), C(e57f3657344b67f5), C(21490e5e8abdec51),
-     C(3c07374d)},
+    {C(534cc35f0ee1eb4e), C(b703820f1f3b3dce), C(884aa164cf22363), C(6dcad433)},
+    {C(7ca6e3933995dac), C(fd118c77daa8188), C(3aceb7b5e7da6545), C(3c07374d)},
     {C(f0d6044f6efd7598), C(e044d6ba4369856e), C(91968e4f8c8a1a4c),
-     C(70bd1968996bffc2), C(4c613de5d8ab32ac), C(fe1f4f97206f79d8),
-     C(ac0434f2c4e213a9), C(70bd1968996bffc2), C(4c613de5d8ab32ac),
-     C(fe1f4f97206f79d8), C(ac0434f2c4e213a9), C(7490e9d82cfe22ca),
-     C(5fbbf7f987454238), C(c39e0dc8368ce949), C(22201d3894676c71),
      C(f0f4602c)},
     {C(3d69e52049879d61), C(76610636ea9f74fe), C(e9bf5602f89310c0),
-     C(8eeb177a86053c11), C(e390122c345f34a2), C(1e30e47afbaaf8d6),
-     C(7b892f68e5f91732), C(8eeb177a86053c11), C(e390122c345f34a2),
-     C(1e30e47afbaaf8d6), C(7b892f68e5f91732), C(b87922525fa44158),
-     C(f440a1ee1a1a766b), C(ee8efad279d08c5c), C(421f910c5b60216e),
      C(3e1ea071)},
-    {C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de),
-     C(27233b28b5b11e9b), C(c7dfe8988a942700), C(570ed11c4abad984),
-     C(4b4c04632f48311a), C(27233b28b5b11e9b), C(c7dfe8988a942700),
-     C(570ed11c4abad984), C(4b4c04632f48311a), C(12f33235442cbf9),
-     C(a35315ca0b5b8cdb), C(d8abde62ead5506b), C(fc0fcf8478ad5266),
-     C(67580f0c)},
+    {C(79da242a16acae31), C(183c5f438e29d40), C(6d351710ae92f3de), C(67580f0c)},
     {C(461c82656a74fb57), C(d84b491b275aa0f7), C(8f262cb29a6eb8b2),
-     C(49fa3070bc7b06d0), C(f12ed446bd0c0539), C(6d43ac5d1dd4b240),
-     C(7609524fe90bec93), C(49fa3070bc7b06d0), C(f12ed446bd0c0539),
-     C(6d43ac5d1dd4b240), C(7609524fe90bec93), C(391c2b2e076ec241),
-     C(f5e62deda7839f7b), C(3c7b3186a10d870f), C(77ef4f2cba4f1005),
      C(4e109454)},
-    {C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3),
-     C(57466046cf6896ed), C(8ac37e0e8b25b0c6), C(3e6074b52ad3cf18),
-     C(aa491ce7b45db297), C(57466046cf6896ed), C(8ac37e0e8b25b0c6),
-     C(3e6074b52ad3cf18), C(aa491ce7b45db297), C(f7a9227c5e5e22c3),
-     C(3d92e0841e29ce28), C(2d30da5b2859e59d), C(ff37fa1c9cbfafc2),
-     C(88a474a7)},
-    {C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4),
-     C(c2dcc9758c910171), C(cb5cddaeff4ddb40), C(5d7cc5869baefef1),
-     C(9644c5853af9cfeb), C(c2dcc9758c910171), C(cb5cddaeff4ddb40),
-     C(5d7cc5869baefef1), C(9644c5853af9cfeb), C(255c968184694ee1),
-     C(4e4d726eda360927), C(7d27dd5b6d100377), C(9a300e2020ddea2c), C(5b5bedd)},
+    {C(53c1a66d0b13003), C(731f060e6fe797fc), C(daa56811791371e3), C(88a474a7)},
+    {C(d3a2efec0f047e9), C(1cabce58853e58ea), C(7a17b2eae3256be4), C(5b5bedd)},
     {C(43c64d7484f7f9b2), C(5da002b64aafaeb7), C(b576c1e45800a716),
-     C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9), C(d9e946f5ae1ca95),
-     C(24ca06e67f0b1833), C(3ee84d3d5b4ca00b), C(5cbc6d701894c3f9),
-     C(d9e946f5ae1ca95), C(24ca06e67f0b1833), C(3413d46b4152650e),
-     C(cbdfdbc2ab516f9c), C(2aad8acb739e0c6c), C(2bfc950d9f9fa977),
      C(1aaddfa7)},
     {C(a7dec6ad81cf7fa1), C(180c1ab708683063), C(95e0fd7008d67cff),
-     C(6b11c5073687208), C(7e0a57de0d453f3), C(e48c267d4f646867),
-     C(2168e9136375f9cb), C(6b11c5073687208), C(7e0a57de0d453f3),
-     C(e48c267d4f646867), C(2168e9136375f9cb), C(64da194aeeea7fdf),
-     C(a3b9f01fa5885678), C(c316f8ee2eb2bd17), C(a7e4d80f83e4427f),
      C(5be07fd8)},
-    {C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e),
-     C(7da9e81d89fda7ad), C(274157cabe71440d), C(2c22d9a480b331f7),
-     C(e835c8ac746472d5), C(7da9e81d89fda7ad), C(274157cabe71440d),
-     C(2c22d9a480b331f7), C(e835c8ac746472d5), C(2038ce817a201ae4),
-     C(46f3289dfe1c5e40), C(435578a42d4b7c56), C(f96d9f409fcf561), C(cbca8606)},
+    {C(5408a1df99d4aff), C(b9565e588740f6bd), C(abf241813b08006e), C(cbca8606)},
     {C(a8b27a6bcaeeed4b), C(aec1eeded6a87e39), C(9daf246d6fed8326),
-     C(d45a938b79f54e8f), C(366b219d6d133e48), C(5b14be3c25c49405),
-     C(fdd791d48811a572), C(d45a938b79f54e8f), C(366b219d6d133e48),
-     C(5b14be3c25c49405), C(fdd791d48811a572), C(3de67b8d9e95d335),
-     C(903c01307cfbeed5), C(af7d65f32274f1d1), C(4dba141b5fc03c42),
      C(bde64d01)},
     {C(9a952a8246fdc269), C(d0dcfcac74ef278c), C(250f7139836f0f1f),
-     C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5), C(7ad09538a3da27f5),
-     C(2b5c18f934aa5303), C(c83d3c5f4e5f0320), C(694e7adeb2bf32e5),
-     C(7ad09538a3da27f5), C(2b5c18f934aa5303), C(c4dad7703d34326e),
-     C(825569e2bcdc6a25), C(b83d267709ca900d), C(44ed05151f5d74e6),
      C(ee90cf33)},
     {C(c930841d1d88684f), C(5eb66eb18b7f9672), C(e455d413008a2546),
-     C(bc271bc0df14d647), C(b071100a9ff2edbb), C(2b1a4c1cc31a119a),
-     C(b5d7caa1bd946cef), C(bc271bc0df14d647), C(b071100a9ff2edbb),
-     C(2b1a4c1cc31a119a), C(b5d7caa1bd946cef), C(e02623ae10f4aadd),
-     C(d79f600389cd06fd), C(1e8da7965303e62b), C(86f50e10eeab0925),
      C(4305c3ce)},
-    {C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5),
-     C(336c1b59a1fc19f6), C(c173acaecc471305), C(db1267d24f3f3f36),
-     C(e9a5ee98627a6e78), C(336c1b59a1fc19f6), C(c173acaecc471305),
-     C(db1267d24f3f3f36), C(e9a5ee98627a6e78), C(718f334204305ae5),
-     C(e3b53c148f98d22c), C(a184012df848926), C(6e96386127d51183), C(4b3a1d76)},
-    {C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456),
-     C(84064a6dcf916340), C(fbf55a26790e0ebb), C(2e7f84151c31a5c2),
-     C(9f7f6d76b950f9bf), C(84064a6dcf916340), C(fbf55a26790e0ebb),
-     C(2e7f84151c31a5c2), C(9f7f6d76b950f9bf), C(125e094fbee2b146),
-     C(5706aa72b2eef7c2), C(1c4a2daa905ee66e), C(83d48029b5451694),
-     C(a8bb6d80)},
-    {C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5),
-     C(e38e526cd3324364), C(85f2b63a5b5e840a), C(485d7cef5aaadd87),
-     C(d2b837a462f6db6d), C(e38e526cd3324364), C(85f2b63a5b5e840a),
-     C(485d7cef5aaadd87), C(d2b837a462f6db6d), C(3e41cef031520d9a),
-     C(82df73902d7f67e), C(3ba6fd54c15257cb), C(22f91f079be42d40), C(1f9fa607)},
+    {C(94dc6971e3cf071a), C(994c7003b73b2b34), C(ea16e85978694e5), C(4b3a1d76)},
+    {C(7fc98006e25cac9), C(77fee0484cda86a7), C(376ec3d447060456), C(a8bb6d80)},
+    {C(bd781c4454103f6), C(612197322f49c931), C(b9cf17fd7e5462d5), C(1f9fa607)},
     {C(da60e6b14479f9df), C(3bdccf69ece16792), C(18ebf45c4fecfdc9),
-     C(16818ee9d38c6664), C(5519fa9a1e35a329), C(cbd0001e4b08ed8),
-     C(41a965e37a0c731b), C(16818ee9d38c6664), C(5519fa9a1e35a329),
-     C(cbd0001e4b08ed8), C(41a965e37a0c731b), C(66e7b5dcca1ca28f),
-     C(963b2d993614347d), C(9b6fc6f41d411106), C(aaaecaccf7848c0c),
      C(8d0e4ed2)},
-    {C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09),
-     C(30278016830ddd43), C(f046646d9012e074), C(c62a5804f6e7c9da),
-     C(98d51f5830e2bc1e), C(30278016830ddd43), C(f046646d9012e074),
-     C(c62a5804f6e7c9da), C(98d51f5830e2bc1e), C(7b2cbe5d37e3f29e),
-     C(7b8c3ed50bda4aa0), C(3ea60cc24639e038), C(f7706de9fb0b5801),
-     C(1bf31347)},
+    {C(4ca56a348b6c4d3), C(60618537c3872514), C(2fbb9f0e65871b09), C(1bf31347)},
     {C(ebd22d4b70946401), C(6863602bf7139017), C(c0b1ac4e11b00666),
-     C(7d2782b82bd494b6), C(97159ba1c26b304b), C(42b3b0fd431b2ac2),
-     C(faa81f82691c830c), C(7d2782b82bd494b6), C(97159ba1c26b304b),
-     C(42b3b0fd431b2ac2), C(faa81f82691c830c), C(7cc6449234c7e185),
-     C(aeaa6fa643ca86a5), C(1412db1c0f2e0133), C(4df2fe3e4072934f),
      C(1ae3fc5b)},
-    {C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364),
-     C(58c8aba7475e2d95), C(3e2f291698c9427a), C(e8710d19c9de9e41),
-     C(65dda22eb04cf953), C(58c8aba7475e2d95), C(3e2f291698c9427a),
-     C(e8710d19c9de9e41), C(65dda22eb04cf953), C(d7729c48c250cffa),
-     C(ef76162b2ddfba4b), C(52371e17f4d51f6d), C(ddd002112ff0c833),
-     C(459c3930)},
+    {C(3cc4693d6cbcb0c), C(501689ea1c70ffa), C(10a4353e9c89e364), C(459c3930)},
     {C(38908e43f7ba5ef0), C(1ab035d4e7781e76), C(41d133e8c0a68ff7),
-     C(d1090893afaab8bc), C(96c4fe6922772807), C(4522426c2b4205eb),
-     C(efad99a1262e7e0d), C(d1090893afaab8bc), C(96c4fe6922772807),
-     C(4522426c2b4205eb), C(efad99a1262e7e0d), C(c7696029abdb465e),
-     C(4e18eaf03d517651), C(d006bced54c86ac8), C(4330326d1021860c),
      C(e00c4184)},
-    {C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8),
-     C(fc947167f69c0da5), C(ae79cfdb91b6f6c1), C(7b251d04c26cbda3),
-     C(128a33a79060d25e), C(fc947167f69c0da5), C(ae79cfdb91b6f6c1),
-     C(7b251d04c26cbda3), C(128a33a79060d25e), C(1eca842dbfe018dd),
-     C(50a4cd2ee0ba9c63), C(c2f5c97d8399682f), C(3f929fc7cbe8ecbb),
-     C(ffc7a781)},
+    {C(34983ccc6aa40205), C(21802cad34e72bc4), C(1943e8fb3c17bb8), C(ffc7a781)},
     {C(86215c45dcac9905), C(ea546afe851cae4b), C(d85b6457e489e374),
-     C(b7609c8e70386d66), C(36e6ccc278d1636d), C(2f873307c08e6a1c),
-     C(10f252a758505289), C(b7609c8e70386d66), C(36e6ccc278d1636d),
-     C(2f873307c08e6a1c), C(10f252a758505289), C(c8977646e81ab4b6),
-     C(8017b745cd80213b), C(960687db359bea0), C(ef4a470660799488), C(6a125480)},
+     C(6a125480)},
     {C(420fc255c38db175), C(d503cd0f3c1208d1), C(d4684e74c825a0bc),
-     C(4c10537443152f3d), C(720451d3c895e25d), C(aff60c4d11f513fd),
-     C(881e8d6d2d5fb953), C(4c10537443152f3d), C(720451d3c895e25d),
-     C(aff60c4d11f513fd), C(881e8d6d2d5fb953), C(9dec034a043f1f55),
-     C(e27a0c22e7bfb39d), C(2220b959128324), C(53240272152dbd8b), C(88a1512b)},
+     C(88a1512b)},
     {C(1d7a31f5bc8fe2f9), C(4763991092dcf836), C(ed695f55b97416f4),
-     C(f265edb0c1c411d7), C(30e1e9ec5262b7e6), C(c2c3ba061ce7957a),
-     C(d975f93b89a16409), C(f265edb0c1c411d7), C(30e1e9ec5262b7e6),
-     C(c2c3ba061ce7957a), C(d975f93b89a16409), C(e9d703123f43450a),
-     C(41383fedfed67c82), C(6e9f43ecbbbd6004), C(c7ccd23a24e77b8), C(549bbbe5)},
+     C(549bbbe5)},
     {C(94129a84c376a26e), C(c245e859dc231933), C(1b8f74fecf917453),
-     C(e9369d2e9007e74b), C(b1375915d1136052), C(926c2021fe1d2351),
-     C(1d943addaaa2e7e6), C(e9369d2e9007e74b), C(b1375915d1136052),
-     C(926c2021fe1d2351), C(1d943addaaa2e7e6), C(f5f515869c246738),
-     C(7e309cd0e1c0f2a0), C(153c3c36cf523e3b), C(4931c66872ea6758),
      C(c133d38c)},
-    {C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb),
-     C(301d7a61c4b3dbca), C(861336c3f0552d61), C(12c6db947471300f),
-     C(a679ef0ed761deb9), C(301d7a61c4b3dbca), C(861336c3f0552d61),
-     C(12c6db947471300f), C(a679ef0ed761deb9), C(5f713b720efcd147),
-     C(37ac330a333aa6b), C(3309dc9ec1616eef), C(52301d7a908026b5), C(fcace348)},
+    {C(1d3a9809dab05c8d), C(adddeb4f71c93e8), C(ef342eb36631edb), C(fcace348)},
     {C(90fa3ccbd60848da), C(dfa6e0595b569e11), C(e585d067a1f5135d),
-     C(6cef866ec295abea), C(c486c0d9214beb2d), C(d6e490944d5fe100),
-     C(59df3175d72c9f38), C(6cef866ec295abea), C(c486c0d9214beb2d),
-     C(d6e490944d5fe100), C(59df3175d72c9f38), C(3f23aeb4c04d1443),
-     C(9bf0515cd8d24770), C(958554f60ccaade2), C(5182863c90132fe8),
      C(ed7b6f9a)},
     {C(2dbb4fc71b554514), C(9650e04b86be0f82), C(60f2304fba9274d3),
-     C(fcfb9443e997cab), C(f13310d96dec2772), C(709cad2045251af2),
-     C(afd0d30cc6376dad), C(fcfb9443e997cab), C(f13310d96dec2772),
-     C(709cad2045251af2), C(afd0d30cc6376dad), C(59d4bed30d550d0d),
-     C(58006d4e22d8aad1), C(eee12d2362d1f13b), C(35cf1d7faaf1d228),
      C(6d907dda)},
     {C(b98bf4274d18374a), C(1b669fd4c7f9a19a), C(b1f5972b88ba2b7a),
-     C(73119c99e6d508be), C(5d4036a187735385), C(8fa66e192fd83831),
-     C(2abf64b6b592ed57), C(73119c99e6d508be), C(5d4036a187735385),
-     C(8fa66e192fd83831), C(2abf64b6b592ed57), C(d4501f95dd84b08c),
-     C(bf1552439c8bea02), C(4f56fe753ba7e0ba), C(4ca8d35cc058cfcd),
      C(7a4d48d5)},
     {C(d6781d0b5e18eb68), C(b992913cae09b533), C(58f6021caaee3a40),
-     C(aafcb77497b5a20b), C(411819e5e79b77a3), C(bd779579c51c77ce),
-     C(58d11f5dcf5d075d), C(aafcb77497b5a20b), C(411819e5e79b77a3),
-     C(bd779579c51c77ce), C(58d11f5dcf5d075d), C(9eae76cde1cb4233),
-     C(32fe25a9bf657970), C(1c0c807948edb06a), C(b8f29a3dfaee254d),
      C(e686f3db)},
-    {C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42),
-     C(3f44f873be4812ec), C(427662c1dbfaa7b2), C(a207ff9638fb6558),
-     C(a738d919e45f550f), C(3f44f873be4812ec), C(427662c1dbfaa7b2),
-     C(a207ff9638fb6558), C(a738d919e45f550f), C(cb186ea05717e7d6),
-     C(1ca7d68a5871fdc1), C(5d4c119ea8ef3750), C(72b6a10fa2ff9406), C(cce7c55)},
-    {C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8),
-     C(d396a297799c24a1), C(8fee992e3069bad5), C(2e3a01b0697ccf57),
-     C(ee9c7390bd901cfa), C(d396a297799c24a1), C(8fee992e3069bad5),
-     C(2e3a01b0697ccf57), C(ee9c7390bd901cfa), C(56f2d9da0af28af2),
-     C(3fdd37b2fe8437cb), C(3d13eeeb60d6aec0), C(2432ae62e800a5ce), C(f58b96b)},
+    {C(226651cf18f4884c), C(595052a874f0f51c), C(c9b75162b23bab42), C(cce7c55)},
+    {C(a734fb047d3162d6), C(e523170d240ba3a5), C(125a6972809730e8), C(f58b96b)},
     {C(c6df6364a24f75a3), C(c294e2c84c4f5df8), C(a88df65c6a89313b),
-     C(895fe8443183da74), C(c7f2f6f895a67334), C(a0d6b6a506691d31),
-     C(24f51712b459a9f0), C(895fe8443183da74), C(c7f2f6f895a67334),
-     C(a0d6b6a506691d31), C(24f51712b459a9f0), C(173a699481b9e088),
-     C(1dee9b77bcbf45d3), C(32b98a646a8667d0), C(3adcd4ee28f42a0e),
      C(1bbf6f60)},
-    {C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625),
-     C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e), C(c63282b20ad86db2),
-     C(aec97fa07916bfd6), C(a3d5d1137d30c4bd), C(1e7d706a49bdfb9e),
-     C(c63282b20ad86db2), C(aec97fa07916bfd6), C(7c9ba3e52d44f73e),
-     C(af62fd245811185d), C(8a9d2dacd8737652), C(bd2cce277d5fbec0),
-     C(ce5e0cc2)},
+    {C(d8d1364c1fbcd10), C(2d7cc7f54832deaa), C(4e22c876a7c57625), C(ce5e0cc2)},
     {C(aae06f9146db885f), C(3598736441e280d9), C(fba339b117083e55),
-     C(b22bf08d9f8aecf7), C(c182730de337b922), C(2b9adc87a0450a46),
-     C(192c29a9cfc00aad), C(b22bf08d9f8aecf7), C(c182730de337b922),
-     C(2b9adc87a0450a46), C(192c29a9cfc00aad), C(9fd733f1d84a59d9),
-     C(d86bd5c9839ace15), C(af20b57303172876), C(9f63cb7161b5364c),
      C(584cfd6f)},
     {C(8955ef07631e3bcc), C(7d70965ea3926f83), C(39aed4134f8b2db6),
-     C(882efc2561715a9c), C(ef8132a18a540221), C(b20a3c87a8c257c1),
-     C(f541b8628fad6c23), C(882efc2561715a9c), C(ef8132a18a540221),
-     C(b20a3c87a8c257c1), C(f541b8628fad6c23), C(9552aed57a6e0467),
-     C(4d9fdd56867611a7), C(c330279bf23b9eab), C(44dbbaea2fcb8eba),
      C(8f9bbc33)},
     {C(ad611c609cfbe412), C(d3c00b18bf253877), C(90b2172e1f3d0bfd),
-     C(371a98b2cb084883), C(33a2886ee9f00663), C(be9568818ed6e6bd),
-     C(f244a0fa2673469a), C(371a98b2cb084883), C(33a2886ee9f00663),
-     C(be9568818ed6e6bd), C(f244a0fa2673469a), C(b447050bd3e559e9),
-     C(d3b695dae7a13383), C(ded0bb65be471188), C(ca3c7a2b78922cae),
      C(d7640d95)},
-    {C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf),
-     C(89f3aab99afbd636), C(f420e004f8148b9a), C(6818073faa797c7c),
-     C(dd3b4e21cbbf42ca), C(89f3aab99afbd636), C(f420e004f8148b9a),
-     C(6818073faa797c7c), C(dd3b4e21cbbf42ca), C(6a2b7db261164844),
-     C(cbead63d1895852a), C(93d37e1eae05e2f9), C(5d06db2703fbc3ae), C(3d12a2b)},
+    {C(d5339adc295d5d69), C(b633cc1dcb8b586a), C(ee84184cf5b1aeaf), C(3d12a2b)},
     {C(40d0aeff521375a8), C(77ba1ad7ecebd506), C(547c6f1a7d9df427),
-     C(21c2be098327f49b), C(7e035065ac7bbef5), C(6d7348e63023fb35),
-     C(9d427dc1b67c3830), C(21c2be098327f49b), C(7e035065ac7bbef5),
-     C(6d7348e63023fb35), C(9d427dc1b67c3830), C(4e3d018a43858341),
-     C(cf924bb44d6b43c5), C(4618b6a26e3446ae), C(54d3013fac3ed469),
      C(aaeafed0)},
     {C(8b2d54ae1a3df769), C(11e7adaee3216679), C(3483781efc563e03),
-     C(9d097dd3152ab107), C(51e21d24126e8563), C(cba56cac884a1354),
-     C(39abb1b595f0a977), C(9d097dd3152ab107), C(51e21d24126e8563),
-     C(cba56cac884a1354), C(39abb1b595f0a977), C(81e6dd1c1109848f),
-     C(1644b209826d7b15), C(6ac67e4e4b4812f0), C(b3a9f5622c935bf7),
      C(95b9b814)},
     {C(99c175819b4eae28), C(932e8ff9f7a40043), C(ec78dcab07ca9f7c),
-     C(c1a78b82ba815b74), C(458cbdfc82eb322a), C(17f4a192376ed8d7),
-     C(6f9e92968bc8ccef), C(c1a78b82ba815b74), C(458cbdfc82eb322a),
-     C(17f4a192376ed8d7), C(6f9e92968bc8ccef), C(93e098c333b39905),
-     C(d59b1cace44b7fdc), C(f7a64ed78c64c7c5), C(7c6eca5dd87ec1ce),
      C(45fbe66e)},
     {C(2a418335779b82fc), C(af0295987849a76b), C(c12bc5ff0213f46e),
-     C(5aeead8d6cb25bb9), C(739315f7743ec3ff), C(9ab48d27111d2dcc),
-     C(5b87bd35a975929b), C(5aeead8d6cb25bb9), C(739315f7743ec3ff),
-     C(9ab48d27111d2dcc), C(5b87bd35a975929b), C(c3dd8d6d95a46bb3),
-     C(7bf9093215a4f483), C(cb557d6ed84285bd), C(daf58422f261fdb5),
      C(b4baa7a8)},
-    {C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c),
-     C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c), C(e9bf61d2dab0f774),
-     C(f4f35bf5870a049c), C(ba1ffba29f0367aa), C(a20bec1dd15a8b6c),
-     C(e9bf61d2dab0f774), C(f4f35bf5870a049c), C(26787efa5b92385),
-     C(3d9533590ce30b59), C(a4da3e40530a01d4), C(6395deaefb70067c),
-     C(83e962fe)},
-    {C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234),
-     C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6), C(2cf65e4958ad5bda),
-     C(cfbf9b03245989a7), C(d8ad7ec84a9c9aa2), C(e256cffed11f69e6),
-     C(2cf65e4958ad5bda), C(cfbf9b03245989a7), C(9fa51e6686cf4444),
-     C(9425c117a34609d5), C(b25f7e2c6f30e96), C(ea5477c3f2b5afd1), C(aac3531c)},
+    {C(3b1fc6a3d279e67d), C(70ea1e49c226396), C(25505adcf104697c), C(83e962fe)},
+    {C(d97eacdf10f1c3c9), C(b54f4654043a36e0), C(b128f6eb09d1234), C(aac3531c)},
     {C(293a5c1c4e203cd4), C(6b3329f1c130cefe), C(f2e32f8ec76aac91),
-     C(361e0a62c8187bff), C(6089971bb84d7133), C(93df7741588dd50b),
-     C(c2a9b6abcd1d80b1), C(361e0a62c8187bff), C(6089971bb84d7133),
-     C(93df7741588dd50b), C(c2a9b6abcd1d80b1), C(4d2f86869d79bc59),
-     C(85cd24d8aa570ff), C(b0dcf6ef0e94bbb5), C(2037c69aa7a78421), C(2b1db7cc)},
+     C(2b1db7cc)},
     {C(4290e018ffaedde7), C(a14948545418eb5e), C(72d851b202284636),
-     C(4ec02f3d2f2b23f2), C(ab3580708aa7c339), C(cdce066fbab3f65),
-     C(d8ed3ecf3c7647b9), C(4ec02f3d2f2b23f2), C(ab3580708aa7c339),
-     C(cdce066fbab3f65), C(d8ed3ecf3c7647b9), C(6d2204b3e31f344a),
-     C(61a4d87f80ee61d7), C(446c43dbed4b728f), C(73130ac94f58747e),
      C(cf00cd31)},
     {C(f919a59cbde8bf2f), C(a56d04203b2dc5a5), C(38b06753ac871e48),
-     C(c2c9fc637dbdfcfa), C(292ab8306d149d75), C(7f436b874b9ffc07),
-     C(a5b56b0129218b80), C(c2c9fc637dbdfcfa), C(292ab8306d149d75),
-     C(7f436b874b9ffc07), C(a5b56b0129218b80), C(9188f7bdc47ec050),
-     C(cfe9345d03a15ade), C(40b520fb2750c49e), C(c2e83d343968af2e),
      C(7d3c43b8)},
     {C(1d70a3f5521d7fa4), C(fb97b3fdc5891965), C(299d49bbbe3535af),
-     C(e1a8286a7d67946e), C(52bd956f047b298), C(cbd74332dd4204ac),
-     C(12b5be7752721976), C(e1a8286a7d67946e), C(52bd956f047b298),
-     C(cbd74332dd4204ac), C(12b5be7752721976), C(278426e27f6204b6),
-     C(932ca7a7cd610181), C(41647321f0a5914d), C(48f4aa61a0ae80db),
      C(cbd5fac6)},
     {C(6af98d7b656d0d7c), C(d2e99ae96d6b5c0c), C(f63bd1603ef80627),
-     C(bde51033ac0413f8), C(bc0272f691aec629), C(6204332651bebc44),
-     C(1cbf00de026ea9bd), C(bde51033ac0413f8), C(bc0272f691aec629),
-     C(6204332651bebc44), C(1cbf00de026ea9bd), C(b9c7ed6a75f3ff1e),
-     C(7e310b76a5808e4f), C(acbbd1aad5531885), C(fc245f2473adeb9c),
      C(76d0fec4)},
-    {C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9),
-     C(6c71064996cbec8b), C(352c535edeefcb89), C(ac7f0aba15cd5ecd),
-     C(3aba1ca8353e5c60), C(6c71064996cbec8b), C(352c535edeefcb89),
-     C(ac7f0aba15cd5ecd), C(3aba1ca8353e5c60), C(5c30a288a80ce646),
-     C(c2940488b6617674), C(925f8cc66b370575), C(aa65d1283b9bb0ef),
-     C(405e3402)},
+    {C(395b7a8adb96ab75), C(582df7165b20f4a), C(e52bd30e9ff657f9), C(405e3402)},
     {C(3822dd82c7df012f), C(b9029b40bd9f122b), C(fd25b988468266c4),
-     C(43e47bd5bab1e0ef), C(4a71f363421f282f), C(880b2f32a2b4e289),
-     C(1299d4eda9d3eadf), C(43e47bd5bab1e0ef), C(4a71f363421f282f),
-     C(880b2f32a2b4e289), C(1299d4eda9d3eadf), C(d713a40226f5564),
-     C(4d8d34fedc769406), C(a85001b29cd9cac3), C(cae92352a41fd2b0),
      C(c732c481)},
     {C(79f7efe4a80b951a), C(dd3a3fddfc6c9c41), C(ab4c812f9e27aa40),
-     C(832954ec9d0de333), C(94c390aa9bcb6b8a), C(f3b32afdc1f04f82),
-     C(d229c3b72e4b9a74), C(832954ec9d0de333), C(94c390aa9bcb6b8a),
-     C(f3b32afdc1f04f82), C(d229c3b72e4b9a74), C(1d11860d7ed624a6),
-     C(cadee20b3441b984), C(75307079bf306f7b), C(87902aa3b9753ba4),
      C(a8d123c9)},
-    {C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59),
-     C(4960111789727567), C(149b8a37c7125ab6), C(78c7a13ab9749382),
-     C(1c61131260ca151a), C(4960111789727567), C(149b8a37c7125ab6),
-     C(78c7a13ab9749382), C(1c61131260ca151a), C(1e93276b35c309a0),
-     C(2618f56230acde58), C(af61130a18e4febf), C(7145deb18e89befe),
-     C(1e80ad7d)},
+    {C(ae6e59f5f055921a), C(e9d9b7bf68e82), C(5ce4e4a5b269cc59), C(1e80ad7d)},
     {C(8959dbbf07387d36), C(b4658afce48ea35d), C(8f3f82437d8cb8d6),
-     C(6566d74954986ba5), C(99d5235cc82519a7), C(257a23805c2d825),
-     C(ad75ccb968e93403), C(6566d74954986ba5), C(99d5235cc82519a7),
-     C(257a23805c2d825), C(ad75ccb968e93403), C(b45bd4cf78e11f7f),
-     C(80c5536bdc487983), C(a4fd76ecbf018c8a), C(3b9dac78a7a70d43),
      C(52aeb863)},
     {C(4739613234278a49), C(99ea5bcd340bf663), C(258640912e712b12),
-     C(c8a2827404991402), C(7ee5e78550f02675), C(2ec53952db5ac662),
-     C(1526405a9df6794b), C(c8a2827404991402), C(7ee5e78550f02675),
-     C(2ec53952db5ac662), C(1526405a9df6794b), C(eddc6271170c5e1f),
-     C(f5a85f986001d9d6), C(95427c677bf58d58), C(53ed666dfa85cb29),
      C(ef7c0c18)},
     {C(420e6c926bc54841), C(96dbbf6f4e7c75cd), C(d8d40fa70c3c67bb),
-     C(3edbc10e4bfee91b), C(f0d681304c28ef68), C(77ea602029aaaf9c),
-     C(90f070bd24c8483c), C(3edbc10e4bfee91b), C(f0d681304c28ef68),
-     C(77ea602029aaaf9c), C(90f070bd24c8483c), C(28bc8e41e08ceb86),
-     C(1eb56e48a65691ef), C(9fea5301c9202f0e), C(3fcb65091aa9f135),
      C(b6ad4b68)},
     {C(c8601bab561bc1b7), C(72b26272a0ff869a), C(56fdfc986d6bc3c4),
-     C(83707730cad725d4), C(c9ca88c3a779674a), C(e1c696fbbd9aa933),
-     C(723f3baab1c17a45), C(83707730cad725d4), C(c9ca88c3a779674a),
-     C(e1c696fbbd9aa933), C(723f3baab1c17a45), C(f82abc7a1d851682),
-     C(30683836818e857d), C(78bfa3e89a5ab23f), C(6928234482b31817),
      C(c1e46b17)},
-    {C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6),
-     C(1ef8e98e1ea57269), C(5971116272f45a8b), C(187ad68ce95d8eac),
-     C(e94e93ee4e8ecaa6), C(1ef8e98e1ea57269), C(5971116272f45a8b),
-     C(187ad68ce95d8eac), C(e94e93ee4e8ecaa6), C(a0ff2a58611838b5),
-     C(b01e03849bfbae6f), C(d081e202e28ea3ab), C(51836bcee762bf13),
-     C(57b8df25)},
+    {C(b2d294931a0e20eb), C(284ffd9a0815bc38), C(1f8a103aac9bbe6), C(57b8df25)},
     {C(7966f53c37b6c6d7), C(8e6abcfb3aa2b88f), C(7f2e5e0724e5f345),
-     C(3eeb60c3f5f8143d), C(a25aec05c422a24f), C(b026b03ad3cca4db),
-     C(e6e030028cc02a02), C(3eeb60c3f5f8143d), C(a25aec05c422a24f),
-     C(b026b03ad3cca4db), C(e6e030028cc02a02), C(16fe679338b34bfc),
-     C(c1be385b5c8a9de4), C(65af5df6567530eb), C(ed3b303df4dc6335),
      C(e9fa36d6)},
     {C(be9bb0abd03b7368), C(13bca93a3031be55), C(e864f4f52b55b472),
-     C(36a8d13a2cbb0939), C(254ac73907413230), C(73520d1522315a70),
-     C(8c9fdb5cf1e1a507), C(36a8d13a2cbb0939), C(254ac73907413230),
-     C(73520d1522315a70), C(8c9fdb5cf1e1a507), C(b3640570b926886),
-     C(fba2344ee87f7bab), C(de57341ab448df05), C(385612ee094fa977),
      C(8f8daefc)},
-    {C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c),
-     C(5b2b7ca856fad1c3), C(8093022d682e375d), C(ea5d163ba7ea231f),
-     C(d6181d012c0de641), C(5b2b7ca856fad1c3), C(8093022d682e375d),
-     C(ea5d163ba7ea231f), C(d6181d012c0de641), C(e7d40d0ab8b08159),
-     C(2e82320f51b3a67e), C(27c2e356ea0b63a3), C(58842d01a2b1d077), C(6e1bb7e)},
+    {C(a08d128c5f1649be), C(a8166c3dbbe19aad), C(cb9f914f829ec62c), C(6e1bb7e)},
     {C(7c386f0ffe0465ac), C(530419c9d843dbf3), C(7450e3a4f72b8d8c),
-     C(48b218e3b721810d), C(d3757ac8609bc7fc), C(111ba02a88aefc8),
-     C(e86343137d3bfc2a), C(48b218e3b721810d), C(d3757ac8609bc7fc),
-     C(111ba02a88aefc8), C(e86343137d3bfc2a), C(44ad26b51661b507),
-     C(db1268670274f51e), C(62a5e75beae875f3), C(e266e7a44c5f28c6),
      C(fd0076f0)},
-    {C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe),
-     C(15747d8c505ffd00), C(438a15f391312cd6), C(e46ca62c26d821f5),
-     C(be78d74c9f79cb44), C(15747d8c505ffd00), C(438a15f391312cd6),
-     C(e46ca62c26d821f5), C(be78d74c9f79cb44), C(a8aa19f3aa59f09a),
-     C(effb3cddab2c9267), C(d78e41ad97cb16a5), C(ace6821513527d32),
-     C(899b17b6)},
+    {C(bb362094e7ef4f8), C(ff3c2a48966f9725), C(55152803acd4a7fe), C(899b17b6)},
     {C(cd80dea24321eea4), C(52b4fdc8130c2b15), C(f3ea100b154bfb82),
-     C(d9ccef1d4be46988), C(5ede0c4e383a5e66), C(da69683716a54d1e),
-     C(bfc3fdf02d242d24), C(d9ccef1d4be46988), C(5ede0c4e383a5e66),
-     C(da69683716a54d1e), C(bfc3fdf02d242d24), C(20ed30274651b3f5),
-     C(4c659824169e86c6), C(637226dae5b52a0e), C(7e050dbd1c71dc7f),
      C(e3e84e31)},
     {C(d599a04125372c3a), C(313136c56a56f363), C(1e993c3677625832),
-     C(2870a99c76a587a4), C(99f74cc0b182dda4), C(8a5e895b2f0ca7b6),
-     C(3d78882d5e0bb1dc), C(2870a99c76a587a4), C(99f74cc0b182dda4),
-     C(8a5e895b2f0ca7b6), C(3d78882d5e0bb1dc), C(f466123732a3e25e),
-     C(aca5e59716a40e50), C(261d2e7383d0e686), C(ce9362d6a42c15a7),
      C(eef79b6b)},
-    {C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534),
-     C(a3335c417687cf3a), C(92ff114ac45cda75), C(c3b8a627384f13b5),
-     C(c4f25de33de8b3f7), C(a3335c417687cf3a), C(92ff114ac45cda75),
-     C(c3b8a627384f13b5), C(c4f25de33de8b3f7), C(eacbf520578c5964),
-     C(4cb19c5ab24f3215), C(e7d8a6f67f0c6e7), C(325c2413eb770ada), C(868e3315)},
-    {C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485),
-     C(c7cd48f7abf1fe59), C(ce600656ace6f53a), C(8a94a4381b108b34),
-     C(f9d1276c64bf59fb), C(c7cd48f7abf1fe59), C(ce600656ace6f53a),
-     C(8a94a4381b108b34), C(f9d1276c64bf59fb), C(219ce70ff5a112a5),
-     C(e6026c576e2d28d7), C(b8e467f25015e3a6), C(950cb904f37af710),
-     C(4639a426)},
+    {C(dbbf541e9dfda0a), C(1479fceb6db4f844), C(31ab576b59062534), C(868e3315)},
+    {C(c2ee3288be4fe2bf), C(c65d2f5ddf32b92), C(af6ecdf121ba5485), C(4639a426)},
     {C(d86603ced1ed4730), C(f9de718aaada7709), C(db8b9755194c6535),
-     C(d803e1eead47604c), C(ad00f7611970a71b), C(bc50036b16ce71f5),
-     C(afba96210a2ca7d6), C(d803e1eead47604c), C(ad00f7611970a71b),
-     C(bc50036b16ce71f5), C(afba96210a2ca7d6), C(28f7a7be1d6765f0),
-     C(97bd888b93938c68), C(6ad41d1b407ded49), C(b9bfec098dc543e4),
      C(f3213646)},
     {C(915263c671b28809), C(a815378e7ad762fd), C(abec6dc9b669f559),
-     C(d17c928c5342477f), C(745130b795254ad5), C(8c5db926fe88f8ba),
-     C(742a95c953e6d974), C(d17c928c5342477f), C(745130b795254ad5),
-     C(8c5db926fe88f8ba), C(742a95c953e6d974), C(279db8057b5d3e96),
-     C(98168411565b4ec4), C(50a72c54fa1125fa), C(27766a635db73638),
      C(17f148e9)},
-    {C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad),
-     C(6531c1fe32bcb417), C(8c970d8df8cdbeb4), C(917ba5fc67e72b40),
-     C(4b65e4e263e0a426), C(6531c1fe32bcb417), C(8c970d8df8cdbeb4),
-     C(917ba5fc67e72b40), C(4b65e4e263e0a426), C(e0de33ce88a8b3a9),
-     C(f8ef98a437e16b08), C(a5162c0c7c5f7b62), C(dbdac43361b2b881),
-     C(bfd94880)},
+    {C(2b67cdd38c307a5e), C(cb1d45bb5c9fe1c), C(800baf2a02ec18ad), C(bfd94880)},
     {C(2d107419073b9cd0), C(a96db0740cef8f54), C(ec41ee91b3ecdc1b),
-     C(ffe319654c8e7ebc), C(6a67b8f13ead5a72), C(6dd10a34f80d532f),
-     C(6e9cfaece9fbca4), C(ffe319654c8e7ebc), C(6a67b8f13ead5a72),
-     C(6dd10a34f80d532f), C(6e9cfaece9fbca4), C(b4468eb6a30aa7e9),
-     C(e87995bee483222a), C(d036c2c90c609391), C(853306e82fa32247),
      C(bb1fa7f3)},
-    {C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8),
-     C(8950cfcf4bdf622c), C(8847dca82efeef2f), C(646b75b026708169),
-     C(21cab4b1687bd8b), C(8950cfcf4bdf622c), C(8847dca82efeef2f),
-     C(646b75b026708169), C(21cab4b1687bd8b), C(243b489a9eae6231),
-     C(5f3e634c4b779876), C(ff8abd1548eaf646), C(c7962f5f0151914b), C(88816b1)},
+    {C(f3e9487ec0e26dfc), C(1ab1f63224e837fa), C(119983bb5a8125d8), C(88816b1)},
     {C(1160987c8fe86f7d), C(879e6db1481eb91b), C(d7dcb802bfe6885d),
-     C(14453b5cc3d82396), C(4ef700c33ed278bc), C(1639c72ffc00d12e),
-     C(fb140ee6155f700d), C(14453b5cc3d82396), C(4ef700c33ed278bc),
-     C(1639c72ffc00d12e), C(fb140ee6155f700d), C(2e6b5c96a6620862),
-     C(a1f136998cbe19c), C(74e058a3b6c5a712), C(93dcf6bd33928b17), C(5c2faeb3)},
+     C(5c2faeb3)},
     {C(eab8112c560b967b), C(97f550b58e89dbae), C(846ed506d304051f),
-     C(276aa37744b5a028), C(8c10800ee90ea573), C(e6e57d2b33a1e0b7),
-     C(91f83563cd3b9dda), C(276aa37744b5a028), C(8c10800ee90ea573),
-     C(e6e57d2b33a1e0b7), C(91f83563cd3b9dda), C(afbb4739570738a1),
-     C(440ba98da5d8f69), C(fde4e9b0eda20350), C(e67dfa5a2138fa1), C(51b5fc6f)},
+     C(51b5fc6f)},
     {C(1addcf0386d35351), C(b5f436561f8f1484), C(85d38e22181c9bb1),
-     C(ff5c03f003c1fefe), C(e1098670afe7ff6), C(ea445030cf86de19),
-     C(f155c68b5c2967f8), C(ff5c03f003c1fefe), C(e1098670afe7ff6),
-     C(ea445030cf86de19), C(f155c68b5c2967f8), C(95d31b145dbb2e9e),
-     C(914fe1ca3deb3265), C(6066020b1358ccc1), C(c74bb7e2dee15036),
      C(33d94752)},
     {C(d445ba84bf803e09), C(1216c2497038f804), C(2293216ea2237207),
-     C(e2164451c651adfb), C(b2534e65477f9823), C(4d70691a69671e34),
-     C(15be4963dbde8143), C(e2164451c651adfb), C(b2534e65477f9823),
-     C(4d70691a69671e34), C(15be4963dbde8143), C(762e75c406c5e9a3),
-     C(7b7579f7e0356841), C(480533eb066dfce5), C(90ae14ea6bfeb4ae),
      C(b0c92948)},
     {C(37235a096a8be435), C(d9b73130493589c2), C(3b1024f59378d3be),
-     C(ad159f542d81f04e), C(49626a97a946096), C(d8d3998bf09fd304),
-     C(d127a411eae69459), C(ad159f542d81f04e), C(49626a97a946096),
-     C(d8d3998bf09fd304), C(d127a411eae69459), C(8f3253c4eb785a7b),
-     C(4049062f37e62397), C(b9fa04d3b670e5c1), C(1211a7967ac9350f),
      C(c7171590)},
     {C(763ad6ea2fe1c99d), C(cf7af5368ac1e26b), C(4d5e451b3bb8d3d4),
-     C(3712eb913d04e2f2), C(2f9500d319c84d89), C(4ac6eb21a8cf06f9),
-     C(7d1917afcde42744), C(3712eb913d04e2f2), C(2f9500d319c84d89),
-     C(4ac6eb21a8cf06f9), C(7d1917afcde42744), C(6b58604b5dd10903),
-     C(c4288dfbc1e319fc), C(230f75ca96817c6e), C(8894cba3b763756c),
      C(240a67fb)},
     {C(ea627fc84cd1b857), C(85e372494520071f), C(69ec61800845780b),
-     C(a3c1c5ca1b0367), C(eb6933997272bb3d), C(76a72cb62692a655),
-     C(140bb5531edf756e), C(a3c1c5ca1b0367), C(eb6933997272bb3d),
-     C(76a72cb62692a655), C(140bb5531edf756e), C(8d0d8067d1c925f4),
-     C(7b3fa56d8d77a10c), C(2bd00287b0946d88), C(f08c8e4bd65b8970),
      C(e1843cd5)},
     {C(1f2ffd79f2cdc0c8), C(726a1bc31b337aaa), C(678b7f275ef96434),
-     C(5aa82bfaa99d3978), C(c18f96cade5ce18d), C(38404491f9e34c03),
-     C(891fb8926ba0418c), C(5aa82bfaa99d3978), C(c18f96cade5ce18d),
-     C(38404491f9e34c03), C(891fb8926ba0418c), C(e5f69a6398114c15),
-     C(7b8ded3623bc6b1d), C(2f3e5c5da5ff70e8), C(1ab142addea6a9ec),
      C(fda1452b)},
     {C(39a9e146ec4b3210), C(f63f75802a78b1ac), C(e2e22539c94741c3),
-     C(8b305d532e61226e), C(caeae80da2ea2e), C(88a6289a76ac684e),
-     C(8ce5b5f9df1cbd85), C(8b305d532e61226e), C(caeae80da2ea2e),
-     C(88a6289a76ac684e), C(8ce5b5f9df1cbd85), C(8ae1fc4798e00d57),
-     C(e7164b8fb364fc46), C(6a978c9bd3a66943), C(ef10d5ae4dd08dc), C(a2cad330)},
+     C(a2cad330)},
     {C(74cba303e2dd9d6d), C(692699b83289fad1), C(dfb9aa7874678480),
-     C(751390a8a5c41bdc), C(6ee5fbf87605d34), C(6ca73f610f3a8f7c),
-     C(e898b3c996570ad), C(751390a8a5c41bdc), C(6ee5fbf87605d34),
-     C(6ca73f610f3a8f7c), C(e898b3c996570ad), C(98168a5858fc7110),
-     C(6f987fa27aa0daa2), C(f25e3e180d4b36a3), C(d0b03495aeb1be8a),
      C(53467e16)},
     {C(4cbc2b73a43071e0), C(56c5db4c4ca4e0b7), C(1b275a162f46bd3d),
-     C(b87a326e413604bf), C(d8f9a5fa214b03ab), C(8a8bb8265771cf88),
-     C(a655319054f6e70f), C(b87a326e413604bf), C(d8f9a5fa214b03ab),
-     C(8a8bb8265771cf88), C(a655319054f6e70f), C(b499cb8e65a9af44),
-     C(bee7fafcc8307491), C(5d2e55fa9b27cda2), C(63b120f5fb2d6ee5),
      C(da14a8d0)},
     {C(875638b9715d2221), C(d9ba0615c0c58740), C(616d4be2dfe825aa),
-     C(5df25f13ea7bc284), C(165edfaafd2598fb), C(af7215c5c718c696),
-     C(e9f2f9ca655e769), C(5df25f13ea7bc284), C(165edfaafd2598fb),
-     C(af7215c5c718c696), C(e9f2f9ca655e769), C(e459cfcb565d3d2d),
-     C(41d032631be2418a), C(c505db05fd946f60), C(54990394a714f5de),
      C(67333551)},
     {C(fb686b2782994a8d), C(edee60693756bb48), C(e6bc3cae0ded2ef5),
-     C(58eb4d03b2c3ddf5), C(6d2542995f9189f1), C(c0beec58a5f5fea2),
-     C(ed67436f42e2a78b), C(58eb4d03b2c3ddf5), C(6d2542995f9189f1),
-     C(c0beec58a5f5fea2), C(ed67436f42e2a78b), C(dfec763cdb2b5193),
-     C(724a8d5345bd2d6), C(94d4fd1b81457c23), C(28e87c50cdede453), C(a0ebd66e)},
+     C(a0ebd66e)},
     {C(ab21d81a911e6723), C(4c31b07354852f59), C(835da384c9384744),
-     C(7f759dddc6e8549a), C(616dd0ca022c8735), C(94717ad4bc15ceb3),
-     C(f66c7be808ab36e), C(7f759dddc6e8549a), C(616dd0ca022c8735),
-     C(94717ad4bc15ceb3), C(f66c7be808ab36e), C(af8286b550b2f4b7),
-     C(745bd217d20a9f40), C(c73bfb9c5430f015), C(55e65922666e3fc2),
      C(4b769593)},
     {C(33d013cc0cd46ecf), C(3de726423aea122c), C(116af51117fe21a9),
-     C(f271ba474edc562d), C(e6596e67f9dd3ebd), C(c0a288edf808f383),
-     C(b3def70681c6babc), C(f271ba474edc562d), C(e6596e67f9dd3ebd),
-     C(c0a288edf808f383), C(b3def70681c6babc), C(7da7864e9989b095),
-     C(bf2f8718693cd8a1), C(264a9144166da776), C(61ad90676870beb6),
      C(6aa75624)},
-    {C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f),
-     C(45744afcf131dbee), C(97222392c2559350), C(498a19b280c6d6ed),
-     C(83ac2c36acdb8d49), C(45744afcf131dbee), C(97222392c2559350),
-     C(498a19b280c6d6ed), C(83ac2c36acdb8d49), C(7a69645c294daa62),
-     C(abe9d2be8275b3d2), C(39542019de371085), C(7f4efac8488cd6ad),
-     C(602a3f96)},
-    {C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee),
-     C(b6dd09ba7851c7af), C(570de4e1bb13b133), C(c4e784eb97211642),
-     C(8285a7fcdcc7c58d), C(b6dd09ba7851c7af), C(570de4e1bb13b133),
-     C(c4e784eb97211642), C(8285a7fcdcc7c58d), C(d421f47990da899b),
-     C(8aed409c997eaa13), C(7a045929c2e29ccf), C(b373682a6202c86b),
-     C(cd183c4d)},
+    {C(8ca92c7cd39fae5d), C(317e620e1bf20f1), C(4f0b33bf2194b97f), C(602a3f96)},
+    {C(fdde3b03f018f43e), C(38f932946c78660), C(c84084ce946851ee), C(cd183c4d)},
     {C(9c8502050e9c9458), C(d6d2a1a69964beb9), C(1675766f480229b5),
-     C(216e1d6c86cb524c), C(d01cf6fd4f4065c0), C(fffa4ec5b482ea0f),
-     C(a0e20ee6a5404ac1), C(216e1d6c86cb524c), C(d01cf6fd4f4065c0),
-     C(fffa4ec5b482ea0f), C(a0e20ee6a5404ac1), C(c1b037e4eebaf85e),
-     C(634e3d7c3ebf89eb), C(bcda972358c67d1), C(fd1352181e5b8578), C(960a4d07)},
+     C(960a4d07)},
     {C(348176ca2fa2fdd2), C(3a89c514cc360c2d), C(9f90b8afb318d6d0),
-     C(bceee07c11a9ac30), C(2e2d47dff8e77eb7), C(11a394cd7b6d614a),
-     C(1d7c41d54e15cb4a), C(bceee07c11a9ac30), C(2e2d47dff8e77eb7),
-     C(11a394cd7b6d614a), C(1d7c41d54e15cb4a), C(15baa5ae7312b0fc),
-     C(f398f596cc984635), C(8ab8fdf87a6788e8), C(b2b5c1234ab47e2), C(9ae998c4)},
+     C(9ae998c4)},
     {C(4a3d3dfbbaea130b), C(4e221c920f61ed01), C(553fd6cd1304531f),
-     C(bd2b31b5608143fe), C(ab717a10f2554853), C(293857f04d194d22),
-     C(d51be8fa86f254f0), C(bd2b31b5608143fe), C(ab717a10f2554853),
-     C(293857f04d194d22), C(d51be8fa86f254f0), C(1eee39e07686907e),
-     C(639039fe0e8d3052), C(d6ec1470cef97ff), C(370c82b860034f0f), C(74e2179d)},
+     C(74e2179d)},
     {C(b371f768cdf4edb9), C(bdef2ace6d2de0f0), C(e05b4100f7f1baec),
-     C(b9e0d415b4ebd534), C(c97c2a27efaa33d7), C(591cdb35f84ef9da),
-     C(a57d02d0e8e3756c), C(b9e0d415b4ebd534), C(c97c2a27efaa33d7),
-     C(591cdb35f84ef9da), C(a57d02d0e8e3756c), C(23f55f12d7c5c87b),
-     C(4c7ca0fe23221101), C(dbc3020480334564), C(d985992f32c236b1),
      C(ee9bae25)},
-    {C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df),
-     C(2228d6725e31b8ab), C(9b98f7e4d0142e70), C(b6a8c2115b8e0fe7),
-     C(b591e2f5ab9b94b1), C(2228d6725e31b8ab), C(9b98f7e4d0142e70),
-     C(b6a8c2115b8e0fe7), C(b591e2f5ab9b94b1), C(6c1feaa8065318e0),
-     C(4e7e2ca21c2e81fb), C(e9fe5d8ce7993c45), C(ee411fa2f12cf8df),
-     C(b66edf10)},
+    {C(7a1d2e96934f61f), C(eb1760ae6af7d961), C(887eb0da063005df), C(b66edf10)},
     {C(8be53d466d4728f2), C(86a5ac8e0d416640), C(984aa464cdb5c8bb),
-     C(87049e68f5d38e59), C(7d8ce44ec6bd7751), C(cc28d08ab414839c),
-     C(6c8f0bd34fe843e3), C(87049e68f5d38e59), C(7d8ce44ec6bd7751),
-     C(cc28d08ab414839c), C(6c8f0bd34fe843e3), C(b8496dcdc01f3e47),
-     C(2f03125c282ac26), C(82a8797ba3f5ef07), C(7c977a4d10bf52b8), C(d6209737)},
-    {C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a),
-     C(98d0dbf796480187), C(fbcb5f3e1bef5742), C(5af2a0463bf6e921),
-     C(ad9555bf0120b3a3), C(98d0dbf796480187), C(fbcb5f3e1bef5742),
-     C(5af2a0463bf6e921), C(ad9555bf0120b3a3), C(283e39b3dc99f447),
-     C(bedaa1a4a0250c28), C(9d50546624ff9a57), C(4abaf523d1c090f6), C(b994a88)},
-    {C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40),
-     C(57c5208e8f021a77), C(f7653fbb69cd9276), C(a484410af21d75cb),
-     C(f19b6844b3d627e8), C(57c5208e8f021a77), C(f7653fbb69cd9276),
-     C(a484410af21d75cb), C(f19b6844b3d627e8), C(f37400fc3ffd9514),
-     C(36ae0d821734edfd), C(5f37820af1f1f306), C(be637d40e6a5ad0), C(a05d43c0)},
+     C(d6209737)},
+    {C(829677eb03abf042), C(43cad004b6bc2c0), C(f2f224756803971a), C(b994a88)},
+    {C(754435bae3496fc), C(5707fc006f094dcf), C(8951c86ab19d8e40), C(a05d43c0)},
     {C(fda9877ea8e3805f), C(31e868b6ffd521b7), C(b08c90681fb6a0fd),
-     C(68110a7f83f5d3ff), C(6d77e045901b85a8), C(84ef681113036d8b),
-     C(3b9f8e3928f56160), C(68110a7f83f5d3ff), C(6d77e045901b85a8),
-     C(84ef681113036d8b), C(3b9f8e3928f56160), C(fc8b7f56c130835),
-     C(a11f3e800638e841), C(d9572267f5cf28c1), C(7897c8149803f2aa),
      C(c79f73a8)},
     {C(2e36f523ca8f5eb5), C(8b22932f89b27513), C(331cd6ecbfadc1bb),
-     C(d1bfe4df12b04cbf), C(f58c17243fd63842), C(3a453cdba80a60af),
-     C(5737b2ca7470ea95), C(d1bfe4df12b04cbf), C(f58c17243fd63842),
-     C(3a453cdba80a60af), C(5737b2ca7470ea95), C(54d44a3f4477030c),
-     C(8168e02d4869aa7f), C(77f383a17778559d), C(95e1737d77a268fc),
      C(a490aff5)},
     {C(21a378ef76828208), C(a5c13037fa841da2), C(506d22a53fbe9812),
-     C(61c9c95d91017da5), C(16f7c83ba68f5279), C(9c0619b0808d05f7),
-     C(83c117ce4e6b70a3), C(61c9c95d91017da5), C(16f7c83ba68f5279),
-     C(9c0619b0808d05f7), C(83c117ce4e6b70a3), C(cfb4c8af7fd01413),
-     C(fdef04e602e72296), C(ed6124d337889b1), C(4919c86707b830da), C(dfad65b4)},
-    {C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9),
-     C(58634004c7b2d19a), C(24bb5f51ed3b9073), C(46409de018033d00),
-     C(4a9805eed5ac802e), C(58634004c7b2d19a), C(24bb5f51ed3b9073),
-     C(46409de018033d00), C(4a9805eed5ac802e), C(e18de8db306baf82),
-     C(46bbf75f1fa025ff), C(5faf2fb09be09487), C(3fbc62bd4e558fb3), C(1d07dfb)},
+     C(dfad65b4)},
+    {C(ccdd5600054b16ca), C(f78846e84204cb7b), C(1f9faec82c24eac9), C(1d07dfb)},
     {C(7854468f4e0cabd0), C(3a3f6b4f098d0692), C(ae2423ec7799d30d),
-     C(29c3529eb165eeba), C(443de3703b657c35), C(66acbce31ae1bc8d),
-     C(1acc99effe1d547e), C(29c3529eb165eeba), C(443de3703b657c35),
-     C(66acbce31ae1bc8d), C(1acc99effe1d547e), C(cf07f8a57906573d),
-     C(31bafb0bbb9a86e7), C(40c69492702a9346), C(7df61fdaa0b858af),
      C(416df9a0)},
     {C(7f88db5346d8f997), C(88eac9aacc653798), C(68a4d0295f8eefa1),
-     C(ae59ca86f4c3323d), C(25906c09906d5c4c), C(8dd2aa0c0a6584ae),
-     C(232a7d96b38f40e9), C(ae59ca86f4c3323d), C(25906c09906d5c4c),
-     C(8dd2aa0c0a6584ae), C(232a7d96b38f40e9), C(8986ee00a2ed0042),
-     C(c49ae7e428c8a7d1), C(b7dd8280713ac9c2), C(e018720aed1ebc28),
      C(1f8fb9cc)},
     {C(bb3fb5fb01d60fcf), C(1b7cc0847a215eb6), C(1246c994437990a1),
-     C(d4edc954c07cd8f3), C(224f47e7c00a30ab), C(d5ad7ad7f41ef0c6),
-     C(59e089281d869fd7), C(d4edc954c07cd8f3), C(224f47e7c00a30ab),
-     C(d5ad7ad7f41ef0c6), C(59e089281d869fd7), C(f29340d07a14b6f1),
-     C(c87c5ef76d9c4ef3), C(463118794193a9a), C(2922dcb0540f0dbc), C(7abf48e3)},
+     C(7abf48e3)},
     {C(2e783e1761acd84d), C(39158042bac975a0), C(1cd21c5a8071188d),
-     C(b1b7ec44f9302176), C(5cb476450dc0c297), C(dc5ef652521ef6a2),
-     C(3cc79a9e334e1f84), C(b1b7ec44f9302176), C(5cb476450dc0c297),
-     C(dc5ef652521ef6a2), C(3cc79a9e334e1f84), C(769e2a283dbcc651),
-     C(9f24b105c8511d3f), C(c31c15575de2f27e), C(ecfecf32c3ae2d66),
      C(dea4e3dd)},
     {C(392058251cf22acc), C(944ec4475ead4620), C(b330a10b5cb94166),
-     C(54bc9bee7cbe1767), C(485820bdbe442431), C(54d6120ea2972e90),
-     C(f437a0341f29b72a), C(54bc9bee7cbe1767), C(485820bdbe442431),
-     C(54d6120ea2972e90), C(f437a0341f29b72a), C(8f30885c784d5704),
-     C(aa95376b16c7906a), C(e826928cfaf93dc3), C(20e8f54d1c16d7d8),
      C(c6064f22)},
-    {C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c),
-     C(80973ea532b0f310), C(a471829aa9c17dd9), C(c2ff3479394804ab),
-     C(6bf44f8606753636), C(80973ea532b0f310), C(a471829aa9c17dd9),
-     C(c2ff3479394804ab), C(6bf44f8606753636), C(5184d2973e6dd827),
-     C(121b96369a332d9a), C(5c25d3475ab69e50), C(26d2961d62884168),
-     C(743bed9c)},
+    {C(adf5c1e5d6419947), C(2a9747bc659d28aa), C(95c5b8cb1f5d62c), C(743bed9c)},
     {C(6bc1db2c2bee5aba), C(e63b0ed635307398), C(7b2eca111f30dbbc),
-     C(230d2b3e47f09830), C(ec8624a821c1caf4), C(ea6ec411cdbf1cb1),
-     C(5f38ae82af364e27), C(230d2b3e47f09830), C(ec8624a821c1caf4),
-     C(ea6ec411cdbf1cb1), C(5f38ae82af364e27), C(a519ef515ea7187c),
-     C(6bad5efa7ebae05f), C(748abacb11a74a63), C(a28eef963d1396eb),
      C(fce254d5)},
     {C(b00f898229efa508), C(83b7590ad7f6985c), C(2780e70a0592e41d),
-     C(7122413bdbc94035), C(e7f90fae33bf7763), C(4b6bd0fb30b12387),
-     C(557359c0c44f48ca), C(7122413bdbc94035), C(e7f90fae33bf7763),
-     C(4b6bd0fb30b12387), C(557359c0c44f48ca), C(d5656c3d6bc5f0d),
-     C(983ff8e5e784da99), C(628479671b445bf), C(e179a1e27ce68f5d), C(e47ec9d1)},
+     C(e47ec9d1)},
     {C(b56eb769ce0d9a8c), C(ce196117bfbcaf04), C(b26c3c3797d66165),
-     C(5ed12338f630ab76), C(fab19fcb319116d), C(167f5f42b521724b),
-     C(c4aa56c409568d74), C(5ed12338f630ab76), C(fab19fcb319116d),
-     C(167f5f42b521724b), C(c4aa56c409568d74), C(75fff4b42f8e9778),
-     C(94218f94710c1ea3), C(b7b05efb738b06a6), C(83fff2deabf9cd3), C(334a145c)},
+     C(334a145c)},
     {C(70c0637675b94150), C(259e1669305b0a15), C(46e1dd9fd387a58d),
-     C(fca4e5bc9292788e), C(cd509dc1facce41c), C(bbba575a59d82fe),
-     C(4e2e71c15b45d4d3), C(fca4e5bc9292788e), C(cd509dc1facce41c),
-     C(bbba575a59d82fe), C(4e2e71c15b45d4d3), C(5dc54582ead999c),
-     C(72612d1571963c6f), C(30318a9d2d3d1829), C(785dd00f4cc9c9a0),
      C(adec1e3c)},
     {C(74c0b8a6821faafe), C(abac39d7491370e7), C(faf0b2a48a4e6aed),
-     C(967e970df9673d2a), C(d465247cffa415c0), C(33a1df0ca1107722),
-     C(49fc2a10adce4a32), C(967e970df9673d2a), C(d465247cffa415c0),
-     C(33a1df0ca1107722), C(49fc2a10adce4a32), C(c5707e079a284308),
-     C(573028266635dda6), C(f786f5eee6127fa0), C(b30d79cebfb51266),
      C(f6a9fbf8)},
     {C(5fb5e48ac7b7fa4f), C(a96170f08f5acbc7), C(bbf5c63d4f52a1e5),
-     C(6cc09e60700563e9), C(d18f23221e964791), C(ffc23eeef7af26eb),
-     C(693a954a3622a315), C(815308a32a9b0daf), C(efb2ab27bf6fd0bd),
-     C(9f1ffc0986111118), C(f9a3aa1778ea3985), C(698fe54b2b93933b),
-     C(dacc2b28404d0f10), C(815308a32a9b0daf), C(efb2ab27bf6fd0bd),
      C(5398210c)},
 };
 
 void TestUnchanging(const uint64_t* expected, int offset, int len) {
-  const uint128 u = CityHash128(data + offset, len);
-  const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128);
   EXPECT_EQ(expected[0], CityHash64(data + offset, len));
-  EXPECT_EQ(expected[15], CityHash32(data + offset, len));
+  EXPECT_EQ(expected[3], CityHash32(data + offset, len));
   EXPECT_EQ(expected[1], CityHash64WithSeed(data + offset, len, kSeed0));
   EXPECT_EQ(expected[2],
             CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1));
-  EXPECT_EQ(expected[3], Uint128Low64(u));
-  EXPECT_EQ(expected[4], Uint128High64(u));
-  EXPECT_EQ(expected[5], Uint128Low64(v));
-  EXPECT_EQ(expected[6], Uint128High64(v));
-#ifdef __SSE4_2__
-  const uint128 y = CityHashCrc128(data + offset, len);
-  const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128);
-  uint64_t crc256_results[4];
-  CityHashCrc256(data + offset, len, crc256_results);
-  EXPECT_EQ(expected[7], Uint128Low64(y));
-  EXPECT_EQ(expected[8], Uint128High64(y));
-  EXPECT_EQ(expected[9], Uint128Low64(z));
-  EXPECT_EQ(expected[10], Uint128High64(z));
-  for (int i = 0; i < 4; i++) {
-    EXPECT_EQ(expected[11 + i], crc256_results[i]);
-  }
-#endif
 }
 
 TEST(CityHashTest, Unchanging) {
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc
index 4bf6409..4ab7a9f 100644
--- a/absl/hash/internal/hash.cc
+++ b/absl/hash/internal/hash.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 4543d67..9ab9890 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -221,7 +221,9 @@
 }
 // AbslHashValue() for hashing floating-point values
 template <typename H, typename Float>
-typename std::enable_if<std::is_floating_point<Float>::value, H>::type
+typename std::enable_if<std::is_same<Float, float>::value ||
+                            std::is_same<Float, double>::value,
+                        H>::type
 AbslHashValue(H hash_state, Float value) {
   return hash_internal::hash_bytes(std::move(hash_state),
                                    value == 0 ? 0 : value);
@@ -231,8 +233,9 @@
 // For example, in x86 sizeof(long double)==16 but it only really uses 80-bits
 // of it. This means we can't use hash_bytes on a long double and have to
 // convert it to something else first.
-template <typename H>
-H AbslHashValue(H hash_state, long double value) {
+template <typename H, typename LongDouble>
+typename std::enable_if<std::is_same<LongDouble, long double>::value, H>::type
+AbslHashValue(H hash_state, LongDouble value) {
   const int category = std::fpclassify(value);
   switch (category) {
     case FP_INFINITE:
@@ -264,7 +267,12 @@
 // AbslHashValue() for hashing pointers
 template <typename H, typename T>
 H AbslHashValue(H hash_state, T* ptr) {
-  return hash_internal::hash_bytes(std::move(hash_state), ptr);
+  auto v = reinterpret_cast<uintptr_t>(ptr);
+  // Due to alignment, pointers tend to have low bits as zero, and the next few
+  // bits follow a pattern since they are also multiples of some base value.
+  // Mixing the pointer twice helps prevent stuck low bits for certain alignment
+  // values.
+  return H::combine(std::move(hash_state), v, v);
 }
 
 // AbslHashValue() for hashing nullptr_t
@@ -303,13 +311,13 @@
 
 // AbslHashValue for hashing tuples
 template <typename H, typename... Ts>
-#if _MSC_VER
+#if defined(_MSC_VER)
 // This SFINAE gets MSVC confused under some conditions. Let's just disable it
 // for now.
 H
-#else
+#else  // _MSC_VER
 typename std::enable_if<absl::conjunction<is_hashable<Ts>...>::value, H>::type
-#endif
+#endif  // _MSC_VER
 AbslHashValue(H hash_state, const std::tuple<Ts...>& t) {
   return hash_internal::hash_tuple(std::move(hash_state), t,
                                    absl::make_index_sequence<sizeof...(Ts)>());
@@ -494,6 +502,15 @@
   }
   return H::combine(std::move(hash_state), v.index());
 }
+
+// -----------------------------------------------------------------------------
+// AbslHashValue for Other Types
+// -----------------------------------------------------------------------------
+
+// AbslHashValue for hashing std::bitset is not defined, for the same reason as
+// for vector<bool> (see std::vector above): It does not expose the raw bytes,
+// and a fallback to std::hash<> is most likely faster.
+
 // -----------------------------------------------------------------------------
 
 // hash_range_or_bytes()
@@ -518,51 +535,22 @@
   return hash_state;
 }
 
-// InvokeHashTag
-//
-// InvokeHash(H, const T&) invokes the appropriate hash implementation for a
-// hasher of type `H` and a value of type `T`. If `T` is not hashable, there
-// will be no matching overload of InvokeHash().
-// Note: Some platforms (eg MSVC) do not support the detect idiom on
-// std::hash. In those platforms the last fallback will be std::hash and
-// InvokeHash() will always have a valid overload even if std::hash<T> is not
-// valid.
-//
-// We try the following options in order:
-//   * If is_uniquely_represented, hash bytes directly.
-//   * ADL AbslHashValue(H, const T&) call.
-//   * std::hash<T>
-
-// In MSVC we can't probe std::hash or stdext::hash because it triggers a
-// static_assert instead of failing substitution.
-#if defined(_MSC_VER)
-#undef ABSL_HASH_INTERNAL_CAN_POISON_
-#else   // _MSC_VER
-#define ABSL_HASH_INTERNAL_CAN_POISON_ 1
-#endif  // _MSC_VER
-
 #if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \
-    ABSL_HASH_INTERNAL_CAN_POISON_
+    ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 #define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1
+#else
+#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
 #endif
 
-enum class InvokeHashTag {
-  kUniquelyRepresented,
-  kHashValue,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-  kLegacyHash,
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-  kStdHash,
-  kNone
-};
-
 // HashSelect
 //
 // Type trait to select the appropriate hash implementation to use.
-// HashSelect<T>::value is an instance of InvokeHashTag that indicates the best
-// available hashing mechanism.
-// See `Note` above about MSVC.
-template <typename T>
+// HashSelect::type<T> will give the proper hash implementation, to be invoked
+// as:
+//   HashSelect::type<T>::Invoke(state, value)
+// Also, HashSelect::type<T>::value is a boolean equal to `true` if there is a
+// valid `Invoke` function. Types that are not hashable will have a ::value of
+// `false`.
 struct HashSelect {
  private:
   struct State : HashStateBase<State> {
@@ -571,95 +559,75 @@
     using State::HashStateBase::combine_contiguous;
   };
 
-  // `Probe<V, Tag>::value` evaluates to `V<T>::value` if it is a valid
-  // expression, and `false` otherwise.
-  // `Probe<V, Tag>::tag` always evaluates to `Tag`.
-  template <template <typename> class V, InvokeHashTag Tag>
-  struct Probe {
+  struct UniquelyRepresentedProbe {
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value)
+        -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {
+      return hash_internal::hash_bytes(std::move(state), value);
+    }
+  };
+
+  struct HashValueProbe {
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+        std::is_same<H,
+                     decltype(AbslHashValue(std::move(state), value))>::value,
+        H> {
+      return AbslHashValue(std::move(state), value);
+    }
+  };
+
+  struct LegacyHashProbe {
+#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+        std::is_convertible<
+            decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),
+            size_t>::value,
+        H> {
+      return hash_internal::hash_bytes(
+          std::move(state),
+          ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
+    }
+#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+  };
+
+  struct StdHashProbe {
+    template <typename H, typename T>
+    static auto Invoke(H state, const T& value)
+        -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
+      return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
+    }
+  };
+
+  template <typename Hash, typename T>
+  struct Probe : Hash {
    private:
-    template <typename U, typename std::enable_if<V<U>::value, int>::type = 0>
+    template <typename H, typename = decltype(H::Invoke(
+                              std::declval<State>(), std::declval<const T&>()))>
     static std::true_type Test(int);
     template <typename U>
     static std::false_type Test(char);
 
    public:
-    static constexpr InvokeHashTag kTag = Tag;
-    static constexpr bool value = decltype(
-        Test<absl::remove_const_t<absl::remove_reference_t<T>>>(0))::value;
+    static constexpr bool value = decltype(Test<Hash>(0))::value;
   };
 
-  template <typename U>
-  using ProbeUniquelyRepresented = is_uniquely_represented<U>;
-
-  template <typename U>
-  using ProbeHashValue =
-      std::is_same<State, decltype(AbslHashValue(std::declval<State>(),
-                                                 std::declval<const U&>()))>;
-
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-  template <typename U>
-  using ProbeLegacyHash =
-      std::is_convertible<decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<
-                                   U>()(std::declval<const U&>())),
-                          size_t>;
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-
-  template <typename U>
-  using ProbeStdHash =
-#if ABSL_HASH_INTERNAL_CAN_POISON_
-      std::is_convertible<decltype(std::hash<U>()(std::declval<const U&>())),
-                          size_t>;
-#else   // ABSL_HASH_INTERNAL_CAN_POISON_
-      std::true_type;
-#endif  // ABSL_HASH_INTERNAL_CAN_POISON_
-
-  template <typename U>
-  using ProbeNone = std::true_type;
-
  public:
   // Probe each implementation in order.
   // disjunction provides short circuting wrt instantiation.
-  static constexpr InvokeHashTag value = absl::disjunction<
-      Probe<ProbeUniquelyRepresented, InvokeHashTag::kUniquelyRepresented>,
-      Probe<ProbeHashValue, InvokeHashTag::kHashValue>,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-      Probe<ProbeLegacyHash, InvokeHashTag::kLegacyHash>,
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-      Probe<ProbeStdHash, InvokeHashTag::kStdHash>,
-      Probe<ProbeNone, InvokeHashTag::kNone>>::kTag;
+  template <typename T>
+  using Apply = absl::disjunction<         //
+      Probe<UniquelyRepresentedProbe, T>,  //
+      Probe<HashValueProbe, T>,            //
+      Probe<LegacyHashProbe, T>,           //
+      Probe<StdHashProbe, T>,              //
+      std::false_type>;
 };
 
 template <typename T>
-struct is_hashable : std::integral_constant<bool, HashSelect<T>::value !=
-                                                      InvokeHashTag::kNone> {};
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kUniquelyRepresented,
-                  H>
-InvokeHash(H state, const T& value) {
-  return hash_internal::hash_bytes(std::move(state), value);
-}
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kHashValue, H>
-InvokeHash(H state, const T& value) {
-  return AbslHashValue(std::move(state), value);
-}
-
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kLegacyHash, H>
-InvokeHash(H state, const T& value) {
-  return hash_internal::hash_bytes(
-      std::move(state), ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
-}
-#endif  // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kStdHash, H>
-InvokeHash(H state, const T& value) {
-  return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
-}
+struct is_hashable
+    : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
 
 // CityHashState
 class CityHashState : public HashStateBase<CityHashState> {
@@ -869,7 +837,8 @@
 template <typename H>
 template <typename T, typename... Ts>
 H HashStateBase<H>::combine(H state, const T& value, const Ts&... values) {
-  return H::combine(hash_internal::InvokeHash(std::move(state), value),
+  return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke(
+                        std::move(state), value),
                     values...);
 }
 
diff --git a/absl/hash/internal/print_hash_of.cc b/absl/hash/internal/print_hash_of.cc
index b6df31c..c392125 100644
--- a/absl/hash/internal/print_hash_of.cc
+++ b/absl/hash/internal/print_hash_of.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h
index 03d795b..c4cc8d0 100644
--- a/absl/hash/internal/spy_hash_state.h
+++ b/absl/hash/internal/spy_hash_state.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -39,8 +39,7 @@
 template <typename T>
 class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {
  public:
-  SpyHashStateImpl()
-      : error_(std::make_shared<absl::optional<std::string>>()) {
+  SpyHashStateImpl() : error_(std::make_shared<absl::optional<std::string>>()) {
     static_assert(std::is_void<T>::value, "");
   }
 
@@ -170,7 +169,6 @@
   // AbslHashValue directly (because the hash state type does not match).
   static bool direct_absl_hash_value_error_;
 
-
   std::vector<std::string> hash_representation_;
   // This is a shared_ptr because we want all instances of the particular
   // SpyHashState run to share the field. This way we can set the error for
@@ -200,7 +198,7 @@
 template <
     typename T, typename U,
     // Only trigger for when (T != U),
-    absl::enable_if_t<!std::is_same<T, U>::value, int> = 0,
+    typename = absl::enable_if_t<!std::is_same<T, U>::value>,
     // This statement works in two ways:
     //  - First, it instantiates RunOnStartup and forces the initialization of
     //    `run`, which set the global variable.
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 89a312e..7c6366f 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
diff --git a/absl/memory/CMakeLists.txt b/absl/memory/CMakeLists.txt
index 5958f5c..0a81220 100644
--- a/absl/memory/CMakeLists.txt
+++ b/absl/memory/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,58 +14,45 @@
 # limitations under the License.
 #
 
-list(APPEND MEMORY_PUBLIC_HEADERS
-  "memory.h"
-)
-
-
-absl_header_library(
-  TARGET
-    absl_memory
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     memory
+  HDRS
+    "memory.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::meta
+  PUBLIC
 )
 
-#
-## TESTS
-#
-
-# test memory_test
-list(APPEND MEMORY_TEST_SRC
-  "memory_test.cc"
-  ${MEMORY_PUBLIC_HEADERS}
-)
-set(MEMORY_TEST_PUBLIC_LIBRARIES absl::base absl::memory)
-
-
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     memory_test
-  SOURCES
-    ${MEMORY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MEMORY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "memory_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::memory
+    absl::base
+    absl::core_headers
+    gmock_main
 )
 
-
-# test memory_exception_safety_test
-set(MEMORY_EXCEPTION_SAFETY_TEST_SRC "memory_exception_safety_test.cc")
-set(MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::memory
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     memory_exception_safety_test
-  SOURCES
-    ${MEMORY_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MEMORY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "memory_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::memory
+    absl::exception_safety_testing
+    gmock_main
 )
-
-
-
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 1eaec0f..5a4a1a1 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -47,19 +47,14 @@
 //   X* NewX(int, int);
 //   auto x = WrapUnique(NewX(1, 2));  // 'x' is std::unique_ptr<X>.
 //
-// The purpose of WrapUnique is to automatically deduce the pointer type. If you
-// wish to make the type explicit, for readability reasons or because you prefer
-// to use a base-class pointer rather than a derived one, just use
+// Do not call WrapUnique with an explicit type, as in
+// `WrapUnique<X>(NewX(1, 2))`.  The purpose of WrapUnique is to automatically
+// deduce the pointer type. If you wish to make the type explicit, just use
 // `std::unique_ptr` directly.
 //
-// Example:
-//   X* Factory(int, int);
-//   auto x = std::unique_ptr<X>(Factory(1, 2));
+//   auto x = std::unique_ptr<X>(NewX(1, 2));
 //                  - or -
-//   std::unique_ptr<X> x(Factory(1, 2));
-//
-// This has the added advantage of working whether Factory returns a raw
-// pointer or a `std::unique_ptr`.
+//   std::unique_ptr<X> x(NewX(1, 2));
 //
 // While `absl::WrapUnique` is useful for capturing the output of a raw
 // pointer factory, prefer 'absl::make_unique<T>(args...)' over
@@ -120,7 +115,7 @@
 //
 // For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic,
 // see Herb Sutter's explanation on
-// (Exception-Safe Function Calls)[http://herbsutter.com/gotw/_102/].
+// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/].
 // (In general, reviewers should treat `new T(a,b)` with scrutiny.)
 //
 // Example usage:
@@ -599,7 +594,7 @@
     return a.max_size();
   }
   static size_type max_size_impl(char, const Alloc&) {
-    return std::numeric_limits<size_type>::max() / sizeof(value_type);
+    return (std::numeric_limits<size_type>::max)() / sizeof(value_type);
   }
 
   template <typename A>
@@ -646,7 +641,7 @@
     : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
                                   std::false_type> {};
 
-#if ABSL_ALLOCATOR_NOTHROW
+#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
 template <typename T>
 struct allocator_is_nothrow<std::allocator<T>> : std::true_type {};
 struct default_allocator_is_nothrow : std::true_type {};
@@ -655,59 +650,42 @@
 #endif
 
 namespace memory_internal {
-#ifdef ABSL_HAVE_EXCEPTIONS  // ConstructRange
 template <typename Allocator, typename Iterator, typename... Args>
 void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
                     const Args&... args) {
   for (Iterator cur = first; cur != last; ++cur) {
-    try {
-      std::allocator_traits<Allocator>::construct(alloc, cur, args...);
-    } catch (...) {
+    ABSL_INTERNAL_TRY {
+      std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
+                                                  args...);
+    }
+    ABSL_INTERNAL_CATCH_ANY {
       while (cur != first) {
         --cur;
-        std::allocator_traits<Allocator>::destroy(alloc, cur);
+        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
       }
-      throw;
+      ABSL_INTERNAL_RETHROW;
     }
   }
 }
-#else   // ABSL_HAVE_EXCEPTIONS  // ConstructRange
-template <typename Allocator, typename Iterator, typename... Args>
-void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
-                    const Args&... args) {
-  for (; first != last; ++first) {
-    std::allocator_traits<Allocator>::construct(alloc, first, args...);
-  }
-}
-#endif  // ABSL_HAVE_EXCEPTIONS  // ConstructRange
 
-#ifdef ABSL_HAVE_EXCEPTIONS  // CopyRange
 template <typename Allocator, typename Iterator, typename InputIterator>
 void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
                InputIterator last) {
   for (Iterator cur = destination; first != last;
        static_cast<void>(++cur), static_cast<void>(++first)) {
-    try {
-      std::allocator_traits<Allocator>::construct(alloc, cur, *first);
-    } catch (...) {
+    ABSL_INTERNAL_TRY {
+      std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
+                                                  *first);
+    }
+    ABSL_INTERNAL_CATCH_ANY {
       while (cur != destination) {
         --cur;
-        std::allocator_traits<Allocator>::destroy(alloc, cur);
+        std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
       }
-      throw;
+      ABSL_INTERNAL_RETHROW;
     }
   }
 }
-#else   // ABSL_HAVE_EXCEPTIONS  // CopyRange
-template <typename Allocator, typename Iterator, typename InputIterator>
-void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
-               InputIterator last) {
-  for (; first != last;
-       static_cast<void>(++destination), static_cast<void>(++first)) {
-    std::allocator_traits<Allocator>::construct(alloc, destination, *first);
-  }
-}
-#endif  // ABSL_HAVE_EXCEPTIONS  // CopyRange
 }  // namespace memory_internal
 }  // namespace absl
 
diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc
index 00d2b19..a1c3970 100644
--- a/absl/memory/memory_exception_safety_test.cc
+++ b/absl/memory/memory_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index 2e453e2..8905433 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -69,6 +69,45 @@
   EXPECT_EQ("hi", *p);
 }
 
+// InitializationVerifier fills in a pattern when allocated so we can
+// distinguish between its default and value initialized states (without
+// accessing truly uninitialized memory).
+struct InitializationVerifier {
+  static constexpr int kDefaultScalar = 0x43;
+  static constexpr int kDefaultArray = 0x4B;
+
+  static void* operator new(size_t n) {
+    void* ret = ::operator new(n);
+    memset(ret, kDefaultScalar, n);
+    return ret;
+  }
+
+  static void* operator new[](size_t n) {
+    void* ret = ::operator new[](n);
+    memset(ret, kDefaultArray, n);
+    return ret;
+  }
+
+  int a;
+  int b;
+};
+
+TEST(Initialization, MakeUnique) {
+  auto p = absl::make_unique<InitializationVerifier>();
+
+  EXPECT_EQ(0, p->a);
+  EXPECT_EQ(0, p->b);
+}
+
+TEST(Initialization, MakeUniqueArray) {
+  auto p = absl::make_unique<InitializationVerifier[]>(2);
+
+  EXPECT_EQ(0, p[0].a);
+  EXPECT_EQ(0, p[0].b);
+  EXPECT_EQ(0, p[1].a);
+  EXPECT_EQ(0, p[1].b);
+}
+
 struct MoveOnly {
   MoveOnly() = default;
   explicit MoveOnly(int i1) : ip1{new int{i1}} {}
@@ -145,7 +184,7 @@
     explicit TakesStdType(const std::vector<int> &vec) {}
   };
   using absl::make_unique;
-  make_unique<TakesStdType>(std::vector<int>());
+  (void)make_unique<TakesStdType>(std::vector<int>());
 }
 
 #if 0
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index dbc9717..1c39fa9 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -1,5 +1,5 @@
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/meta/CMakeLists.txt b/absl/meta/CMakeLists.txt
index adb0ceb..74d4a54 100644
--- a/absl/meta/CMakeLists.txt
+++ b/absl/meta/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,39 +14,37 @@
 # limitations under the License.
 #
 
-list(APPEND META_PUBLIC_HEADERS
-  "type_traits.h"
+absl_cc_library(
+  NAME
+    type_traits
+  HDRS
+    "type_traits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-# test type_traits_test
-list(APPEND TYPE_TRAITS_TEST_SRC
-  "type_traits_test.cc"
-  ${META_PUBLIC_HEADERS}
-)
-
-absl_header_library(
-  TARGET
-    absl_meta
-  PUBLIC_LIBRARIES
-    absl::base
-  EXPORT_NAME
-    meta
- )
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     type_traits_test
-  SOURCES
-    ${TYPE_TRAITS_TEST_SRC}
-  PUBLIC_LIBRARIES
+  SRCS
+    "type_traits_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::type_traits
     absl::base
-    absl::meta
+    absl::core_headers
+    gmock_main
 )
 
-
-
+# component target
+absl_cc_library(
+  NAME
+    meta
+  DEPS
+    absl::type_traits
+  PUBLIC
+)
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 23ebd6e..fbdc921 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -22,7 +22,7 @@
 // support type inference, classification, and transformation, as well as
 // make it easier to write templates based on generic type behavior.
 //
-// See http://en.cppreference.com/w/cpp/header/type_traits
+// See https://en.cppreference.com/w/cpp/header/type_traits
 //
 // WARNING: use of many of the constructs in this header will count as "complex
 // template metaprogramming", so before proceeding, please carefully consider
@@ -246,7 +246,7 @@
 // For the purposes of this check, the call to std::declval is considered
 // trivial."
 //
-// Notes from http://en.cppreference.com/w/cpp/types/is_constructible:
+// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
 // In many implementations, is_nothrow_constructible also checks if the
 // destructor throws because it is effectively noexcept(T(arg)). Same
 // applies to is_trivially_constructible, which, in these implementations, also
@@ -413,24 +413,139 @@
 using result_of_t = typename std::result_of<T>::type;
 
 namespace type_traits_internal {
+// In MSVC we can't probe std::hash or stdext::hash because it triggers a
+// static_assert instead of failing substitution. Libc++ prior to 4.0
+// also used a static_assert.
+//
+#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
+                          _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
+#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
+#else
+#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
+#endif
+
+#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 template <typename Key, typename = size_t>
+struct IsHashable : std::true_type {};
+#else   // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+template <typename Key, typename = void>
 struct IsHashable : std::false_type {};
 
 template <typename Key>
-struct IsHashable<Key,
-                  decltype(std::declval<std::hash<Key>>()(std::declval<Key>()))>
-    : std::true_type {};
+struct IsHashable<
+    Key,
+    absl::enable_if_t<std::is_convertible<
+        decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
+        std::size_t>::value>> : std::true_type {};
+#endif  // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 
-template <typename Key>
-struct IsHashEnabled
-    : absl::conjunction<std::is_default_constructible<std::hash<Key>>,
-                        std::is_copy_constructible<std::hash<Key>>,
-                        std::is_destructible<std::hash<Key>>,
-                        absl::is_copy_assignable<std::hash<Key>>,
-                        IsHashable<Key>> {};
+struct AssertHashEnabledHelper {
+ private:
+  static void Sink(...) {}
+  struct NAT {};
+
+  template <class Key>
+  static auto GetReturnType(int)
+      -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
+  template <class Key>
+  static NAT GetReturnType(...);
+
+  template <class Key>
+  static std::nullptr_t DoIt() {
+    static_assert(IsHashable<Key>::value,
+                  "std::hash<Key> does not provide a call operator");
+    static_assert(
+        std::is_default_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be default constructible when it is enabled");
+    static_assert(
+        std::is_copy_constructible<std::hash<Key>>::value,
+        "std::hash<Key> must be copy constructible when it is enabled");
+    static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
+                  "std::hash<Key> must be copy assignable when it is enabled");
+    // is_destructible is unchecked as it's implied by each of the
+    // is_constructible checks.
+    using ReturnType = decltype(GetReturnType<Key>(0));
+    static_assert(std::is_same<ReturnType, NAT>::value ||
+                      std::is_same<ReturnType, size_t>::value,
+                  "std::hash<Key> must return size_t");
+    return nullptr;
+  }
+
+  template <class... Ts>
+  friend void AssertHashEnabled();
+};
+
+template <class... Ts>
+inline void AssertHashEnabled() {
+  using Helper = AssertHashEnabledHelper;
+  Helper::Sink(Helper::DoIt<Ts>()...);
+}
 
 }  // namespace type_traits_internal
 
+// An internal namespace that is required to implement the C++17 swap traits.
+// It is not further nested in type_traits_internal to avoid long symbol names.
+namespace swap_internal {
+
+// Necessary for the traits.
+using std::swap;
+
+// This declaration prevents global `swap` and `absl::swap` overloads from being
+// considered unless ADL picks them up.
+void swap();
+
+template <class T>
+using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
+
+// NOTE: This dance with the default template parameter is for MSVC.
+template <class T,
+          class IsNoexcept = std::integral_constant<
+              bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
+using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
+
+// IsSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T`.
+template <class T>
+struct IsSwappable
+    : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
+
+// IsNothrowSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T` and is noexcept.
+template <class T>
+struct IsNothrowSwappable
+    : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
+
+// Swap()
+//
+// Performs the swap idiom from a namespace where valid candidates may only be
+// found in `std` or via ADL.
+template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
+void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
+  swap(lhs, rhs);
+}
+
+// StdSwapIsUnconstrained
+//
+// Some standard library implementations are broken in that they do not
+// constrain `std::swap`. This will effectively tell us if we are dealing with
+// one of those implementations.
+using StdSwapIsUnconstrained = IsSwappable<void()>;
+
+}  // namespace swap_internal
+
+namespace type_traits_internal {
+
+// Make the swap-related traits/function accessible from this namespace.
+using swap_internal::IsNothrowSwappable;
+using swap_internal::IsSwappable;
+using swap_internal::Swap;
+using swap_internal::StdSwapIsUnconstrained;
+
+}  // namespace type_traits_internal
 }  // namespace absl
 
 #endif  // ABSL_META_TYPE_TRAITS_H_
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index f51f5de..912336e 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -953,4 +953,85 @@
 #endif  // _LIBCPP_VERSION
 }
 
+namespace adl_namespace {
+
+struct DeletedSwap {
+};
+
+void swap(DeletedSwap&, DeletedSwap&) = delete;
+
+struct SpecialNoexceptSwap {
+  SpecialNoexceptSwap(SpecialNoexceptSwap&&) {}
+  SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; }
+  ~SpecialNoexceptSwap() = default;
+};
+
+void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {}
+
+}  // namespace adl_namespace
+
+TEST(TypeTraitsTest, IsSwappable) {
+  using absl::type_traits_internal::IsSwappable;
+  using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+  EXPECT_TRUE(IsSwappable<int>::value);
+
+  struct S {};
+  EXPECT_TRUE(IsSwappable<S>::value);
+
+  struct NoConstruct {
+    NoConstruct(NoConstruct&&) = delete;
+    NoConstruct& operator=(NoConstruct&&) { return *this; }
+    ~NoConstruct() = default;
+  };
+
+  EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value);
+  struct NoAssign {
+    NoAssign(NoAssign&&) {}
+    NoAssign& operator=(NoAssign&&) = delete;
+    ~NoAssign() = default;
+  };
+
+  EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value);
+
+  EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value);
+
+  EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
+TEST(TypeTraitsTest, IsNothrowSwappable) {
+  using absl::type_traits_internal::IsNothrowSwappable;
+  using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+  EXPECT_TRUE(IsNothrowSwappable<int>::value);
+
+  struct NonNoexceptMoves {
+    NonNoexceptMoves(NonNoexceptMoves&&) {}
+    NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; }
+    ~NonNoexceptMoves() = default;
+  };
+
+  EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value);
+
+  struct NoConstruct {
+    NoConstruct(NoConstruct&&) = delete;
+    NoConstruct& operator=(NoConstruct&&) { return *this; }
+    ~NoConstruct() = default;
+  };
+
+  EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value);
+
+  struct NoAssign {
+    NoAssign(NoAssign&&) {}
+    NoAssign& operator=(NoAssign&&) = delete;
+    ~NoAssign() = default;
+  };
+
+  EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value);
+
+  EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value);
+
+  EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
 }  // namespace
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index 324ce66..7cd7ee1 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -4,7 +4,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt
index 3360b2e..d26141c 100644
--- a/absl/numeric/CMakeLists.txt
+++ b/absl/numeric/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,49 +14,45 @@
 # limitations under the License.
 #
 
-list(APPEND NUMERIC_PUBLIC_HEADERS
-  "int128.h"
-)
-
-
-# library 128
-list(APPEND INT128_SRC
-  "int128.cc"
-  ${NUMERIC_PUBLIC_HEADERS}
-)
-absl_library(
-  TARGET
-    absl_int128
-  SOURCES
-    ${INT128_SRC}
-  PUBLIC_LIBRARIES
-    ${INT128_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     int128
+  HDRS
+    "int128.h"
+  SRCS
+    "int128.cc"
+    "int128_have_intrinsic.inc"
+    "int128_no_intrinsic.inc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+  PUBLIC
 )
 
-
-absl_header_library(
-  TARGET
-    absl_numeric
-  PUBLIC_LIBRARIES
-    absl::int128
-  EXPORT_NAME
-    numeric
-)
-
-# test int128_test
-set(INT128_TEST_SRC "int128_test.cc")
-set(INT128_TEST_PUBLIC_LIBRARIES absl::numeric absl::base)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     int128_test
-  SOURCES
-    ${INT128_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${INT128_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "int128_stream_test.cc"
+    "int128_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::int128
+    absl::base
+    absl::core_headers
+    absl::hash_testing
+    absl::type_traits
+    gmock_main
 )
 
-
-
+# component target
+absl_cc_library(
+  NAME
+    numeric
+  DEPS
+    absl::int128
+  PUBLIC
+)
diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc
index cd79534..93b62c5 100644
--- a/absl/numeric/int128.cc
+++ b/absl/numeric/int128.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,7 +17,7 @@
 #include <stddef.h>
 #include <cassert>
 #include <iomanip>
-#include <iostream>  // NOLINT(readability/streams)
+#include <ostream>  // NOLINT(readability/streams)
 #include <sstream>
 #include <string>
 #include <type_traits>
@@ -65,7 +65,7 @@
 
 // Long division/modulo for uint128 implemented using the shift-subtract
 // division algorithm adapted from:
-// http://stackoverflow.com/questions/5386377/division-without-using
+// https://stackoverflow.com/questions/5386377/division-without-using
 void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
                 uint128* remainder_ret) {
   assert(divisor != 0);
@@ -123,6 +123,28 @@
 
   return MakeUint128(0, static_cast<uint64_t>(v));
 }
+
+#if defined(__clang__) && !defined(__SSE3__)
+// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
+// Casting from long double to uint64_t is miscompiled and drops bits.
+// It is more work, so only use when we need the workaround.
+uint128 MakeUint128FromFloat(long double v) {
+  // Go 50 bits at a time, that fits in a double
+  static_assert(std::numeric_limits<double>::digits >= 50, "");
+  static_assert(std::numeric_limits<long double>::digits <= 150, "");
+  // Undefined behavior if v is not finite or cannot fit into uint128.
+  assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));
+
+  v = std::ldexp(v, -100);
+  uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+  v = std::ldexp(v - static_cast<double>(w0), 50);
+  uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+  v = std::ldexp(v - static_cast<double>(w1), 50);
+  uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+  return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
+         static_cast<uint128>(w2);
+}
+#endif  // __clang__ && !__SSE3__
 }  // namespace
 
 uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 79b62a7..2f5b8ad 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -37,8 +37,21 @@
 #include "absl/base/macros.h"
 #include "absl/base/port.h"
 
-namespace absl {
+#if defined(_MSC_VER)
+// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
+// a typedef for unsigned short.  Otherwise wchar_t is mapped to the __wchar_t
+// builtin type.  We need to make sure not to define operator wchar_t()
+// alongside operator unsigned short() in these instances.
+#define ABSL_INTERNAL_WCHAR_T __wchar_t
+#if defined(_M_X64)
+#include <intrin.h>
+#pragma intrinsic(_umul128)
+#endif  // defined(_M_X64)
+#else   // defined(_MSC_VER)
+#define ABSL_INTERNAL_WCHAR_T wchar_t
+#endif  // defined(_MSC_VER)
 
+namespace absl {
 
 // uint128
 //
@@ -126,7 +139,7 @@
   constexpr explicit operator unsigned char() const;
   constexpr explicit operator char16_t() const;
   constexpr explicit operator char32_t() const;
-  constexpr explicit operator wchar_t() const;
+  constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
   constexpr explicit operator short() const;  // NOLINT(runtime/int)
   // NOLINTNEXTLINE(runtime/int)
   constexpr explicit operator unsigned short() const;
@@ -227,8 +240,8 @@
 // TODO(strel) add operator>>(std::istream&, uint128)
 
 constexpr uint128 Uint128Max() {
-  return uint128(std::numeric_limits<uint64_t>::max(),
-                 std::numeric_limits<uint64_t>::max());
+  return uint128((std::numeric_limits<uint64_t>::max)(),
+                 (std::numeric_limits<uint64_t>::max)());
 }
 
 }  // namespace absl
@@ -266,9 +279,9 @@
 #endif  // ABSL_HAVE_INTRINSIC_INT128
   static constexpr bool tinyness_before = false;
 
-  static constexpr absl::uint128 min() { return 0; }
+  static constexpr absl::uint128 (min)() { return 0; }
   static constexpr absl::uint128 lowest() { return 0; }
-  static constexpr absl::uint128 max() { return absl::Uint128Max(); }
+  static constexpr absl::uint128 (max)() { return absl::Uint128Max(); }
   static constexpr absl::uint128 epsilon() { return 0; }
   static constexpr absl::uint128 round_error() { return 0; }
   static constexpr absl::uint128 infinity() { return 0; }
@@ -384,13 +397,13 @@
 
 constexpr uint128::uint128(int v)
     : lo_{static_cast<uint64_t>(v)},
-      hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0} {}
+      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
     : lo_{static_cast<uint64_t>(v)},
-      hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0} {}
+      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
     : lo_{static_cast<uint64_t>(v)},
-      hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0} {}
+      hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
 
 constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
 // NOLINTNEXTLINE(runtime/int)
@@ -413,13 +426,13 @@
     : hi_{high}, lo_{low} {}
 
 constexpr uint128::uint128(int v)
-    : hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0},
+    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
       lo_{static_cast<uint64_t>(v)} {}
 constexpr uint128::uint128(long v)  // NOLINT(runtime/int)
-    : hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0},
+    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
       lo_{static_cast<uint64_t>(v)} {}
 constexpr uint128::uint128(long long v)  // NOLINT(runtime/int)
-    : hi_{v < 0 ? std::numeric_limits<uint64_t>::max() : 0},
+    : hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
       lo_{static_cast<uint64_t>(v)} {}
 
 constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
@@ -463,8 +476,8 @@
   return static_cast<char32_t>(lo_);
 }
 
-constexpr uint128::operator wchar_t() const {
-  return static_cast<wchar_t>(lo_);
+constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
+  return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
 }
 
 // NOLINTNEXTLINE(runtime/int)
@@ -661,6 +674,12 @@
   // can be used for uint128 storage.
   return static_cast<unsigned __int128>(lhs) *
          static_cast<unsigned __int128>(rhs);
+#elif defined(_MSC_VER) && defined(_M_X64)
+  uint64_t carry;
+  uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
+  return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
+                         Uint128High64(lhs) * Uint128Low64(rhs) + carry,
+                     low);
 #else   // ABSL_HAVE_INTRINSIC128
   uint64_t a32 = Uint128Low64(lhs) >> 32;
   uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
@@ -708,4 +727,6 @@
 
 }  // namespace absl
 
+#undef ABSL_INTERNAL_WCHAR_T
+
 #endif  // ABSL_NUMERIC_INT128_H_
diff --git a/absl/numeric/int128_benchmark.cc b/absl/numeric/int128_benchmark.cc
index 1cb7d0e..a5502d9 100644
--- a/absl/numeric/int128_benchmark.cc
+++ b/absl/numeric/int128_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc
index ee2a093..c7ea683 100644
--- a/absl/numeric/int128_have_intrinsic.inc
+++ b/absl/numeric/int128_have_intrinsic.inc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -15,4 +15,4 @@
 
 // This file contains :int128 implementation details that depend on internal
 // representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is
-// included by int128.h.
+// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc
index 0d0b3cf..046cb9b 100644
--- a/absl/numeric/int128_no_intrinsic.inc
+++ b/absl/numeric/int128_no_intrinsic.inc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -15,4 +15,4 @@
 
 // This file contains :int128 implementation details that depend on internal
 // representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
-// is included by int128.h.
+// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
diff --git a/absl/numeric/int128_stream_test.cc b/absl/numeric/int128_stream_test.cc
index 09efaad..3cfa9dc 100644
--- a/absl/numeric/int128_stream_test.cc
+++ b/absl/numeric/int128_stream_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index dfe3475..5e1b5ec 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -51,7 +51,7 @@
 class Uint128FloatTraitsTest : public ::testing::Test {};
 typedef ::testing::Types<float, double, long double> FloatingPointTypes;
 
-TYPED_TEST_CASE(Uint128IntegerTraitsTest, IntegerTypes);
+TYPED_TEST_SUITE(Uint128IntegerTraitsTest, IntegerTypes);
 
 TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) {
   static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
@@ -62,7 +62,7 @@
                 "TypeParam must not be assignable from absl::uint128");
 }
 
-TYPED_TEST_CASE(Uint128FloatTraitsTest, FloatingPointTypes);
+TYPED_TEST_SUITE(Uint128FloatTraitsTest, FloatingPointTypes);
 
 TYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) {
   static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
@@ -271,6 +271,20 @@
   EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);
   EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);
   EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);
+
+  absl::uint128 highest_precision_in_long_double =
+      ~absl::uint128{} >> (128 - std::numeric_limits<long double>::digits);
+  EXPECT_EQ(highest_precision_in_long_double,
+            static_cast<absl::uint128>(
+                static_cast<long double>(highest_precision_in_long_double)));
+  // Apply a mask just to make sure all the bits are the right place.
+  const absl::uint128 arbitrary_mask =
+      absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468);
+  EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask,
+            static_cast<absl::uint128>(static_cast<long double>(
+                highest_precision_in_long_double & arbitrary_mask)));
+
+  EXPECT_EQ(static_cast<absl::uint128>(-0.1L), 0);
 }
 
 TEST(Uint128, OperatorAssignReturnRef) {
@@ -440,4 +454,29 @@
   EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max());
 }
 
+TEST(Uint128, Hash) {
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      // Some simple values
+      absl::uint128{0},
+      absl::uint128{1},
+      ~absl::uint128{},
+      // 64 bit limits
+      absl::uint128{std::numeric_limits<int64_t>::max()},
+      absl::uint128{std::numeric_limits<uint64_t>::max()} + 0,
+      absl::uint128{std::numeric_limits<uint64_t>::max()} + 1,
+      absl::uint128{std::numeric_limits<uint64_t>::max()} + 2,
+      // Keeping high same
+      absl::uint128{1} << 62,
+      absl::uint128{1} << 63,
+      // Keeping low same
+      absl::uint128{1} << 64,
+      absl::uint128{1} << 65,
+      // 128 bit limits
+      std::numeric_limits<absl::uint128>::max(),
+      std::numeric_limits<absl::uint128>::max() - 1,
+      std::numeric_limits<absl::uint128>::min() + 1,
+      std::numeric_limits<absl::uint128>::min(),
+  }));
+}
+
 }  // namespace
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 6d7c261..9640ff4 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -5,17 +5,16 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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.
-#
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
@@ -413,6 +412,7 @@
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":pow10_helper",
         ":strings",
         "//absl/base",
         "//absl/base:core_headers",
@@ -471,6 +471,8 @@
     srcs = ["charconv_test.cc"],
     copts = ABSL_TEST_COPTS,
     deps = [
+        ":pow10_helper",
+        ":str_format",
         ":strings",
         "//absl/base",
         "@com_google_googletest//:gtest_main",
@@ -659,3 +661,23 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "pow10_helper",
+    testonly = True,
+    srcs = ["internal/pow10_helper.cc"],
+    hdrs = ["internal/pow10_helper.h"],
+    visibility = ["//visibility:private"],
+)
+
+cc_test(
+    name = "pow10_helper_test",
+    srcs = ["internal/pow10_helper_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":pow10_helper",
+        ":str_format",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/strings/BUILD.gn b/absl/strings/BUILD.gn
index 20af83c..6f5cef6 100644
--- a/absl/strings/BUILD.gn
+++ b/absl/strings/BUILD.gn
@@ -144,3 +144,21 @@
     "../types:span",
   ]
 }
+
+source_set("pow10_helper") {
+  testonly = true
+  configs -= [ "//build/config/compiler:chromium_code" ]
+  configs += [
+    "//build/config/compiler:no_chromium_code",
+    "//third_party/abseil-cpp:absl_default_cflags_cc",
+  ]
+  public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
+  sources = [
+    "internal/pow10_helper.cc",
+  ]
+  public = [
+    "internal/pow10_helper.h",
+  ]
+  visibility = []
+  visibility += [ ":*" ]
+}
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index f3e4162..d3393a3 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,93 +14,359 @@
 # limitations under the License.
 #
 
-
-list(APPEND STRINGS_PUBLIC_HEADERS
-  "ascii.h"
-  "charconv.h"
-  "escaping.h"
-  "match.h"
-  "numbers.h"
-  "str_cat.h"
-  "string_view.h"
-  "strip.h"
-  "str_join.h"
-  "str_replace.h"
-  "str_split.h"
-  "substitute.h"
-)
-
-
-list(APPEND STRINGS_INTERNAL_HEADERS
-  "internal/char_map.h"
-  "internal/charconv_bigint.h"
-  "internal/charconv_parse.h"
-  "internal/memutil.h"
-  "internal/ostringstream.h"
-  "internal/resize_uninitialized.h"
-  "internal/stl_type_traits.h"
-  "internal/str_join_internal.h"
-  "internal/str_split_internal.h"
-  "internal/utf8.h"
-)
-
-
-
-# add string library
-list(APPEND STRINGS_SRC
-  "ascii.cc"
-  "charconv.cc"
-  "escaping.cc"
-  "internal/charconv_bigint.cc"
-  "internal/charconv_parse.cc"
-  "internal/memutil.cc"
-  "internal/memutil.h"
-  "internal/utf8.cc"
-  "internal/ostringstream.cc"
-  "match.cc"
-  "numbers.cc"
-  "str_cat.cc"
-  "str_replace.cc"
-  "str_split.cc"
-  "string_view.cc"
-  "substitute.cc"
-  ${STRINGS_PUBLIC_HEADERS}
-  ${STRINGS_INTERNAL_HEADERS}
-)
-set(STRINGS_PUBLIC_LIBRARIES absl::base absl_throw_delegate)
-
-absl_library(
-  TARGET
-    absl_strings
-  SOURCES
-    ${STRINGS_SRC}
-  PUBLIC_LIBRARIES
-    ${STRINGS_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     strings
+  HDRS
+    "ascii.h"
+    "charconv.h"
+    "escaping.h"
+    "match.h"
+    "numbers.h"
+    "str_cat.h"
+    "str_join.h"
+    "str_replace.h"
+    "str_split.h"
+    "string_view.h"
+    "strip.h"
+    "substitute.h"
+  SRCS
+    "ascii.cc"
+    "charconv.cc"
+    "escaping.cc"
+    "internal/charconv_bigint.cc"
+    "internal/charconv_bigint.h"
+    "internal/charconv_parse.cc"
+    "internal/charconv_parse.h"
+    "internal/memutil.cc"
+    "internal/memutil.h"
+    "internal/stl_type_traits.h"
+    "internal/str_join_internal.h"
+    "internal/str_split_internal.h"
+    "match.cc"
+    "numbers.cc"
+    "str_cat.cc"
+    "str_replace.cc"
+    "str_split.cc"
+    "string_view.cc"
+    "substitute.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::strings_internal
+    absl::base
+    absl::bits
+    absl::config
+    absl::core_headers
+    absl::endian
+    absl::throw_delegate
+    absl::memory
+    absl::type_traits
+    absl::int128
+  PUBLIC
 )
 
-# add str_format library
-absl_header_library(
-  TARGET
-    absl_str_format
-  PUBLIC_LIBRARIES
-    str_format_internal
-  EXPORT_NAME
+absl_cc_library(
+  NAME
+    strings_internal
+  HDRS
+    "internal/char_map.h"
+    "internal/ostringstream.h"
+    "internal/resize_uninitialized.h"
+    "internal/utf8.h"
+  SRCS
+    "internal/ostringstream.cc"
+    "internal/utf8.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::endian
+    absl::type_traits
+)
+
+absl_cc_test(
+  NAME
+    match_test
+  SRCS
+    "match_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    escaping_test
+  SRCS
+    "escaping_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    absl::fixed_array
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    ascii_test
+  SRCS
+    "ascii_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    memutil_test
+  SRCS
+    "internal/memutil.h"
+    "internal/memutil_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    utf8_test
+  SRCS
+    "internal/utf8_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings_internal
+    absl::base
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    string_view_test
+  SRCS
+    "string_view_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::strings
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    substitute_test
+  SRCS
+    "substitute_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_replace_test
+  SRCS
+    "str_replace_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_split_test
+  SRCS
+    "str_split_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    absl::core_headers
+    absl::dynamic_annotations
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    ostringstream_test
+  SRCS
+    "internal/ostringstream_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    resize_uninitialized_test
+  SRCS
+    "internal/resize_uninitialized.h"
+    "internal/resize_uninitialized_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_join_test
+  SRCS
+    "str_join_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    absl::core_headers
+    absl::memory
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_cat_test
+  SRCS
+    "str_cat_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::core_headers
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    numbers_test
+  SRCS
+    "internal/numbers_test_common.h"
+    "numbers_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    absl::core_headers
+    absl::pow10_helper
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    strip_test
+  SRCS
+    "strip_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    char_map_test
+  SRCS
+    "internal/char_map_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    charconv_test
+  SRCS
+    "charconv_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::str_format
+    absl::base
+    absl::pow10_helper
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    charconv_parse_test
+  SRCS
+    "internal/charconv_parse.h"
+    "internal/charconv_parse_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    charconv_bigint_test
+  SRCS
+    "internal/charconv_bigint.h"
+    "internal/charconv_bigint_test.cc"
+    "internal/charconv_parse.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::base
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
     str_format
+  HDRS
+    "str_format.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::str_format_internal
+  PUBLIC
 )
 
-# str_format_internal
-absl_library(
-  TARGET
+absl_cc_library(
+  NAME
     str_format_internal
-  SOURCES
-    "internal/str_format/arg.cc"
-    "internal/str_format/bind.cc"
-    "internal/str_format/extension.cc"
-    "internal/str_format/float_conversion.cc"
-    "internal/str_format/output.cc"
-    "internal/str_format/parser.cc"
+  HDRS
     "internal/str_format/arg.h"
     "internal/str_format/bind.h"
     "internal/str_format/checker.h"
@@ -108,356 +374,145 @@
     "internal/str_format/float_conversion.h"
     "internal/str_format/output.h"
     "internal/str_format/parser.h"
-  PUBLIC_LIBRARIES
-    str_format_extension_internal
+  SRCS
+    "internal/str_format/arg.cc"
+    "internal/str_format/bind.cc"
+    "internal/str_format/extension.cc"
+    "internal/str_format/float_conversion.cc"
+    "internal/str_format/output.cc"
+    "internal/str_format/parser.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
     absl::strings
-    absl::base
-    absl::numeric
-    absl::container
+    absl::core_headers
+    absl::inlined_vector
+    absl::type_traits
+    absl::int128
     absl::span
 )
 
-# str_format_extension_internal
-absl_library(
-  TARGET
-    str_format_extension_internal
-  SOURCES
-    "internal/str_format/extension.cc"
-    "internal/str_format/extension.h"
-    "internal/str_format/output.cc"
-    "internal/str_format/output.h"
-  PUBLIC_LIBRARIES
-    absl::base
-    absl::strings
-)
-
-#
-## TESTS
-#
-
-# test match_test
-set(MATCH_TEST_SRC "match_test.cc")
-set(MATCH_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    match_test
-  SOURCES
-    ${MATCH_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MATCH_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test escaping_test
-set(ESCAPING_TEST_SRC "escaping_test.cc")
-set(ESCAPING_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
-  TARGET
-    escaping_test
-  SOURCES
-    ${ESCAPING_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ESCAPING_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test ascii_test
-set(ASCII_TEST_SRC "ascii_test.cc")
-set(ASCII_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    ascii_test
-  SOURCES
-    ${ASCII_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ASCII_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test memutil_test
-set(MEMUTIL_TEST_SRC "internal/memutil_test.cc")
-set(MEMUTIL_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    memutil_test
-  SOURCES
-    ${MEMUTIL_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MEMUTIL_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test utf8_test
-set(UTF8_TEST_SRC "internal/utf8_test.cc")
-set(UTF8_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
-  TARGET
-    utf8_test
-  SOURCES
-    ${UTF8_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${UTF8_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test string_view_test
-set(STRING_VIEW_TEST_SRC "string_view_test.cc")
-set(STRING_VIEW_TEST_PUBLIC_LIBRARIES absl::strings absl_throw_delegate absl::base)
-
-absl_test(
-  TARGET
-    string_view_test
-  SOURCES
-    ${STRING_VIEW_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STRING_VIEW_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test substitute_test
-set(SUBSTITUTE_TEST_SRC "substitute_test.cc")
-set(SUBSTITUTE_TEST_PUBLIC_LIBRARIES absl::strings absl::base)
-
-absl_test(
-  TARGET
-    substitute_test
-  SOURCES
-    ${SUBSTITUTE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SUBSTITUTE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test str_replace_test
-set(STR_REPLACE_TEST_SRC "str_replace_test.cc")
-set(STR_REPLACE_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_throw_delegate)
-
-absl_test(
-  TARGET
-    str_replace_test
-  SOURCES
-    ${STR_REPLACE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_REPLACE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test str_split_test
-set(STR_SPLIT_TEST_SRC "str_split_test.cc")
-set(STR_SPLIT_TEST_PUBLIC_LIBRARIES absl::strings absl::base absl_throw_delegate)
-
-absl_test(
-  TARGET
-    str_split_test
-  SOURCES
-    ${STR_SPLIT_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_SPLIT_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test ostringstream_test
-set(OSTRINGSTREAM_TEST_SRC "internal/ostringstream_test.cc")
-set(OSTRINGSTREAM_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    ostringstream_test
-  SOURCES
-    ${OSTRINGSTREAM_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${OSTRINGSTREAM_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test resize_uninitialized_test
-set(RESIZE_UNINITIALIZED_TEST_SRC "internal/resize_uninitialized_test.cc")
-
-absl_test(
-  TARGET
-    resize_uninitialized_test
-  SOURCES
-    ${RESIZE_UNINITIALIZED_TEST_SRC}
-)
-
-
-# test str_join_test
-set(STR_JOIN_TEST_SRC "str_join_test.cc")
-set(STR_JOIN_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    str_join_test
-  SOURCES
-    ${STR_JOIN_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_JOIN_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test str_cat_test
-set(STR_CAT_TEST_SRC "str_cat_test.cc")
-set(STR_CAT_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    str_cat_test
-  SOURCES
-    ${STR_CAT_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STR_CAT_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test numbers_test
-set(NUMBERS_TEST_SRC "numbers_test.cc")
-set(NUMBERS_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    numbers_test
-  SOURCES
-    ${NUMBERS_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${NUMBERS_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test strip_test
-set(STRIP_TEST_SRC "strip_test.cc")
-set(STRIP_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    strip_test
-  SOURCES
-    ${STRIP_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${STRIP_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test char_map_test
-set(CHAR_MAP_TEST_SRC "internal/char_map_test.cc")
-set(CHAR_MAP_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    char_map_test
-  SOURCES
-    ${CHAR_MAP_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHAR_MAP_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test charconv_test
-set(CHARCONV_TEST_SRC "charconv_test.cc")
-set(CHARCONV_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    charconv_test
-  SOURCES
-    ${CHARCONV_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHARCONV_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test charconv_parse_test
-set(CHARCONV_PARSE_TEST_SRC "internal/charconv_parse_test.cc")
-set(CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    charconv_parse_test
-  SOURCES
-    ${CHARCONV_PARSE_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHARCONV_PARSE_TEST_PUBLIC_LIBRARIES}
-)
-
-
-# test charconv_bigint_test
-set(CHARCONV_BIGINT_TEST_SRC "internal/charconv_bigint_test.cc")
-set(CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES absl::strings)
-
-absl_test(
-  TARGET
-    charconv_bigint_test
-  SOURCES
-    ${CHARCONV_BIGINT_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${CHARCONV_BIGINT_TEST_PUBLIC_LIBRARIES}
-)
-# test str_format_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     str_format_test
-  SOURCES
+  SRCS
     "str_format_test.cc"
-  PUBLIC_LIBRARIES
-    absl::base
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
     absl::str_format
     absl::strings
+    absl::core_headers
+    gmock_main
 )
 
-# test str_format_bind_test
-absl_test(
-  TARGET
-    str_format_bind_test
-  SOURCES
-    "internal/str_format/bind_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_internal
-)
-
-# test str_format_checker_test
-absl_test(
-  TARGET
-    str_format_checker_test
-  SOURCES
-    "internal/str_format/checker_test.cc"
-  PUBLIC_LIBRARIES
+absl_cc_test(
+  NAME
+    str_format_extension_test
+  SRCS
+    "internal/str_format/extension_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
     absl::str_format
+    absl::str_format_internal
+    gmock_main
 )
 
-# test str_format_convert_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
+    str_format_arg_test
+  SRCS
+    "internal/str_format/arg_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format
+    absl::str_format_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_format_bind_test
+  SRCS
+    "internal/str_format/bind_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    str_format_checker_test
+  SRCS
+    "internal/str_format/checker_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
     str_format_convert_test
-  SOURCES
+  SRCS
     "internal/str_format/convert_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_internal
-    absl::numeric
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    absl::int128
+    gmock_main
 )
 
-# test str_format_output_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     str_format_output_test
-  SOURCES
+  SRCS
     "internal/str_format/output_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_extension_internal
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    gmock_main
 )
 
-# test str_format_parser_test
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     str_format_parser_test
-  SOURCES
+  SRCS
     "internal/str_format/parser_test.cc"
-  PUBLIC_LIBRARIES
-    str_format_internal
-    absl::base
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::str_format_internal
+    absl::core_headers
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    pow10_helper
+  HDRS
+    "internal/pow10_helper.h"
+  SRCS
+    "internal/pow10_helper.cc"
+  TESTONLY
+)
 
+absl_cc_test(
+  NAME
+    pow10_helper_test
+  SRCS
+    "internal/pow10_helper_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::pow10_helper
+    absl::str_format
+    gmock_main
+)
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc
index c9481e8..3f7c581 100644
--- a/absl/strings/ascii.cc
+++ b/absl/strings/ascii.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h
index 48a9da2..f9e4fd1 100644
--- a/absl/strings/ascii.h
+++ b/absl/strings/ascii.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc
index 8dea4b8..aca458c 100644
--- a/absl/strings/ascii_benchmark.cc
+++ b/absl/strings/ascii_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/ascii_test.cc b/absl/strings/ascii_test.cc
index 9903b04..5ecd23f 100644
--- a/absl/strings/ascii_test.cc
+++ b/absl/strings/ascii_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/charconv.cc b/absl/strings/charconv.cc
index c7b8c98..bc07e7a 100644
--- a/absl/strings/charconv.cc
+++ b/absl/strings/charconv.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -551,9 +551,10 @@
   int binary_exponent = Power10Exponent(parsed_decimal.exponent);
 
   // Discard bits that are inaccurate due to truncation error.  The magic
-  // `mantissa_width` constants below are justified in charconv_algorithm.md.
-  // They represent the number of bits in `wide_binary_mantissa` that are
-  // guaranteed to be unaffected by error propagation.
+  // `mantissa_width` constants below are justified in
+  // https://abseil.io/about/design/charconv. They represent the number of bits
+  // in `wide_binary_mantissa` that are guaranteed to be unaffected by error
+  // propagation.
   bool mantissa_exact;
   int mantissa_width;
   if (parsed_decimal.subrange_begin) {
diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h
index 0735382..59f74bf 100644
--- a/absl/strings/charconv.h
+++ b/absl/strings/charconv.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/charconv_benchmark.cc b/absl/strings/charconv_benchmark.cc
index fd83f44..644b2ab 100644
--- a/absl/strings/charconv_benchmark.cc
+++ b/absl/strings/charconv_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/charconv_test.cc b/absl/strings/charconv_test.cc
index 89418fe..b58fad2 100644
--- a/absl/strings/charconv_test.cc
+++ b/absl/strings/charconv_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -19,7 +19,9 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/strings/internal/pow10_helper.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 
 #ifdef _MSC_FULL_VER
 #define ABSL_COMPILER_DOES_EXACT_ROUNDING 0
@@ -31,6 +33,8 @@
 
 namespace {
 
+using absl::strings_internal::Pow10;
+
 #if ABSL_COMPILER_DOES_EXACT_ROUNDING
 
 // Tests that the given string is accepted by absl::from_chars, and that it
@@ -275,7 +279,8 @@
   absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low);
   EXPECT_EQ(expected_low, actual_low);
 
-  std::string high_rep = absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
+  std::string high_rep =
+      absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
   FloatType actual_high = 0;
   absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(),
                    actual_high);
@@ -678,7 +683,8 @@
     auto result =
         absl::from_chars(input.data(), input.data() + input.size(), actual);
     EXPECT_EQ(result.ec, std::errc());
-    EXPECT_EQ(expected, actual);
+    EXPECT_EQ(expected, actual)
+        << absl::StrFormat("%a vs %a", expected, actual);
   }
   // test legal values near upper_bound
   for (index = upper_bound, step = 1; index > lower_bound;
@@ -690,7 +696,8 @@
     auto result =
         absl::from_chars(input.data(), input.data() + input.size(), actual);
     EXPECT_EQ(result.ec, std::errc());
-    EXPECT_EQ(expected, actual);
+    EXPECT_EQ(expected, actual)
+        << absl::StrFormat("%a vs %a", expected, actual);
   }
   // Test underflow values below lower_bound
   for (index = lower_bound - 1, step = 1; index > -1000000;
@@ -747,7 +754,7 @@
 // acceptable exponents in this test.
 TEST(FromChars, DecimalDoubleLimits) {
   auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
-  auto expected_gen = [](int index) { return std::pow(10.0, index); };
+  auto expected_gen = [](int index) { return Pow10(index); };
   TestOverflowAndUnderflow<double>(input_gen, expected_gen, -323, 308);
 }
 
@@ -759,7 +766,7 @@
 // acceptable exponents in this test.
 TEST(FromChars, DecimalFloatLimits) {
   auto input_gen = [](int index) { return absl::StrCat("1.0e", index); };
-  auto expected_gen = [](int index) { return std::pow(10.0, index); };
+  auto expected_gen = [](int index) { return Pow10(index); };
   TestOverflowAndUnderflow<float>(input_gen, expected_gen, -45, 38);
 }
 
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc
index 8d8b00b..bc8307e 100644
--- a/absl/strings/escaping.cc
+++ b/absl/strings/escaping.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -179,7 +179,8 @@
             ch = (ch << 4) + hex_digit_to_int(*++p);
           if (ch > 0xFF) {
             if (error) {
-              *error = "Value of \\" + std::string(hex_start, p + 1 - hex_start) +
+              *error = "Value of \\" +
+                       std::string(hex_start, p + 1 - hex_start) +
                        " exceeds 0xff";
             }
             return false;
@@ -294,7 +295,7 @@
 // ----------------------------------------------------------------------
 // CUnescapeInternal()
 //
-//    Same as above but uses a C++ string for output. 'source' and 'dest'
+//    Same as above but uses a std::string for output. 'source' and 'dest'
 //    may be the same.
 // ----------------------------------------------------------------------
 bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
@@ -324,7 +325,8 @@
 //
 //    Escaped chars: \n, \r, \t, ", ', \, and !absl::ascii_isprint().
 // ----------------------------------------------------------------------
-std::string CEscapeInternal(absl::string_view src, bool use_hex, bool utf8_safe) {
+std::string CEscapeInternal(absl::string_view src, bool use_hex,
+                            bool utf8_safe) {
   std::string dest;
   bool last_hex_escape = false;  // true if last output char was \xNN.
 
@@ -786,7 +788,7 @@
   // Base64 encodes three bytes of input at a time. If the input is not
   // divisible by three, we pad as appropriate.
   //
-  // (from http://tools.ietf.org/html/rfc3548)
+  // (from https://tools.ietf.org/html/rfc3548)
   // Special processing is performed if fewer than 24 bits are available
   // at the end of the data being encoded.  A full encoding quantum is
   // always completed at the end of a quantity.  When fewer than 24 input
@@ -800,12 +802,12 @@
   size_t len = (input_len / 3) * 4;
 
   if (input_len % 3 == 0) {
-    // (from http://tools.ietf.org/html/rfc3548)
+    // (from https://tools.ietf.org/html/rfc3548)
     // (1) the final quantum of encoding input is an integral multiple of 24
     // bits; here, the final unit of encoded output will be an integral
     // multiple of 4 characters with no "=" padding,
   } else if (input_len % 3 == 1) {
-    // (from http://tools.ietf.org/html/rfc3548)
+    // (from https://tools.ietf.org/html/rfc3548)
     // (2) the final quantum of encoding input is exactly 8 bits; here, the
     // final unit of encoded output will be two characters followed by two
     // "=" padding characters, or
@@ -814,7 +816,7 @@
       len += 2;
     }
   } else {  // (input_len % 3 == 2)
-    // (from http://tools.ietf.org/html/rfc3548)
+    // (from https://tools.ietf.org/html/rfc3548)
     // (3) the final quantum of encoding input is exactly 16 bits; here, the
     // final unit of encoded output will be three characters followed by one
     // "=" padding character.
@@ -843,8 +845,8 @@
 
   // Three bytes of data encodes to four characters of cyphertext.
   // So we can pump through three-byte chunks atomically.
-  if (szsrc >= 3) {  // "limit_src - 3" is UB if szsrc < 3
-    while (cur_src < limit_src - 3) {  // as long as we have >= 32 bits
+  if (szsrc >= 3) {  // "limit_src - 3" is UB if szsrc < 3.
+    while (cur_src < limit_src - 3) {  // While we have >= 32 bits.
       uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
 
       cur_dest[0] = base64[in >> 18];
@@ -1011,7 +1013,8 @@
   }
 }
 
-// This is a templated function so that T can be either a char* or a string.
+// This is a templated function so that T can be either a char* or a
+// std::string.
 template <typename T>
 void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
   auto dest_ptr = &dest[0];
@@ -1028,7 +1031,8 @@
 //
 // See CUnescapeInternal() for implementation details.
 // ----------------------------------------------------------------------
-bool CUnescape(absl::string_view source, std::string* dest, std::string* error) {
+bool CUnescape(absl::string_view source, std::string* dest,
+               std::string* error) {
   return CUnescapeInternal(source, kUnescapeNulls, dest, error);
 }
 
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 2965973..fd9be78 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -19,7 +19,6 @@
 //
 // This header file contains string utilities involved in escaping and
 // unescaping strings in various ways.
-//
 
 #ifndef ABSL_STRINGS_ESCAPING_H_
 #define ABSL_STRINGS_ESCAPING_H_
@@ -38,7 +37,7 @@
 // CUnescape()
 //
 // Unescapes a `source` string and copies it into `dest`, rewriting C-style
-// escape sequences (http://en.cppreference.com/w/cpp/language/escape) into
+// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into
 // their proper code point equivalents, returning `true` if successful.
 //
 // The following unescape sequences can be handled:
@@ -56,7 +55,6 @@
 //     UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and
 //     0x99).
 //
-//
 // If any errors are encountered, this function returns `false`, leaving the
 // `dest` output parameter in an unspecified state, and stores the first
 // encountered error in `error`. To disable error reporting, set `error` to
@@ -80,7 +78,7 @@
 // CEscape()
 //
 // Escapes a 'src' string using C-style escapes sequences
-// (http://en.cppreference.com/w/cpp/language/escape), escaping other
+// (https://en.cppreference.com/w/cpp/language/escape), escaping other
 // non-printable/non-whitespace bytes as octal sequences (e.g. "\377").
 //
 // Example:
diff --git a/absl/strings/escaping_benchmark.cc b/absl/strings/escaping_benchmark.cc
index 0f791f4..10d5b03 100644
--- a/absl/strings/escaping_benchmark.cc
+++ b/absl/strings/escaping_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc
index 9dc27f3..d433b4c 100644
--- a/absl/strings/escaping_test.cc
+++ b/absl/strings/escaping_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -36,18 +36,19 @@
 
 TEST(CEscape, EscapeAndUnescape) {
   const std::string inputs[] = {
-    std::string("foo\nxx\r\b\0023"),
-    std::string(""),
-    std::string("abc"),
-    std::string("\1chad_rules"),
-    std::string("\1arnar_drools"),
-    std::string("xxxx\r\t'\"\\"),
-    std::string("\0xx\0", 4),
-    std::string("\x01\x31"),
-    std::string("abc\xb\x42\141bc"),
-    std::string("123\1\x31\x32\x33"),
-    std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
-    std::string("\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
+      std::string("foo\nxx\r\b\0023"),
+      std::string(""),
+      std::string("abc"),
+      std::string("\1chad_rules"),
+      std::string("\1arnar_drools"),
+      std::string("xxxx\r\t'\"\\"),
+      std::string("\0xx\0", 4),
+      std::string("\x01\x31"),
+      std::string("abc\xb\x42\141bc"),
+      std::string("123\1\x31\x32\x33"),
+      std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
+      std::string(
+          "\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
   };
   // Do this twice, once for octal escapes and once for hex escapes.
   for (int kind = 0; kind < 4; kind++) {
@@ -159,15 +160,14 @@
     EXPECT_TRUE(absl::CUnescape(val.escaped, &out));
     EXPECT_EQ(out, val.unescaped);
   }
-  std::string bad[] =
-     {"\\u1",         // too short
-      "\\U1",         // too short
-      "\\Uffffff",    // exceeds 0x10ffff (largest Unicode)
-      "\\U00110000",  // exceeds 0x10ffff (largest Unicode)
-      "\\uD835",      // surrogate character (D800-DFFF)
-      "\\U0000DD04",  // surrogate character (D800-DFFF)
-      "\\777",        // exceeds 0xff
-      "\\xABCD"};     // exceeds 0xff
+  std::string bad[] = {"\\u1",         // too short
+                       "\\U1",         // too short
+                       "\\Uffffff",    // exceeds 0x10ffff (largest Unicode)
+                       "\\U00110000",  // exceeds 0x10ffff (largest Unicode)
+                       "\\uD835",      // surrogate character (D800-DFFF)
+                       "\\U0000DD04",  // surrogate character (D800-DFFF)
+                       "\\777",        // exceeds 0xff
+                       "\\xABCD"};     // exceeds 0xff
   for (const std::string& e : bad) {
     std::string error;
     std::string out;
@@ -258,9 +258,11 @@
   // All escapes, including newlines and null escapes, should have been
   // converted to the equivalent characters.
   EXPECT_EQ(std::string("\0\n"
-                   "0\n"
-                   "\0\n"
-                   "\0", 7), result_string_);
+                        "0\n"
+                        "\0\n"
+                        "\0",
+                        7),
+            result_string_);
 }
 
 
@@ -268,17 +270,21 @@
   std::string original_string(kStringWithMultipleHexNulls);
   EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
   EXPECT_EQ(std::string("\0\n"
-                   "0\n"
-                   "\0\n"
-                   "\0", 7), result_string_);
+                        "0\n"
+                        "\0\n"
+                        "\0",
+                        7),
+            result_string_);
 }
 
 TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) {
   std::string original_string(kStringWithMultipleUnicodeNulls);
   EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
   EXPECT_EQ(std::string("\0\n"
-                   "0\n"
-                   "\0", 5), result_string_);
+                        "0\n"
+                        "\0",
+                        5),
+            result_string_);
 }
 
 static struct {
diff --git a/absl/strings/internal/char_map.h b/absl/strings/internal/char_map.h
index 8d92963..b9108b8 100644
--- a/absl/strings/internal/char_map.h
+++ b/absl/strings/internal/char_map.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/char_map_benchmark.cc b/absl/strings/internal/char_map_benchmark.cc
index c45f315..5cef967 100644
--- a/absl/strings/internal/char_map_benchmark.cc
+++ b/absl/strings/internal/char_map_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/char_map_test.cc b/absl/strings/internal/char_map_test.cc
index c3601e1..d330624 100644
--- a/absl/strings/internal/char_map_test.cc
+++ b/absl/strings/internal/char_map_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc
index 3e7296e..95d471d 100644
--- a/absl/strings/internal/charconv_bigint.cc
+++ b/absl/strings/internal/charconv_bigint.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h
index aa70af2..7da9a7e 100644
--- a/absl/strings/internal/charconv_bigint.h
+++ b/absl/strings/internal/charconv_bigint.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -57,17 +57,10 @@
                 "unsupported max_words value");
 
   BigUnsigned() : size_(0), words_{} {}
-  explicit BigUnsigned(uint32_t v) : size_(v > 0 ? 1 : 0), words_{v} {}
-  explicit BigUnsigned(uint64_t v)
-      : size_(0),
-        words_{static_cast<uint32_t>(v & 0xffffffff),
-               static_cast<uint32_t>(v >> 32)} {
-    if (words_[1]) {
-      size_ = 2;
-    } else if (words_[0]) {
-      size_ = 1;
-    }
-  }
+  explicit constexpr BigUnsigned(uint64_t v)
+      : size_((v >> 32) ? 2 : v ? 1 : 0),
+        words_{static_cast<uint32_t>(v & 0xffffffffu),
+               static_cast<uint32_t>(v >> 32)} {}
 
   // Constructs a BigUnsigned from the given string_view containing a decimal
   // value.  If the input std::string is not a decimal integer, constructs a 0
@@ -110,12 +103,12 @@
         SetToZero();
         return;
       }
-      size_ = std::min(size_ + word_shift, max_words);
+      size_ = (std::min)(size_ + word_shift, max_words);
       count %= 32;
       if (count == 0) {
         std::copy_backward(words_, words_ + size_ - word_shift, words_ + size_);
       } else {
-        for (int i = std::min(size_, max_words - 1); i > word_shift; --i) {
+        for (int i = (std::min)(size_, max_words - 1); i > word_shift; --i) {
           words_[i] = (words_[i - word_shift] << count) |
                       (words_[i - word_shift - 1] >> (32 - count));
         }
@@ -274,7 +267,7 @@
   void MultiplyBy(int other_size, const uint32_t* other_words) {
     const int original_size = size_;
     const int first_step =
-        std::min(original_size + other_size - 2, max_words - 1);
+        (std::min)(original_size + other_size - 2, max_words - 1);
     for (int step = first_step; step >= 0; --step) {
       MultiplyStep(original_size, other_words, other_size, step);
     }
@@ -293,7 +286,7 @@
           value = 0;
         }
       }
-      size_ = std::min(max_words, std::max(index + 1, size_));
+      size_ = (std::min)(max_words, (std::max)(index + 1, size_));
     }
   }
 
@@ -316,7 +309,7 @@
       } else {
         // Normally 32-bit AddWithCarry() sets size_, but since we don't call
         // it when `high` is 0, do it ourselves here.
-        size_ = std::min(max_words, std::max(index + 1, size_));
+        size_ = (std::min)(max_words, (std::max)(index + 1, size_));
       }
     }
   }
@@ -355,7 +348,7 @@
 // Returns -1 if lhs < rhs, 0 if lhs == rhs, and 1 if lhs > rhs.
 template <int N, int M>
 int Compare(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
-  int limit = std::max(lhs.size(), rhs.size());
+  int limit = (std::max)(lhs.size(), rhs.size());
   for (int i = limit - 1; i >= 0; --i) {
     const uint32_t lhs_word = lhs.GetWord(i);
     const uint32_t rhs_word = rhs.GetWord(i);
@@ -370,7 +363,7 @@
 
 template <int N, int M>
 bool operator==(const BigUnsigned<N>& lhs, const BigUnsigned<M>& rhs) {
-  int limit = std::max(lhs.size(), rhs.size());
+  int limit = (std::max)(lhs.size(), rhs.size());
   for (int i = 0; i < limit; ++i) {
     if (lhs.GetWord(i) != rhs.GetWord(i)) {
       return false;
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc
index 9b63578..745714a 100644
--- a/absl/strings/internal/charconv_bigint_test.cc
+++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index 7e4dabc..f3c7232 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/charconv_parse.h b/absl/strings/internal/charconv_parse.h
index 7a5c087..44d06b2 100644
--- a/absl/strings/internal/charconv_parse.h
+++ b/absl/strings/internal/charconv_parse.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/charconv_parse_test.cc b/absl/strings/internal/charconv_parse_test.cc
index f48b9ae..9511c98 100644
--- a/absl/strings/internal/charconv_parse_test.cc
+++ b/absl/strings/internal/charconv_parse_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/escaping_test_common.h b/absl/strings/internal/escaping_test_common.h
index cc41f43..bd80303 100644
--- a/absl/strings/internal/escaping_test_common.h
+++ b/absl/strings/internal/escaping_test_common.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/memutil.cc b/absl/strings/internal/memutil.cc
index a0de70d..77aa63c 100644
--- a/absl/strings/internal/memutil.cc
+++ b/absl/strings/internal/memutil.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/memutil.h b/absl/strings/internal/memutil.h
index 7de383b..7c071a8 100644
--- a/absl/strings/internal/memutil.h
+++ b/absl/strings/internal/memutil.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/memutil_benchmark.cc b/absl/strings/internal/memutil_benchmark.cc
index 77915ad..dc95c3e 100644
--- a/absl/strings/internal/memutil_benchmark.cc
+++ b/absl/strings/internal/memutil_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/memutil_test.cc b/absl/strings/internal/memutil_test.cc
index 09424de..d8681dd 100644
--- a/absl/strings/internal/memutil_test.cc
+++ b/absl/strings/internal/memutil_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h
index 20e3af5..2824720 100644
--- a/absl/strings/internal/numbers_test_common.h
+++ b/absl/strings/internal/numbers_test_common.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -64,11 +64,11 @@
 
 inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
   static const std::array<uint32_test_case, 27> test_cases{{
-      {"0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+      {"0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
       {"0x34234324", true, 16, 0x34234324},
       {"34234324", true, 16, 0x34234324},
       {"0", true, 16, 0},
-      {" \t\n 0xffffffff", true, 16, std::numeric_limits<uint32_t>::max()},
+      {" \t\n 0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
       {" \f\v 46", true, 10, 46},  // must accept weird whitespace
       {" \t\n 72717222", true, 8, 072717222},
       {" \t\n 072717222", true, 8, 072717222},
@@ -77,7 +77,7 @@
 
       // Base-10 version.
       {"34234324", true, 0, 34234324},
-      {"4294967295", true, 0, std::numeric_limits<uint32_t>::max()},
+      {"4294967295", true, 0, (std::numeric_limits<uint32_t>::max)()},
       {"34234324 \n\t", true, 10, 34234324},
 
       // Unusual base
@@ -96,8 +96,8 @@
       {" \t\n -123", false, 0, 0},
 
       // Out of bounds.
-      {"4294967296", false, 0, std::numeric_limits<uint32_t>::max()},
-      {"0x100000000", false, 0, std::numeric_limits<uint32_t>::max()},
+      {"4294967296", false, 0, (std::numeric_limits<uint32_t>::max)()},
+      {"0x100000000", false, 0, (std::numeric_limits<uint32_t>::max)()},
       {nullptr, false, 0, 0},
   }};
   return test_cases;
@@ -119,7 +119,7 @@
       {"000", true, 0, 0},
       {"0", true, 0, 0},
       {" \t\n 0xffffffffffffffff", true, 16,
-       std::numeric_limits<uint64_t>::max()},
+       (std::numeric_limits<uint64_t>::max)()},
 
       {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
       {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
@@ -130,7 +130,7 @@
       {"34234324487834466", true, 0, int64_t{34234324487834466}},
 
       {" \t\n 18446744073709551615", true, 0,
-       std::numeric_limits<uint64_t>::max()},
+       (std::numeric_limits<uint64_t>::max)()},
 
       {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
 
@@ -156,12 +156,13 @@
       // Out of bounds.
       {"18446744073709551616", false, 10, 0},
       {"18446744073709551616", false, 0, 0},
-      {"0x10000000000000000", false, 16, std::numeric_limits<uint64_t>::max()},
+      {"0x10000000000000000", false, 16,
+       (std::numeric_limits<uint64_t>::max)()},
       {"0X10000000000000000", false, 16,
-       std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
-      {"0x10000000000000000", false, 0, std::numeric_limits<uint64_t>::max()},
+       (std::numeric_limits<uint64_t>::max)()},  // 0X versus 0x.
+      {"0x10000000000000000", false, 0, (std::numeric_limits<uint64_t>::max)()},
       {"0X10000000000000000", false, 0,
-       std::numeric_limits<uint64_t>::max()},  // 0X versus 0x.
+       (std::numeric_limits<uint64_t>::max)()},  // 0X versus 0x.
 
       {"0x1234", true, 16, 0x1234},
 
diff --git a/absl/strings/internal/ostringstream.cc b/absl/strings/internal/ostringstream.cc
index 6ee2b10..d0f0f84 100644
--- a/absl/strings/internal/ostringstream.cc
+++ b/absl/strings/internal/ostringstream.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/ostringstream.h b/absl/strings/internal/ostringstream.h
index e81a89a..2079201 100644
--- a/absl/strings/internal/ostringstream.h
+++ b/absl/strings/internal/ostringstream.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -25,18 +25,18 @@
 namespace absl {
 namespace strings_internal {
 
-// The same as std::ostringstream but appends to a user-specified string,
+// The same as std::ostringstream but appends to a user-specified std::string,
 // and is faster. It is ~70% faster to create, ~50% faster to write to, and
-// completely free to extract the result string.
+// completely free to extract the result std::string.
 //
-//   string s;
+//   std::string s;
 //   OStringStream strm(&s);
 //   strm << 42 << ' ' << 3.14;  // appends to `s`
 //
 // The stream object doesn't have to be named. Starting from C++11 operator<<
 // works with rvalues of std::ostream.
 //
-//   string s;
+//   std::string s;
 //   OStringStream(&s) << 42 << ' ' << 3.14;  // appends to `s`
 //
 // OStringStream is faster to create than std::ostringstream but it's still
@@ -45,14 +45,14 @@
 //
 // Creates unnecessary instances of OStringStream: slow.
 //
-//   string s;
+//   std::string s;
 //   OStringStream(&s) << 42;
 //   OStringStream(&s) << ' ';
 //   OStringStream(&s) << 3.14;
 //
 // Creates a single instance of OStringStream and reuses it: fast.
 //
-//   string s;
+//   std::string s;
 //   OStringStream strm(&s);
 //   strm << 42;
 //   strm << ' ';
@@ -64,8 +64,8 @@
   // The argument can be null, in which case you'll need to call str(p) with a
   // non-null argument before you can write to the stream.
   //
-  // The destructor of OStringStream doesn't use the std::string. It's OK to destroy
-  // the std::string before the stream.
+  // The destructor of OStringStream doesn't use the std::string. It's OK to
+  // destroy the std::string before the stream.
   explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {}
 
   std::string* str() { return s_; }
diff --git a/absl/strings/internal/ostringstream_benchmark.cc b/absl/strings/internal/ostringstream_benchmark.cc
index c93f969..5979f18 100644
--- a/absl/strings/internal/ostringstream_benchmark.cc
+++ b/absl/strings/internal/ostringstream_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/ostringstream_test.cc b/absl/strings/internal/ostringstream_test.cc
index 069a0e1..2879e50 100644
--- a/absl/strings/internal/ostringstream_test.cc
+++ b/absl/strings/internal/ostringstream_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/pow10_helper.cc b/absl/strings/internal/pow10_helper.cc
new file mode 100644
index 0000000..03ed8d0
--- /dev/null
+++ b/absl/strings/internal/pow10_helper.cc
@@ -0,0 +1,120 @@
+// 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.
+
+#include "absl/strings/internal/pow10_helper.h"
+
+#include <cmath>
+
+namespace absl {
+namespace strings_internal {
+
+namespace {
+
+// The exact value of 1e23 falls precisely halfway between two representable
+// doubles. Furthermore, the rounding rules we prefer (break ties by rounding
+// to the nearest even) dictate in this case that the number should be rounded
+// down, but this is not completely specified for floating-point literals in
+// C++. (It just says to use the default rounding mode of the standard
+// library.) We ensure the result we want by using a number that has an
+// unambiguous correctly rounded answer.
+constexpr double k1e23 = 9999999999999999e7;
+
+constexpr double kPowersOfTen[] = {
+    0.0,    1e-323, 1e-322, 1e-321, 1e-320, 1e-319, 1e-318, 1e-317, 1e-316,
+    1e-315, 1e-314, 1e-313, 1e-312, 1e-311, 1e-310, 1e-309, 1e-308, 1e-307,
+    1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301, 1e-300, 1e-299, 1e-298,
+    1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291, 1e-290, 1e-289,
+    1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281, 1e-280,
+    1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
+    1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262,
+    1e-261, 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253,
+    1e-252, 1e-251, 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244,
+    1e-243, 1e-242, 1e-241, 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235,
+    1e-234, 1e-233, 1e-232, 1e-231, 1e-230, 1e-229, 1e-228, 1e-227, 1e-226,
+    1e-225, 1e-224, 1e-223, 1e-222, 1e-221, 1e-220, 1e-219, 1e-218, 1e-217,
+    1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211, 1e-210, 1e-209, 1e-208,
+    1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201, 1e-200, 1e-199,
+    1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191, 1e-190,
+    1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
+    1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172,
+    1e-171, 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163,
+    1e-162, 1e-161, 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154,
+    1e-153, 1e-152, 1e-151, 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145,
+    1e-144, 1e-143, 1e-142, 1e-141, 1e-140, 1e-139, 1e-138, 1e-137, 1e-136,
+    1e-135, 1e-134, 1e-133, 1e-132, 1e-131, 1e-130, 1e-129, 1e-128, 1e-127,
+    1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121, 1e-120, 1e-119, 1e-118,
+    1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111, 1e-110, 1e-109,
+    1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101, 1e-100,
+    1e-99,  1e-98,  1e-97,  1e-96,  1e-95,  1e-94,  1e-93,  1e-92,  1e-91,
+    1e-90,  1e-89,  1e-88,  1e-87,  1e-86,  1e-85,  1e-84,  1e-83,  1e-82,
+    1e-81,  1e-80,  1e-79,  1e-78,  1e-77,  1e-76,  1e-75,  1e-74,  1e-73,
+    1e-72,  1e-71,  1e-70,  1e-69,  1e-68,  1e-67,  1e-66,  1e-65,  1e-64,
+    1e-63,  1e-62,  1e-61,  1e-60,  1e-59,  1e-58,  1e-57,  1e-56,  1e-55,
+    1e-54,  1e-53,  1e-52,  1e-51,  1e-50,  1e-49,  1e-48,  1e-47,  1e-46,
+    1e-45,  1e-44,  1e-43,  1e-42,  1e-41,  1e-40,  1e-39,  1e-38,  1e-37,
+    1e-36,  1e-35,  1e-34,  1e-33,  1e-32,  1e-31,  1e-30,  1e-29,  1e-28,
+    1e-27,  1e-26,  1e-25,  1e-24,  1e-23,  1e-22,  1e-21,  1e-20,  1e-19,
+    1e-18,  1e-17,  1e-16,  1e-15,  1e-14,  1e-13,  1e-12,  1e-11,  1e-10,
+    1e-9,   1e-8,   1e-7,   1e-6,   1e-5,   1e-4,   1e-3,   1e-2,   1e-1,
+    1e+0,   1e+1,   1e+2,   1e+3,   1e+4,   1e+5,   1e+6,   1e+7,   1e+8,
+    1e+9,   1e+10,  1e+11,  1e+12,  1e+13,  1e+14,  1e+15,  1e+16,  1e+17,
+    1e+18,  1e+19,  1e+20,  1e+21,  1e+22,  k1e23,  1e+24,  1e+25,  1e+26,
+    1e+27,  1e+28,  1e+29,  1e+30,  1e+31,  1e+32,  1e+33,  1e+34,  1e+35,
+    1e+36,  1e+37,  1e+38,  1e+39,  1e+40,  1e+41,  1e+42,  1e+43,  1e+44,
+    1e+45,  1e+46,  1e+47,  1e+48,  1e+49,  1e+50,  1e+51,  1e+52,  1e+53,
+    1e+54,  1e+55,  1e+56,  1e+57,  1e+58,  1e+59,  1e+60,  1e+61,  1e+62,
+    1e+63,  1e+64,  1e+65,  1e+66,  1e+67,  1e+68,  1e+69,  1e+70,  1e+71,
+    1e+72,  1e+73,  1e+74,  1e+75,  1e+76,  1e+77,  1e+78,  1e+79,  1e+80,
+    1e+81,  1e+82,  1e+83,  1e+84,  1e+85,  1e+86,  1e+87,  1e+88,  1e+89,
+    1e+90,  1e+91,  1e+92,  1e+93,  1e+94,  1e+95,  1e+96,  1e+97,  1e+98,
+    1e+99,  1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107,
+    1e+108, 1e+109, 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116,
+    1e+117, 1e+118, 1e+119, 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125,
+    1e+126, 1e+127, 1e+128, 1e+129, 1e+130, 1e+131, 1e+132, 1e+133, 1e+134,
+    1e+135, 1e+136, 1e+137, 1e+138, 1e+139, 1e+140, 1e+141, 1e+142, 1e+143,
+    1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149, 1e+150, 1e+151, 1e+152,
+    1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159, 1e+160, 1e+161,
+    1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169, 1e+170,
+    1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
+    1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188,
+    1e+189, 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197,
+    1e+198, 1e+199, 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206,
+    1e+207, 1e+208, 1e+209, 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215,
+    1e+216, 1e+217, 1e+218, 1e+219, 1e+220, 1e+221, 1e+222, 1e+223, 1e+224,
+    1e+225, 1e+226, 1e+227, 1e+228, 1e+229, 1e+230, 1e+231, 1e+232, 1e+233,
+    1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239, 1e+240, 1e+241, 1e+242,
+    1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249, 1e+250, 1e+251,
+    1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259, 1e+260,
+    1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
+    1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278,
+    1e+279, 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287,
+    1e+288, 1e+289, 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296,
+    1e+297, 1e+298, 1e+299, 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305,
+    1e+306, 1e+307, 1e+308,
+};
+
+}  // namespace
+
+double Pow10(int exp) {
+  if (exp < -324) {
+    return 0.0;
+  } else if (exp > 308) {
+    return INFINITY;
+  } else {
+    return kPowersOfTen[exp + 324];
+  }
+}
+
+}  // namespace strings_internal
+}  // namespace absl
diff --git a/absl/strings/internal/pow10_helper.h b/absl/strings/internal/pow10_helper.h
new file mode 100644
index 0000000..9d1aa71
--- /dev/null
+++ b/absl/strings/internal/pow10_helper.h
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+// This test helper library contains a table of powers of 10, to guarantee
+// precise values are computed across the full range of doubles. We can't rely
+// on the pow() function, because not all standard libraries ship a version
+// that is precise.
+#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+
+#include <vector>
+
+namespace absl {
+namespace strings_internal {
+
+// Computes the precise value of 10^exp. (I.e. the nearest representable
+// double to the exact value, rounding to nearest-even in the (single) case of
+// being exactly halfway between.)
+double Pow10(int exp);
+
+}  // namespace strings_internal
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/absl/strings/internal/pow10_helper_test.cc b/absl/strings/internal/pow10_helper_test.cc
new file mode 100644
index 0000000..a4a68b5
--- /dev/null
+++ b/absl/strings/internal/pow10_helper_test.cc
@@ -0,0 +1,120 @@
+// 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.
+
+#include "absl/strings/internal/pow10_helper.h"
+
+#include <cmath>
+
+#include "gtest/gtest.h"
+#include "absl/strings/str_format.h"
+
+namespace absl {
+namespace strings_internal {
+
+namespace {
+
+struct TestCase {
+  int power;           // Testing Pow10(power)
+  uint64_t significand;  // Raw bits of the expected value
+  int radix;           // significand is adjusted by 2^radix
+};
+
+TEST(Pow10HelperTest, Works) {
+  // The logic in pow10_helper.cc is so simple that theoretically we don't even
+  // need a test. However, we're paranoid and believe that there may be
+  // compilers that don't round floating-point literals correctly, even though
+  // it is specified by the standard. We check various edge cases, just to be
+  // sure.
+  constexpr TestCase kTestCases[] = {
+      // Subnormals
+      {-323, 0x2, -1074},
+      {-322, 0x14, -1074},
+      {-321, 0xca, -1074},
+      {-320, 0x7e8, -1074},
+      {-319, 0x4f10, -1074},
+      {-318, 0x316a2, -1074},
+      {-317, 0x1ee257, -1074},
+      {-316, 0x134d761, -1074},
+      {-315, 0xc1069cd, -1074},
+      {-314, 0x78a42205, -1074},
+      {-313, 0x4b6695433, -1074},
+      {-312, 0x2f201d49fb, -1074},
+      {-311, 0x1d74124e3d1, -1074},
+      {-310, 0x12688b70e62b, -1074},
+      {-309, 0xb8157268fdaf, -1074},
+      {-308, 0x730d67819e8d2, -1074},
+      // Values that are very close to rounding the other way.
+      // Comment shows difference of significand from the true value.
+      {-307, 0x11fa182c40c60d, -1072},  // -.4588
+      {-290, 0x18f2b061aea072, -1016},  //  .4854
+      {-276, 0x11BA03F5B21000, -969},   //  .4709
+      {-259, 0x1899C2F6732210, -913},   //  .4830
+      {-252, 0x1D53844EE47DD1, -890},   // -.4743
+      {-227, 0x1E5297287C2F45, -807},   // -.4708
+      {-198, 0x1322E220A5B17E, -710},   // -.4714
+      {-195, 0x12B010D3E1CF56, -700},   //  .4928
+      {-192, 0x123FF06EEA847A, -690},   //  .4968
+      {-163, 0x1708D0F84D3DE7, -594},   // -.4977
+      {-145, 0x13FAAC3E3FA1F3, -534},   // -.4785
+      {-111, 0x133D4032C2C7F5, -421},   //  .4774
+      {-106, 0x1D5B561574765B, -405},   // -.4869
+      {-104, 0x16EF5B40C2FC77, -398},   // -.4741
+      {-88, 0x197683DF2F268D, -345},    // -.4738
+      {-86, 0x13E497065CD61F, -338},    //  .4736
+      {-76, 0x17288E1271F513, -305},    // -.4761
+      {-63, 0x1A53FC9631D10D, -262},    //  .4929
+      {-30, 0x14484BFEEBC2A0, -152},    //  .4758
+      {-21, 0x12E3B40A0E9B4F, -122},    // -.4916
+      {-5, 0x14F8B588E368F1, -69},      //  .4829
+      {23, 0x152D02C7E14AF6, 24},       // -.5000 (exactly, round-to-even)
+      {29, 0x1431E0FAE6D721, 44},       // -.4870
+      {34, 0x1ED09BEAD87C03, 60},       // -.4721
+      {70, 0x172EBAD6DDC73D, 180},      //  .4733
+      {105, 0x1BE7ABD3781ECA, 296},     // -.4850
+      {126, 0x17A2ECC414A03F, 366},     // -.4999
+      {130, 0x1CDA62055B2D9E, 379},     //  .4855
+      {165, 0x115D847AD00087, 496},     // -.4913
+      {172, 0x14B378469B6732, 519},     //  .4818
+      {187, 0x1262DFEEBBB0F9, 569},     // -.4805
+      {210, 0x18557F31326BBB, 645},     // -.4992
+      {212, 0x1302CB5E6F642A, 652},     // -.4838
+      {215, 0x1290BA9A38C7D1, 662},     // -.4881
+      {236, 0x1F736F9B3494E9, 731},     //  .4707
+      {244, 0x176EC98994F489, 758},     //  .4924
+      {250, 0x1658E3AB795204, 778},     // -.4963
+      {252, 0x117571DDF6C814, 785},     //  .4873
+      {254, 0x1B4781EAD1989E, 791},     // -.4887
+      {260, 0x1A03FDE214CAF1, 811},     //  .4784
+      {284, 0x1585041B2C477F, 891},     //  .4798
+      {304, 0x1D2A1BE4048F90, 957},     // -.4987
+      // Out-of-range values
+      {-324, 0x0, 0},
+      {-325, 0x0, 0},
+      {-326, 0x0, 0},
+      {309, 1, 2000},
+      {310, 1, 2000},
+      {311, 1, 2000},
+  };
+  for (const TestCase& test_case : kTestCases) {
+    EXPECT_EQ(Pow10(test_case.power),
+              std::ldexp(test_case.significand, test_case.radix))
+        << absl::StrFormat("Failure for Pow10(%d): %a vs %a", test_case.power,
+                           Pow10(test_case.power),
+                           std::ldexp(test_case.significand, test_case.radix));
+  }
+}
+
+}  // namespace
+}  // namespace strings_internal
+}  // namespace absl
diff --git a/absl/strings/internal/resize_uninitialized.h b/absl/strings/internal/resize_uninitialized.h
index a94e054..469962b 100644
--- a/absl/strings/internal/resize_uninitialized.h
+++ b/absl/strings/internal/resize_uninitialized.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -18,6 +18,7 @@
 #define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
 
 #include <string>
+#include <type_traits>
 #include <utility>
 
 #include "absl/base/port.h"
@@ -27,40 +28,42 @@
 namespace strings_internal {
 
 // Is a subclass of true_type or false_type, depending on whether or not
-// T has a resize_uninitialized member.
-template <typename T, typename = void>
-struct HasResizeUninitialized : std::false_type {};
-template <typename T>
-struct HasResizeUninitialized<
-    T, absl::void_t<decltype(std::declval<T>().resize_uninitialized(237))>>
-    : std::true_type {};
+// T has a __resize_default_init member.
+template <typename string_type, typename = void>
+struct ResizeUninitializedTraits {
+  using HasMember = std::false_type;
+  static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
+};
 
+// __resize_default_init is provided by libc++ >= 8.0 and by Google's internal
+// ::string implementation.
 template <typename string_type>
-void ResizeUninit(string_type* s, size_t new_size, std::true_type) {
-  s->resize_uninitialized(new_size);
-}
-template <typename string_type>
-void ResizeUninit(string_type* s, size_t new_size, std::false_type) {
-  s->resize(new_size);
-}
+struct ResizeUninitializedTraits<
+    string_type, absl::void_t<decltype(std::declval<string_type&>()
+                                           .__resize_default_init(237))> > {
+  using HasMember = std::true_type;
+  static void Resize(string_type* s, size_t new_size) {
+    s->__resize_default_init(new_size);
+  }
+};
 
-// Returns true if the string implementation supports a resize where
-// the new characters added to the string are left untouched.
+// Returns true if the std::string implementation supports a resize where
+// the new characters added to the std::string are left untouched.
 //
 // (A better name might be "STLStringSupportsUninitializedResize", alluding to
 // the previous function.)
 template <typename string_type>
 inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
-  return HasResizeUninitialized<string_type>();
+  return ResizeUninitializedTraits<string_type>::HasMember::value;
 }
 
 // Like str->resize(new_size), except any new characters added to "*str" as a
 // result of resizing may be left uninitialized, rather than being filled with
 // '0' bytes. Typically used when code is then going to overwrite the backing
-// store of the string with known data. Uses a Google extension to ::string.
+// store of the std::string with known data.
 template <typename string_type, typename = void>
 inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
-  ResizeUninit(s, new_size, HasResizeUninitialized<string_type>());
+  ResizeUninitializedTraits<string_type>::Resize(s, new_size);
 }
 
 }  // namespace strings_internal
diff --git a/absl/strings/internal/resize_uninitialized_test.cc b/absl/strings/internal/resize_uninitialized_test.cc
index ad282ef..c5be0b1 100644
--- a/absl/strings/internal/resize_uninitialized_test.cc
+++ b/absl/strings/internal/resize_uninitialized_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -24,44 +24,44 @@
   void resize(size_t) { resize_call_count += 1; }
 };
 
-int resize_uninitialized_call_count = 0;
+int resize_default_init_call_count = 0;
 
-struct resize_uninitializable_string {
+struct resize_default_init_string {
   void resize(size_t) { resize_call_count += 1; }
-  void resize_uninitialized(size_t) { resize_uninitialized_call_count += 1; }
+  void __resize_default_init(size_t) { resize_default_init_call_count += 1; }
 };
 
 TEST(ResizeUninit, WithAndWithout) {
   resize_call_count = 0;
-  resize_uninitialized_call_count = 0;
+  resize_default_init_call_count = 0;
   {
     resizable_string rs;
 
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     EXPECT_FALSE(
         absl::strings_internal::STLStringSupportsNontrashingResize(&rs));
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     absl::strings_internal::STLStringResizeUninitialized(&rs, 237);
     EXPECT_EQ(resize_call_count, 1);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
   }
 
   resize_call_count = 0;
-  resize_uninitialized_call_count = 0;
+  resize_default_init_call_count = 0;
   {
-    resize_uninitializable_string rus;
+    resize_default_init_string rus;
 
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     EXPECT_TRUE(
         absl::strings_internal::STLStringSupportsNontrashingResize(&rus));
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 0);
+    EXPECT_EQ(resize_default_init_call_count, 0);
     absl::strings_internal::STLStringResizeUninitialized(&rus, 237);
     EXPECT_EQ(resize_call_count, 0);
-    EXPECT_EQ(resize_uninitialized_call_count, 1);
+    EXPECT_EQ(resize_default_init_call_count, 1);
   }
 }
 
diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h
index 04c4a53..202ab37 100644
--- a/absl/strings/internal/stl_type_traits.h
+++ b/absl/strings/internal/stl_type_traits.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 3376d48..4d48af0 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -35,12 +35,14 @@
     T, void_t<decltype(AbslFormatConvert(
            std::declval<const T&>(), std::declval<ConversionSpec>(),
            std::declval<FormatSink*>()))>> : std::true_type {};
+
 template <typename T>
 class StreamedWrapper;
 
 // If 'v' can be converted (in the printf sense) according to 'conv',
 // then convert it, appending to `sink` and return `true`.
 // Otherwise fail and return `false`.
+
 // Raw pointers.
 struct VoidPtr {
   VoidPtr() = default;
@@ -54,7 +56,8 @@
                                          FormatSinkImpl* sink);
 
 // Strings.
-ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, ConversionSpec conv,
+ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
+                                         ConversionSpec conv,
                                          FormatSinkImpl* sink);
 ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
                                          FormatSinkImpl* sink);
@@ -80,7 +83,7 @@
 
   int precision = conv.precision();
   if (precision >= 0)
-    to_write = std::min(to_write, static_cast<size_t>(precision));
+    to_write = (std::min)(to_write, static_cast<size_t>(precision));
 
   space_remaining = Excess(to_write, space_remaining);
 
@@ -335,12 +338,12 @@
     using CommonType = typename std::conditional<std::is_signed<T>::value,
                                                  int64_t, uint64_t>::type;
     if (static_cast<CommonType>(val) >
-        static_cast<CommonType>(std::numeric_limits<int>::max())) {
-      return std::numeric_limits<int>::max();
+        static_cast<CommonType>((std::numeric_limits<int>::max)())) {
+      return (std::numeric_limits<int>::max)();
     } else if (std::is_signed<T>::value &&
                static_cast<CommonType>(val) <
-                   static_cast<CommonType>(std::numeric_limits<int>::min())) {
-      return std::numeric_limits<int>::min();
+                   static_cast<CommonType>((std::numeric_limits<int>::min)())) {
+      return (std::numeric_limits<int>::min)();
     }
     return static_cast<int>(val);
   }
@@ -409,7 +412,7 @@
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__);        \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__);        \
-  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);             \
+  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__);        \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
 
 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index 83d5904..3421fac 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/absl/strings/internal/str_format/arg_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      https://www.apache.org/licenses/LICENSE-2.0
 //
 #include "absl/strings/internal/str_format/arg.h"
 
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index c4eddd1..a31859e 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -25,12 +25,12 @@
   explicit ArgContext(absl::Span<const FormatArgImpl> pack) : pack_(pack) {}
 
   // Fill 'bound' with the results of applying the context's argument pack
-  // to the specified 'props'. We synthesize a BoundConversion by
+  // to the specified 'unbound'. We synthesize a BoundConversion by
   // lining up a UnboundConversion with a user argument. We also
   // resolve any '*' specifiers for width and precision, so after
   // this call, 'bound' has all the information it needs to be formatted.
   // Returns false on failure.
-  bool Bind(const UnboundConversion *props, BoundConversion *bound);
+  bool Bind(const UnboundConversion* unbound, BoundConversion* bound);
 
  private:
   absl::Span<const FormatArgImpl> pack_;
@@ -53,7 +53,8 @@
         // "A negative field width is taken as a '-' flag followed by a
         // positive field width."
         force_left = true;
-        width = -width;
+        // Make sure we don't overflow the width when negating it.
+        width = -std::max(width, -std::numeric_limits<int>::max());
       }
     }
 
@@ -159,7 +160,7 @@
 }
 
 std::string Summarize(const UntypedFormatSpecImpl format,
-                 absl::Span<const FormatArgImpl> args) {
+                      absl::Span<const FormatArgImpl> args) {
   typedef SummarizingConverter Converter;
   std::string out;
   {
@@ -187,7 +188,7 @@
 }
 
 std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
-                   absl::Span<const FormatArgImpl> args) {
+                        absl::Span<const FormatArgImpl> args) {
   size_t orig = out->size();
   if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
     out->erase(orig);
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 1b52df9..4f78295 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -153,7 +153,7 @@
 
 // for testing
 std::string Summarize(UntypedFormatSpecImpl format,
-                 absl::Span<const FormatArgImpl> args);
+                      absl::Span<const FormatArgImpl> args);
 bool BindWithPack(const UnboundConversion* props,
                   absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
 
@@ -162,10 +162,10 @@
                    absl::Span<const FormatArgImpl> args);
 
 std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
-                   absl::Span<const FormatArgImpl> args);
+                        absl::Span<const FormatArgImpl> args);
 
 inline std::string FormatPack(const UntypedFormatSpecImpl format,
-                         absl::Span<const FormatArgImpl> args) {
+                              absl::Span<const FormatArgImpl> args) {
   std::string out;
   AppendPack(&out, format, args);
   return out;
@@ -176,7 +176,7 @@
 int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
              absl::Span<const FormatArgImpl> args);
 
-// Returned by Streamed(v). Converts via '%s' to the string created
+// Returned by Streamed(v). Converts via '%s' to the std::string created
 // by std::ostream << v.
 template <typename T>
 class StreamedWrapper {
diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc
index 4757573..ba6470e 100644
--- a/absl/strings/internal/str_format/bind_test.cc
+++ b/absl/strings/internal/str_format/bind_test.cc
@@ -1,6 +1,7 @@
 #include "absl/strings/internal/str_format/bind.h"
 
 #include <string.h>
+#include <limits>
 
 #include "gtest/gtest.h"
 
@@ -91,6 +92,20 @@
   }
 }
 
+TEST_F(FormatBindTest, WidthUnderflowRegression) {
+  UnboundConversion props;
+  BoundConversion bound;
+  int next = 0;
+  const int args_i[] = {std::numeric_limits<int>::min(), 17};
+  const FormatArgImpl args[] = {FormatArgImpl(args_i[0]),
+                                FormatArgImpl(args_i[1])};
+  ASSERT_TRUE(Extract("*d", &props, &next));
+  ASSERT_TRUE(BindWithPack(&props, args, &bound));
+
+  EXPECT_EQ(bound.width(), std::numeric_limits<int>::max());
+  EXPECT_EQ(bound.arg(), args + 1);
+}
+
 TEST_F(FormatBindTest, FormatPack) {
   struct Expectation {
     int line;
diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc
index 14d11ea..c1d8c76 100644
--- a/absl/strings/internal/str_format/checker_test.cc
+++ b/absl/strings/internal/str_format/checker_test.cc
@@ -62,32 +62,32 @@
       ValidFormat<int>("%% %d"),                        //
       ValidFormat<int>("%ld"),                          //
       ValidFormat<int>("%lld"),                         //
-      ValidFormat<std::string>("%s"),                        //
-      ValidFormat<std::string>("%10s"),                      //
+      ValidFormat<std::string>("%s"),                   //
+      ValidFormat<std::string>("%10s"),                 //
       ValidFormat<int>("%.10x"),                        //
       ValidFormat<int, int>("%*.3x"),                   //
       ValidFormat<int>("%1.d"),                         //
       ValidFormat<int>("%.d"),                          //
       ValidFormat<int, double>("%d %g"),                //
-      ValidFormat<int, std::string>("%*s"),                  //
+      ValidFormat<int, std::string>("%*s"),             //
       ValidFormat<int, double>("%.*f"),                 //
       ValidFormat<void (*)(), volatile int*>("%p %p"),  //
       ValidFormat<string_view, const char*, double, void*>(
           "string_view=%s const char*=%s double=%f void*=%p)"),
 
-      ValidFormat<int>("%% %1$d"),            //
-      ValidFormat<int>("%1$ld"),              //
-      ValidFormat<int>("%1$lld"),             //
-      ValidFormat<std::string>("%1$s"),            //
-      ValidFormat<std::string>("%1$10s"),          //
-      ValidFormat<int>("%1$.10x"),            //
-      ValidFormat<int>("%1$*1$.*1$d"),        //
-      ValidFormat<int, int>("%1$*2$.3x"),     //
-      ValidFormat<int>("%1$1.d"),             //
-      ValidFormat<int>("%1$.d"),              //
-      ValidFormat<double, int>("%2$d %1$g"),  //
-      ValidFormat<int, std::string>("%2$*1$s"),    //
-      ValidFormat<int, double>("%2$.*1$f"),   //
+      ValidFormat<int>("%% %1$d"),               //
+      ValidFormat<int>("%1$ld"),                 //
+      ValidFormat<int>("%1$lld"),                //
+      ValidFormat<std::string>("%1$s"),          //
+      ValidFormat<std::string>("%1$10s"),        //
+      ValidFormat<int>("%1$.10x"),               //
+      ValidFormat<int>("%1$*1$.*1$d"),           //
+      ValidFormat<int, int>("%1$*2$.3x"),        //
+      ValidFormat<int>("%1$1.d"),                //
+      ValidFormat<int>("%1$.d"),                 //
+      ValidFormat<double, int>("%2$d %1$g"),     //
+      ValidFormat<int, std::string>("%2$*1$s"),  //
+      ValidFormat<int, double>("%2$.*1$f"),      //
       ValidFormat<void*, string_view, const char*, double>(
           "string_view=%2$s const char*=%3$s double=%4$f void*=%1$p "
           "repeat=%3$s)")};
@@ -99,25 +99,25 @@
   constexpr Case falses[] = {
       ValidFormat<int>(""),  //
 
-      ValidFormat<e>("%s"),             //
-      ValidFormat<e2>("%s"),            //
-      ValidFormat<>("%s"),              //
-      ValidFormat<>("%r"),              //
-      ValidFormat<int>("%s"),           //
-      ValidFormat<int>("%.1.d"),        //
-      ValidFormat<int>("%*1d"),         //
-      ValidFormat<int>("%1-d"),         //
+      ValidFormat<e>("%s"),                  //
+      ValidFormat<e2>("%s"),                 //
+      ValidFormat<>("%s"),                   //
+      ValidFormat<>("%r"),                   //
+      ValidFormat<int>("%s"),                //
+      ValidFormat<int>("%.1.d"),             //
+      ValidFormat<int>("%*1d"),              //
+      ValidFormat<int>("%1-d"),              //
       ValidFormat<std::string, int>("%*s"),  //
-      ValidFormat<int>("%*d"),          //
+      ValidFormat<int>("%*d"),               //
       ValidFormat<std::string>("%p"),        //
-      ValidFormat<int (*)(int)>("%d"),  //
+      ValidFormat<int (*)(int)>("%d"),       //
 
-      ValidFormat<>("%3$d"),                //
-      ValidFormat<>("%1$r"),                //
-      ValidFormat<int>("%1$s"),             //
-      ValidFormat<int>("%1$.1.d"),          //
-      ValidFormat<int>("%1$*2$1d"),         //
-      ValidFormat<int>("%1$1-d"),           //
+      ValidFormat<>("%3$d"),                     //
+      ValidFormat<>("%1$r"),                     //
+      ValidFormat<int>("%1$s"),                  //
+      ValidFormat<int>("%1$.1.d"),               //
+      ValidFormat<int>("%1$*2$1d"),              //
+      ValidFormat<int>("%1$1-d"),                //
       ValidFormat<std::string, int>("%2$*1$s"),  //
       ValidFormat<std::string>("%1$p"),
 
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 32f8a0f..99cc0af 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -232,7 +232,7 @@
 template <typename T>
 class TypedFormatConvertTest : public FormatConvertTest { };
 
-TYPED_TEST_CASE_P(TypedFormatConvertTest);
+TYPED_TEST_SUITE_P(TypedFormatConvertTest);
 
 std::vector<std::string> AllFlagCombinations() {
   const char kFlags[] = {'-', '#', '0', '+', ' '};
@@ -363,6 +363,7 @@
     AllIntTypes;
 INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes,
                               TypedFormatConvertTest, AllIntTypes);
+
 TEST_F(FormatConvertTest, Uint128) {
   absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;
   absl::uint128 max = absl::Uint128Max();
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index c217470..d7f5815 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index 11b996a..eb81f8a 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -13,7 +13,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-//
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
 
@@ -360,7 +359,7 @@
   integral = d | i | u | o | x | X,
   floating = a | e | f | g | A | E | F | G,
   numeric = integral | floating,
-  string = s,  // absl:ignore(std::string)
+  string = s,
   pointer = p
 };
 
@@ -409,4 +408,4 @@
 
 }  // namespace absl
 
-#endif  // ABSL_STRINGS_STR_FORMAT_EXTENSION_H_
+#endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 224fc92..4e23fef 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/absl/strings/internal/str_format/extension_test.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -18,6 +18,7 @@
 
 #include <random>
 #include <string>
+
 #include "absl/strings/str_format.h"
 
 #include "gtest/gtest.h"
diff --git a/absl/strings/internal/str_format/output.cc b/absl/strings/internal/str_format/output.cc
index 5c3795b..38987b6 100644
--- a/absl/strings/internal/str_format/output.cc
+++ b/absl/strings/internal/str_format/output.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -20,6 +20,16 @@
 namespace absl {
 namespace str_format_internal {
 
+namespace {
+struct ClearErrnoGuard {
+  ClearErrnoGuard() : old_value(errno) { errno = 0; }
+  ~ClearErrnoGuard() {
+    if (!errno) errno = old_value;
+  }
+  int old_value;
+};
+}  // namespace
+
 void BufferRawSink::Write(string_view v) {
   size_t to_write = std::min(v.size(), size_);
   std::memcpy(buffer_, v.data(), to_write);
@@ -30,14 +40,27 @@
 
 void FILERawSink::Write(string_view v) {
   while (!v.empty() && !error_) {
+    // Reset errno to zero in case the libc implementation doesn't set errno
+    // when a failure occurs.
+    ClearErrnoGuard guard;
+
     if (size_t result = std::fwrite(v.data(), 1, v.size(), output_)) {
       // Some progress was made.
       count_ += result;
       v.remove_prefix(result);
     } else {
-      // Some error occurred.
-      if (errno != EINTR) {
+      if (errno == EINTR) {
+        continue;
+      } else if (errno) {
         error_ = errno;
+      } else if (std::ferror(output_)) {
+        // Non-POSIX compliant libc implementations may not set errno, so we
+        // have check the streams error indicator.
+        error_ = EBADF;
+      } else {
+        // We're likely on a non-POSIX system that encountered EINTR but had no
+        // way of reporting it.
+        continue;
       }
     }
   }
diff --git a/absl/strings/internal/str_format/output.h b/absl/strings/internal/str_format/output.h
index 12ecd99..42da641 100644
--- a/absl/strings/internal/str_format/output.h
+++ b/absl/strings/internal/str_format/output.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc
index cc3c615..6e04abe 100644
--- a/absl/strings/internal/str_format/output_test.cc
+++ b/absl/strings/internal/str_format/output_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,7 +17,6 @@
 #include <sstream>
 #include <string>
 
-
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -28,12 +27,6 @@
   std::string str = "ABC";
   str_format_internal::InvokeFlush(&str, "DEF");
   EXPECT_EQ(str, "ABCDEF");
-
-#if UTIL_FORMAT_HAS_GLOBAL_STRING
-  std::string str2 = "ABC";
-  str_format_internal::InvokeFlush(&str2, "DEF");
-  EXPECT_EQ(str2, "ABCDEF");
-#endif  // UTIL_FORMAT_HAS_GLOBAL_STRING
 }
 
 TEST(InvokeFlush, Stream) {
diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc
index 5e3d0d0..10487f2 100644
--- a/absl/strings/internal/str_format/parser.cc
+++ b/absl/strings/internal/str_format/parser.cc
@@ -99,10 +99,11 @@
     // digit doesn't match the expected characters.
     int num_digits = std::numeric_limits<int>::digits10;
     for (;;) {
-      if (ABSL_PREDICT_FALSE(pos == end || !num_digits)) break;
+      if (ABSL_PREDICT_FALSE(pos == end)) break;
       c = *pos++;
       if (!std::isdigit(c)) break;
       --num_digits;
+      if (ABSL_PREDICT_FALSE(!num_digits)) break;
       digits = 10 * digits + c - '0';
     }
     return digits;
diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc
index ae40203..ff70575 100644
--- a/absl/strings/internal/str_format/parser_test.cc
+++ b/absl/strings/internal/str_format/parser_test.cc
@@ -246,6 +246,8 @@
 
   EXPECT_FALSE(Run("1000000000.999999999d"));
   EXPECT_FALSE(Run("999999999.1000000000d"));
+  EXPECT_FALSE(Run("9999999999d"));
+  EXPECT_FALSE(Run(".9999999999d"));
 }
 
 TEST_F(ConsumeUnboundConversionTest, Flags) {
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h
index 0058fc8..7c35f4d 100644
--- a/absl/strings/internal/str_join_internal.h
+++ b/absl/strings/internal/str_join_internal.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -193,7 +193,7 @@
 // and formats each element using the provided Formatter object.
 template <typename Iterator, typename Formatter>
 std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
-                     Formatter&& f) {
+                          Formatter&& f) {
   std::string result;
   absl::string_view sep("");
   for (Iterator it = start; it != end; ++it) {
@@ -212,7 +212,7 @@
 // This is an overload of the previous JoinAlgorithm() function. Here the
 // Formatter argument is of type NoFormatter. Since NoFormatter is an internal
 // type, this overload is only invoked when strings::Join() is called with a
-// range of string-like objects (e.g., string, absl::string_view), and an
+// range of string-like objects (e.g., std::string, absl::string_view), and an
 // explicit Formatter argument was NOT specified.
 //
 // The optimization is that the needed space will be reserved in the output
@@ -224,7 +224,7 @@
               typename std::iterator_traits<Iterator>::iterator_category,
               std::forward_iterator_tag>::value>::type>
 std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
-                     NoFormatter) {
+                          NoFormatter) {
   std::string result;
   if (start != end) {
     // Sums size
@@ -276,14 +276,15 @@
 
 template <typename... T, typename Formatter>
 std::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep,
-                     Formatter&& fmt) {
+                          Formatter&& fmt) {
   std::string result;
   JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);
   return result;
 }
 
 template <typename Iterator>
-std::string JoinRange(Iterator first, Iterator last, absl::string_view separator) {
+std::string JoinRange(Iterator first, Iterator last,
+                      absl::string_view separator) {
   // No formatter was explicitly given, so a default must be chosen.
   typedef typename std::iterator_traits<Iterator>::value_type ValueType;
   typedef typename DefaultFormatter<ValueType>::Type Formatter;
@@ -292,7 +293,7 @@
 
 template <typename Range, typename Formatter>
 std::string JoinRange(const Range& range, absl::string_view separator,
-                 Formatter&& fmt) {
+                      Formatter&& fmt) {
   using std::begin;
   using std::end;
   return JoinAlgorithm(begin(range), end(range), separator, fmt);
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 81e8d55..52f6222 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -96,8 +96,8 @@
     }
   }
 
-  // Holds the data moved from temporary std::string arguments. Declared first so
-  // that 'value' can refer to 'copy_'.
+  // Holds the data moved from temporary std::string arguments. Declared first
+  // so that 'value' can refer to 'copy_'.
   std::string copy_;
   absl::string_view value_;
 };
@@ -376,10 +376,10 @@
 
   // Partial specialization for a std::vector<std::string>.
   //
-  // Optimized for the common case of splitting to a std::vector<std::string>. In
-  // this case we first split the results to a std::vector<absl::string_view> so
-  // the returned std::vector<std::string> can have space reserved to avoid std::string
-  // moves.
+  // Optimized for the common case of splitting to a std::vector<std::string>.
+  // In this case we first split the results to a std::vector<absl::string_view>
+  // so the returned std::vector<std::string> can have space reserved to avoid
+  // std::string moves.
   template <typename A>
   struct ConvertToContainer<std::vector<std::string, A>, std::string, false> {
     std::vector<std::string, A> operator()(const Splitter& splitter) const {
diff --git a/absl/strings/internal/utf8.cc b/absl/strings/internal/utf8.cc
index 2415c2c..82d36c2 100644
--- a/absl/strings/internal/utf8.cc
+++ b/absl/strings/internal/utf8.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h
index d2c3c0b..0423630 100644
--- a/absl/strings/internal/utf8.h
+++ b/absl/strings/internal/utf8.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -13,7 +13,6 @@
 // limitations under the License.
 //
 // UTF8 utilities, implemented to reduce dependencies.
-//
 
 #ifndef ABSL_STRINGS_INTERNAL_UTF8_H_
 #define ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/absl/strings/internal/utf8_test.cc b/absl/strings/internal/utf8_test.cc
index 64cec70..88dd503 100644
--- a/absl/strings/internal/utf8_test.cc
+++ b/absl/strings/internal/utf8_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -22,12 +22,17 @@
 
 namespace {
 
+#if !defined(__cpp_char8_t)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++2a-compat"
+#endif
 TEST(EncodeUTF8Char, BasicFunction) {
   std::pair<char32_t, std::string> tests[] = {{0x0030, u8"\u0030"},
-                                         {0x00A3, u8"\u00A3"},
-                                         {0x00010000, u8"\U00010000"},
-                                         {0x0000FFFF, u8"\U0000FFFF"},
-                                         {0x0010FFFD, u8"\U0010FFFD"}};
+                                              {0x00A3, u8"\u00A3"},
+                                              {0x00010000, u8"\U00010000"},
+                                              {0x0000FFFF, u8"\U0000FFFF"},
+                                              {0x0010FFFD, u8"\U0010FFFD"}};
   for (auto &test : tests) {
     char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
     char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'};
@@ -53,5 +58,9 @@
   EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf2, -1),
             absl::strings_internal::kMaxEncodedUTF8Size);
 }
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif  // !defined(__cpp_char8_t)
 
 }  // namespace
diff --git a/absl/strings/match.cc b/absl/strings/match.cc
index 3d10c57..7b24241 100644
--- a/absl/strings/match.cc
+++ b/absl/strings/match.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -18,15 +18,6 @@
 
 namespace absl {
 
-namespace {
-bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
-  return (piece1.size() == piece2.size() &&
-          0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
-                                            piece1.size()));
-  // memcasecmp uses ascii_tolower().
-}
-}  // namespace
-
 bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
   return (piece1.size() == piece2.size() &&
           0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
@@ -36,12 +27,12 @@
 
 bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
   return (text.size() >= prefix.size()) &&
-         CaseEqual(text.substr(0, prefix.size()), prefix);
+         EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
 }
 
 bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
   return (text.size() >= suffix.size()) &&
-         CaseEqual(text.substr(text.size() - suffix.size()), suffix);
+         EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
 }
 
 }  // namespace absl
diff --git a/absl/strings/match.h b/absl/strings/match.h
index 6e8ed10..5251b7f 100644
--- a/absl/strings/match.h
+++ b/absl/strings/match.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -74,13 +74,13 @@
 
 // StartsWithIgnoreCase()
 //
-// Returns whether a given ASCII string `text` starts with `starts_with`,
+// Returns whether a given ASCII string `text` starts with `prefix`,
 // ignoring case in the comparison.
 bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
 
 // EndsWithIgnoreCase()
 //
-// Returns whether a given ASCII string `text` ends with `ends_with`, ignoring
+// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
 // case in the comparison.
 bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
 
diff --git a/absl/strings/match_test.cc b/absl/strings/match_test.cc
index c21e00b..4c313dd 100644
--- a/absl/strings/match_test.cc
+++ b/absl/strings/match_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -19,7 +19,7 @@
 namespace {
 
 TEST(MatchTest, StartsWith) {
-  const std::string s1("123" "\0" "456", 7);
+  const std::string s1("123\0abc", 7);
   const absl::string_view a("foobar");
   const absl::string_view b(s1);
   const absl::string_view e;
@@ -36,7 +36,7 @@
 }
 
 TEST(MatchTest, EndsWith) {
-  const std::string s1("123" "\0" "456", 7);
+  const std::string s1("123\0abc", 7);
   const absl::string_view a("foobar");
   const absl::string_view b(s1);
   const absl::string_view e;
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 9309f9d..558c339 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -35,17 +35,18 @@
 #include "absl/strings/ascii.h"
 #include "absl/strings/charconv.h"
 #include "absl/strings/internal/memutil.h"
+#include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
 
 namespace absl {
 
-bool SimpleAtof(absl::string_view str, float* value) {
-  *value = 0.0;
+bool SimpleAtof(absl::string_view str, float* out) {
+  *out = 0.0;
   str = StripAsciiWhitespace(str);
   if (!str.empty() && str[0] == '+') {
     str.remove_prefix(1);
   }
-  auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
+  auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
   if (result.ec == std::errc::invalid_argument) {
     return false;
   }
@@ -56,22 +57,22 @@
   // from_chars() with DR 3801's current wording will return max() on
   // overflow.  SimpleAtof returns infinity instead.
   if (result.ec == std::errc::result_out_of_range) {
-    if (*value > 1.0) {
-      *value = std::numeric_limits<float>::infinity();
-    } else if (*value < -1.0) {
-      *value = -std::numeric_limits<float>::infinity();
+    if (*out > 1.0) {
+      *out = std::numeric_limits<float>::infinity();
+    } else if (*out < -1.0) {
+      *out = -std::numeric_limits<float>::infinity();
     }
   }
   return true;
 }
 
-bool SimpleAtod(absl::string_view str, double* value) {
-  *value = 0.0;
+bool SimpleAtod(absl::string_view str, double* out) {
+  *out = 0.0;
   str = StripAsciiWhitespace(str);
   if (!str.empty() && str[0] == '+') {
     str.remove_prefix(1);
   }
-  auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
+  auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
   if (result.ec == std::errc::invalid_argument) {
     return false;
   }
@@ -82,10 +83,10 @@
   // from_chars() with DR 3801's current wording will return max() on
   // overflow.  SimpleAtod returns infinity instead.
   if (result.ec == std::errc::result_out_of_range) {
-    if (*value > 1.0) {
-      *value = std::numeric_limits<double>::infinity();
-    } else if (*value < -1.0) {
-      *value = -std::numeric_limits<double>::infinity();
+    if (*out > 1.0) {
+      *out = std::numeric_limits<double>::infinity();
+    } else if (*out < -1.0) {
+      *out = -std::numeric_limits<double>::infinity();
     }
   }
   return true;
@@ -93,14 +94,6 @@
 
 namespace {
 
-// TODO(rogeeff): replace with the real released thing once we figure out what
-// it is.
-inline bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
-  return (piece1.size() == piece2.size() &&
-          0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
-                                            piece1.size()));
-}
-
 // Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
 // range 0 <= i < 100, and buf must have space for two characters. Example:
 //   char buf[2];
@@ -136,18 +129,18 @@
 
 }  // namespace
 
-bool SimpleAtob(absl::string_view str, bool* value) {
-  ABSL_RAW_CHECK(value != nullptr, "Output pointer must not be nullptr.");
-  if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
-      CaseEqual(str, "yes") || CaseEqual(str, "y") ||
-      CaseEqual(str, "1")) {
-    *value = true;
+bool SimpleAtob(absl::string_view str, bool* out) {
+  ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
+  if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
+      EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
+      EqualsIgnoreCase(str, "1")) {
+    *out = true;
     return true;
   }
-  if (CaseEqual(str, "false") || CaseEqual(str, "f") ||
-      CaseEqual(str, "no") || CaseEqual(str, "n") ||
-      CaseEqual(str, "0")) {
-    *value = false;
+  if (EqualsIgnoreCase(str, "false") || EqualsIgnoreCase(str, "f") ||
+      EqualsIgnoreCase(str, "no") || EqualsIgnoreCase(str, "n") ||
+      EqualsIgnoreCase(str, "0")) {
+    *out = false;
     return true;
   }
   return false;
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index f9b2cce..e0f96df 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -44,7 +44,8 @@
 // Converts the given string into an integer value, returning `true` if
 // successful. The string must reflect a base-10 integer (optionally followed or
 // preceded by ASCII whitespace) whose value falls within the range of the
-// integer type.
+// integer type. If any errors are encountered, this function returns `false`,
+// leaving `out` in an unspecified state.
 template <typename int_type>
 ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);
 
@@ -52,25 +53,29 @@
 //
 // Converts the given string (optionally followed or preceded by ASCII
 // whitespace) into a float, which may be rounded on overflow or underflow.
-// See http://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`.
-ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* value);
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
 
 // SimpleAtod()
 //
 // Converts the given string (optionally followed or preceded by ASCII
 // whitespace) into a double, which may be rounded on overflow or underflow.
-// See http://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`.
-ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* value);
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
 
 // SimpleAtob()
 //
 // Converts the given string into a boolean, returning `true` if successful.
 // The following case-insensitive strings are interpreted as boolean `true`:
 // "true", "t", "yes", "y", "1". The following case-insensitive strings
-// are interpreted as boolean `false`: "false", "f", "no", "n", "0".
-ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* value);
+// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
+// errors are encountered, this function returns `false`, leaving `out` in an
+// unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
 
 }  // namespace absl
 
diff --git a/absl/strings/numbers_benchmark.cc b/absl/strings/numbers_benchmark.cc
index 0570b75..54dbedd 100644
--- a/absl/strings/numbers_benchmark.cc
+++ b/absl/strings/numbers_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 36fc0d6..ca2ee48 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -39,6 +39,7 @@
 #include "absl/strings/str_cat.h"
 
 #include "absl/strings/internal/numbers_test_common.h"
+#include "absl/strings/internal/pow10_helper.h"
 
 namespace {
 
@@ -190,7 +191,8 @@
   EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
 
   char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
-  EXPECT_EQ(expected, std::string(&buffer[1], generic_actual)) << " Input " << x;
+  EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))
+      << " Input " << x;
 
   char* my_actual =
       absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);
@@ -783,7 +785,7 @@
   if (iters_per_float == 0) iters_per_float = 1;
   for (float f : floats) {
     if (f == last) continue;
-    float testf = nextafter(last, std::numeric_limits<float>::max());
+    float testf = std::nextafter(last, std::numeric_limits<float>::max());
     runnable(testf);
     runnable(-testf);
     last = testf;
@@ -797,7 +799,7 @@
         last = testf;
       }
     }
-    testf = nextafter(f, 0.0f);
+    testf = std::nextafter(f, 0.0f);
     if (testf > last) {
       runnable(testf);
       runnable(-testf);
@@ -871,15 +873,15 @@
     }
 
     for (int exponent = -324; exponent <= 308; ++exponent) {
-      double powten = pow(10.0, exponent);
+      double powten = absl::strings_internal::Pow10(exponent);
       if (powten == 0) powten = 5e-324;
       if (kFloatNumCases >= 1e9) {
         // The exhaustive test takes a very long time, so log progress.
         char buf[kSixDigitsToBufferSize];
         ABSL_RAW_LOG(
             INFO, "%s",
-            absl::StrCat("Exp ", exponent, " powten=", powten, "(",
-                         powten, ") (",
+            absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten,
+                         ") (",
                          std::string(buf, SixDigitsToBuffer(powten, buf)), ")")
                 .c_str());
       }
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc
index efa4fd7..2667976 100644
--- a/absl/strings/str_cat.cc
+++ b/absl/strings/str_cat.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -78,9 +78,9 @@
 
 // ----------------------------------------------------------------------
 // StrCat()
-//    This merges the given strings or integers, with no delimiter.  This
+//    This merges the given strings or integers, with no delimiter. This
 //    is designed to be the fastest possible way to construct a string out
-//    of a mix of raw C strings, StringPieces, strings, and integer values.
+//    of a mix of raw C strings, string_views, strings, and integer values.
 // ----------------------------------------------------------------------
 
 // Append is merely a version of memcpy that returns the address of the byte
@@ -119,7 +119,7 @@
 }
 
 std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
-              const AlphaNum& d) {
+                   const AlphaNum& d) {
   std::string result;
   strings_internal::STLStringResizeUninitialized(
       &result, a.size() + b.size() + c.size() + d.size());
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h
index da9ed9a..cba8ceb 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -42,7 +42,6 @@
 // Floating point numbers are formatted with six-digit precision, which is
 // the default for "std::cout <<" or printf "%g" (the same as "%.6g").
 //
-//
 // You can convert to hexadecimal output rather than decimal output using the
 // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
 // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
@@ -78,8 +77,8 @@
 
 // Enum that specifies the number of significant digits to return in a `Hex` or
 // `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
-// would produce hexadecimal strings such as "0A","0F" and a 'kSpacePad5' value
-// would produce hexadecimal strings such as "    A","    F".
+// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
+// would produce hexadecimal strings such as "    a","    f".
 enum PadSpec : uint8_t {
   kNoPad = 1,
   kZeroPad2,
@@ -97,6 +96,10 @@
   kZeroPad14,
   kZeroPad15,
   kZeroPad16,
+  kZeroPad17,
+  kZeroPad18,
+  kZeroPad19,
+  kZeroPad20,
 
   kSpacePad2 = kZeroPad2 + 64,
   kSpacePad3,
@@ -113,6 +116,10 @@
   kSpacePad14,
   kSpacePad15,
   kSpacePad16,
+  kSpacePad17,
+  kSpacePad18,
+  kSpacePad19,
+  kSpacePad20,
 };
 
 // -----------------------------------------------------------------------------
@@ -237,6 +244,7 @@
 
   AlphaNum(const char* c_str) : piece_(c_str) {}  // NOLINT(runtime/explicit)
   AlphaNum(absl::string_view pc) : piece_(pc) {}  // NOLINT(runtime/explicit)
+
   template <typename Allocator>
   AlphaNum(  // NOLINT(runtime/explicit)
       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
@@ -309,16 +317,15 @@
 
 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                   const AlphaNum& c);
+                                        const AlphaNum& c);
 ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                   const AlphaNum& c, const AlphaNum& d);
+                                        const AlphaNum& c, const AlphaNum& d);
 
 // Support 5 or more arguments
 template <typename... AV>
-ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                          const AlphaNum& c, const AlphaNum& d,
-                                          const AlphaNum& e,
-                                          const AV&... args) {
+ABSL_MUST_USE_RESULT inline std::string StrCat(
+    const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
+    const AlphaNum& e, const AV&... args) {
   return strings_internal::CatPieces(
       {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
        static_cast<const AlphaNum&>(args).Piece()...});
@@ -336,18 +343,18 @@
 // not try to check each of its input arguments to be sure that they are not
 // a subset of the string being appended to. That is, while this will work:
 //
-//   string s = "foo";
+//   std::string s = "foo";
 //   s += s;
 //
 // This output is undefined:
 //
-//   string s = "foo";
+//   std::string s = "foo";
 //   StrAppend(&s, s);
 //
 // This output is undefined as well, since `absl::string_view` does not own its
 // data:
 //
-//   string s = "foobar";
+//   std::string s = "foobar";
 //   absl::string_view p = s;
 //   StrAppend(&s, p);
 
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index b6df9e3..14c63b3 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/str_cat_test.cc b/absl/strings/str_cat_test.cc
index 555d8db..beb15fa 100644
--- a/absl/strings/str_cat_test.cc
+++ b/absl/strings/str_cat_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -106,11 +106,7 @@
 TEST(StrCat, Basics) {
   std::string result;
 
-  std::string strs[] = {
-    "Hello",
-    "Cruel",
-    "World"
-  };
+  std::string strs[] = {"Hello", "Cruel", "World"};
 
   std::string stdstrs[] = {
     "std::Hello",
@@ -164,9 +160,10 @@
   result = absl::StrCat(ui64s[0], ", ", ui64s[1], "!");
   EXPECT_EQ(result, "12345678910, 10987654321!");
 
-  std::string one = "1";  // Actually, it's the size of this std::string that we want; a
-                     // 64-bit build distinguishes between size_t and uint64_t,
-                     // even though they're both unsigned 64-bit values.
+  std::string one =
+      "1";  // Actually, it's the size of this std::string that we want; a
+            // 64-bit build distinguishes between size_t and uint64_t,
+            // even though they're both unsigned 64-bit values.
   result = absl::StrCat("And a ", one.size(), " and a ",
                         &result[2] - &result[0], " and a ", one, " 2 3 4", "!");
   EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
@@ -306,11 +303,7 @@
 TEST(StrAppend, Basics) {
   std::string result = "existing text";
 
-  std::string strs[] = {
-    "Hello",
-    "Cruel",
-    "World"
-  };
+  std::string strs[] = {"Hello", "Cruel", "World"};
 
   std::string stdstrs[] = {
     "std::Hello",
@@ -365,9 +358,10 @@
   absl::StrAppend(&result, ui64s[0], ", ", ui64s[1], "!");
   EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!");
 
-  std::string one = "1";  // Actually, it's the size of this std::string that we want; a
-                     // 64-bit build distinguishes between size_t and uint64_t,
-                     // even though they're both unsigned 64-bit values.
+  std::string one =
+      "1";  // Actually, it's the size of this std::string that we want; a
+            // 64-bit build distinguishes between size_t and uint64_t,
+            // even though they're both unsigned 64-bit values.
   old_size = result.size();
   absl::StrAppend(&result, "And a ", one.size(), " and a ",
                   &result[2] - &result[0], " and a ", one, " 2 3 4", "!");
@@ -427,7 +421,7 @@
   snprintf(expected, sizeof(expected), nopad_format, v);
   EXPECT_EQ(expected, actual) << " decimal value " << v;
 
-  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad16; ++spec) {
+  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), zeropad_format,
@@ -435,7 +429,7 @@
     EXPECT_EQ(expected, actual) << " decimal value " << v;
   }
 
-  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad16; ++spec) {
+  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Hex(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), spacepad_format,
@@ -453,7 +447,7 @@
   snprintf(expected, sizeof(expected), nopad_format, v);
   EXPECT_EQ(expected, actual) << " decimal value " << v;
 
-  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad16; ++spec) {
+  for (int spec = absl::kZeroPad2; spec <= absl::kZeroPad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), zeropad_format,
@@ -463,7 +457,7 @@
         << "' digits " << (spec - absl::kZeroPad2 + 2);
   }
 
-  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad16; ++spec) {
+  for (int spec = absl::kSpacePad2; spec <= absl::kSpacePad20; ++spec) {
     std::string actual =
         absl::StrCat(absl::Dec(v, static_cast<absl::PadSpec>(spec)));
     snprintf(expected, sizeof(expected), spacepad_format,
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 2d07725..539d951 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -24,7 +24,8 @@
 //
 // Example:
 //
-//   string s = absl::StrFormat("%s %s You have $%d!", "Hello", name, dollars);
+//   std::string s = absl::StrFormat(
+//                      "%s %s You have $%d!", "Hello", name, dollars);
 //
 // The library consists of the following basic utilities:
 //
@@ -89,7 +90,7 @@
 // Example:
 //
 //   absl::UntypedFormatSpec format("%d");
-//   string out;
+//   std::string out;
 //   CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)}));
 class UntypedFormatSpec {
  public:
@@ -135,8 +136,8 @@
 // Example:
 //
 //   int n = 0;
-//   string s = absl::StrFormat("%s%d%n", "hello", 123,
-//                   absl::FormatCountCapture(&n));
+//   std::string s = absl::StrFormat("%s%d%n", "hello", 123,
+//                       absl::FormatCountCapture(&n));
 //   EXPECT_EQ(8, n);
 class FormatCountCapture {
  public:
@@ -186,7 +187,7 @@
 // A format string generally follows the POSIX syntax as used within the POSIX
 // `printf` specification.
 //
-// (See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html.)
+// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.)
 //
 // In specific, the `FormatSpec` supports the following type specifiers:
 //   * `c` for characters
@@ -223,7 +224,7 @@
 //     "%p", *int               -> "0x7ffdeb6ad2a4"
 //
 //     int n = 0;
-//     string s = absl::StrFormat(
+//     std::string s = absl::StrFormat(
 //         "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));
 //     EXPECT_EQ(8, n);
 //
@@ -290,14 +291,14 @@
 //
 // Example:
 //
-//   string s = absl::StrFormat(
+//   std::string s = absl::StrFormat(
 //       "Welcome to %s, Number %d!", "The Village", 6);
 //   EXPECT_EQ("Welcome to The Village, Number 6!", s);
 //
 // Returns an empty string in case of error.
 template <typename... Args>
 ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
-                                      const Args&... args) {
+                                           const Args&... args) {
   return str_format_internal::FormatPack(
       str_format_internal::UntypedFormatSpecImpl::Extract(format),
       {str_format_internal::FormatArgImpl(args)...});
@@ -311,11 +312,12 @@
 //
 // Example:
 //
-//   string orig("For example PI is approximately ");
+//   std::string orig("For example PI is approximately ");
 //   std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
 template <typename... Args>
-std::string& StrAppendFormat(std::string* dst, const FormatSpec<Args...>& format,
-                        const Args&... args) {
+std::string& StrAppendFormat(std::string* dst,
+                             const FormatSpec<Args...>& format,
+                             const Args&... args) {
   return str_format_internal::AppendPack(
       dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
       {str_format_internal::FormatArgImpl(args)...});
@@ -434,7 +436,8 @@
 // `absl::FormatRawSink` interface), using a format string and zero or more
 // additional arguments.
 //
-// By default, `string` and `std::ostream` are supported as destination objects.
+// By default, `std::string` and `std::ostream` are supported as destination
+// objects.
 //
 // `absl::Format()` is a generic version of `absl::StrFormat(), for custom
 // sinks. The format string, like format strings for `StrFormat()`, is checked
@@ -483,9 +486,10 @@
 //
 // Example:
 //
-//   std::optional<string> FormatDynamic(const string& in_format,
-//                                       const vector<string>& in_args) {
-//     string out;
+//   std::optional<std::string> FormatDynamic(
+//       const std::string& in_format,
+//       const vector<std::string>& in_args) {
+//     std::string out;
 //     std::vector<absl::FormatArg> args;
 //     for (const auto& v : in_args) {
 //       // It is important that 'v' is a reference to the objects in in_args.
@@ -509,4 +513,5 @@
 }
 
 }  // namespace absl
+
 #endif  // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index aa14e21..d4cffa0 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -242,6 +242,7 @@
   std::string ReadFile() {
     std::fseek(file_, 0, SEEK_END);
     int size = std::ftell(file_);
+    EXPECT_GT(size, 0);
     std::rewind(file_);
     std::string str(2 * size, ' ');
     int read_bytes = std::fread(&str[0], 1, str.size(), file_);
@@ -270,7 +271,7 @@
   EXPECT_EQ(errno, EBADF);
 }
 
-#if __GNUC__
+#if __GLIBC__
 TEST_F(FormatEntryPointTest, FprintfTooLarge) {
   std::FILE* f = std::fopen("/dev/null", "w");
   int width = 2000000000;
@@ -297,7 +298,7 @@
   EXPECT_EQ(result, 30);
   EXPECT_EQ(tmp.ReadFile(), "STRING: ABC NUMBER: -000000019");
 }
-#endif  // __GNUC__
+#endif  // __GLIBC__
 
 TEST_F(FormatEntryPointTest, SNPrintF) {
   char buffer[16];
@@ -340,7 +341,7 @@
   EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
   EXPECT_EQ(StrFormat("%c", long{'a'}), "a");  // NOLINT
   EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
-  //     "s" - std::string                  Eg: "C" -> "C", std::string("C++") -> "C++"
+  //     "s" - std::string       Eg: "C" -> "C", std::string("C++") -> "C++"
   //           Formats std::string, char*, string_view, and Cord.
   EXPECT_EQ(StrFormat("%s", "C"), "C");
   EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
@@ -605,35 +606,21 @@
 // Some codegen thunks that we can use to easily dump the generated assembly for
 // different StrFormat calls.
 
-inline std::string CodegenAbslStrFormatInt(int i) {
+std::string CodegenAbslStrFormatInt(int i) {  // NOLINT
   return absl::StrFormat("%d", i);
 }
 
-inline std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
-                                                 int64_t i64) {
+std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
+                                               int64_t i64) {  // NOLINT
   return absl::StrFormat("%d %s %d", i, s, i64);
 }
 
-inline void CodegenAbslStrAppendFormatInt(std::string* out, int i) {
+void CodegenAbslStrAppendFormatInt(std::string* out, int i) {  // NOLINT
   absl::StrAppendFormat(out, "%d", i);
 }
 
-inline void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
-                                                     const std::string& s,
-                                                     int64_t i64) {
+void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
+                                              const std::string& s,
+                                              int64_t i64) {  // NOLINT
   absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
 }
-
-auto absl_internal_str_format_force_codegen_funcs = std::make_tuple(
-    CodegenAbslStrFormatInt, CodegenAbslStrFormatIntStringInt64,
-    CodegenAbslStrAppendFormatInt, CodegenAbslStrAppendFormatIntStringInt64);
-
-bool absl_internal_str_format_force_codegen_always_false;
-// Force the compiler to generate the functions by making it look like we
-// escape the function pointers.
-// It can't statically know that
-// absl_internal_str_format_force_codegen_always_false is not changed by someone
-// else.
-bool absl_internal_str_format_force_codegen =
-    absl_internal_str_format_force_codegen_always_false &&
-    printf("%p", &absl_internal_str_format_force_codegen_funcs) == 0;
diff --git a/absl/strings/str_join.h b/absl/strings/str_join.h
index f9611ad..7345b96 100644
--- a/absl/strings/str_join.h
+++ b/absl/strings/str_join.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -18,13 +18,13 @@
 // -----------------------------------------------------------------------------
 //
 // This header file contains functions for joining a range of elements and
-// returning the result as a string. StrJoin operations are specified by passing
-// a range, a separator string to use between the elements joined, and an
-// optional Formatter responsible for converting each argument in the range to a
-// string. If omitted, a default `AlphaNumFormatter()` is called on the elements
-// to be joined, using the same formatting that `absl::StrCat()` uses. This
-// package defines a number of default formatters, and you can define your own
-// implementations.
+// returning the result as a std::string. StrJoin operations are specified by
+// passing a range, a separator string to use between the elements joined, and
+// an optional Formatter responsible for converting each argument in the range
+// to a string. If omitted, a default `AlphaNumFormatter()` is called on the
+// elements to be joined, using the same formatting that `absl::StrCat()` uses.
+// This package defines a number of default formatters, and you can define your
+// own implementations.
 //
 // Ranges are specified by passing a container with `std::begin()` and
 // `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
@@ -37,8 +37,8 @@
 //
 // Example:
 //
-//   std::vector<string> v = {"foo", "bar", "baz"};
-//   string s = absl::StrJoin(v, "-");
+//   std::vector<std::string> v = {"foo", "bar", "baz"};
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
 //
 // See comments on the `absl::StrJoin()` function for more examples.
@@ -66,16 +66,16 @@
 // -----------------------------------------------------------------------------
 //
 // A Formatter is a function object that is responsible for formatting its
-// argument as a string and appending it to a given output string. Formatters
-// may be implemented as function objects, lambdas, or normal functions. You may
-// provide your own Formatter to enable `absl::StrJoin()` to work with arbitrary
-// types.
+// argument as a string and appending it to a given output std::string.
+// Formatters may be implemented as function objects, lambdas, or normal
+// functions. You may provide your own Formatter to enable `absl::StrJoin()` to
+// work with arbitrary types.
 //
 // The following is an example of a custom Formatter that simply uses
-// `std::to_string()` to format an integer as a string.
+// `std::to_string()` to format an integer as a std::string.
 //
 //   struct MyFormatter {
-//     void operator()(string* out, int i) const {
+//     void operator()(std::string* out, int i) const {
 //       out->append(std::to_string(i));
 //     }
 //   };
@@ -84,7 +84,7 @@
 // argument to `absl::StrJoin()`:
 //
 //   std::vector<int> v = {1, 2, 3, 4};
-//   string s = absl::StrJoin(v, "-", MyFormatter());
+//   std::string s = absl::StrJoin(v, "-", MyFormatter());
 //   EXPECT_EQ("1-2-3-4", s);
 //
 // The following standard formatters are provided within this file:
@@ -156,7 +156,7 @@
 // StrJoin()
 // -----------------------------------------------------------------------------
 //
-// Joins a range of elements and returns the result as a string.
+// Joins a range of elements and returns the result as a std::string.
 // `absl::StrJoin()` takes a range, a separator string to use between the
 // elements joined, and an optional Formatter responsible for converting each
 // argument in the range to a string.
@@ -167,22 +167,22 @@
 // Example 1:
 //   // Joins a collection of strings. This pattern also works with a collection
 //   // of `absl::string_view` or even `const char*`.
-//   std::vector<string> v = {"foo", "bar", "baz"};
-//   string s = absl::StrJoin(v, "-");
+//   std::vector<std::string> v = {"foo", "bar", "baz"};
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
 //
 // Example 2:
 //   // Joins the values in the given `std::initializer_list<>` specified using
 //   // brace initialization. This pattern also works with an initializer_list
 //   // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
-//   string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
+//   std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
 //   EXPECT_EQ("foo-bar-baz", s);
 //
 // Example 3:
 //   // Joins a collection of ints. This pattern also works with floats,
 //   // doubles, int64s -- any `StrCat()`-compatible type.
 //   std::vector<int> v = {1, 2, 3, -4};
-//   string s = absl::StrJoin(v, "-");
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("1-2-3--4", s);
 //
 // Example 4:
@@ -193,7 +193,7 @@
 //   // `std::vector<int*>`.
 //   int x = 1, y = 2, z = 3;
 //   std::vector<int*> v = {&x, &y, &z};
-//   string s = absl::StrJoin(v, "-");
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("1-2-3", s);
 //
 // Example 5:
@@ -202,53 +202,53 @@
 //   v.emplace_back(new int(1));
 //   v.emplace_back(new int(2));
 //   v.emplace_back(new int(3));
-//   string s = absl::StrJoin(v, "-");
+//   std::string s = absl::StrJoin(v, "-");
 //   EXPECT_EQ("1-2-3", s);
 //
 // Example 6:
 //   // Joins a `std::map`, with each key-value pair separated by an equals
 //   // sign. This pattern would also work with, say, a
 //   // `std::vector<std::pair<>>`.
-//   std::map<string, int> m = {
+//   std::map<std::string, int> m = {
 //       std::make_pair("a", 1),
 //       std::make_pair("b", 2),
 //       std::make_pair("c", 3)};
-//   string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
+//   std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
 //   EXPECT_EQ("a=1,b=2,c=3", s);
 //
 // Example 7:
 //   // These examples show how `absl::StrJoin()` handles a few common edge
 //   // cases:
-//   std::vector<string> v_empty;
+//   std::vector<std::string> v_empty;
 //   EXPECT_EQ("", absl::StrJoin(v_empty, "-"));
 //
-//   std::vector<string> v_one_item = {"foo"};
+//   std::vector<std::string> v_one_item = {"foo"};
 //   EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-"));
 //
-//   std::vector<string> v_empty_string = {""};
+//   std::vector<std::string> v_empty_string = {""};
 //   EXPECT_EQ("", absl::StrJoin(v_empty_string, "-"));
 //
-//   std::vector<string> v_one_item_empty_string = {"a", ""};
+//   std::vector<std::string> v_one_item_empty_string = {"a", ""};
 //   EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-"));
 //
-//   std::vector<string> v_two_empty_string = {"", ""};
+//   std::vector<std::string> v_two_empty_string = {"", ""};
 //   EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-"));
 //
 // Example 8:
 //   // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
-//   // a string using the `absl::AlphaNum` class.
-//   string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
+//   // a std::string using the `absl::AlphaNum` class.
+//   std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
 //   EXPECT_EQ("123-abc-0.456", s);
 
 template <typename Iterator, typename Formatter>
 std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
-               Formatter&& fmt) {
+                    Formatter&& fmt) {
   return strings_internal::JoinAlgorithm(start, end, sep, fmt);
 }
 
 template <typename Range, typename Formatter>
 std::string StrJoin(const Range& range, absl::string_view separator,
-               Formatter&& fmt) {
+                    Formatter&& fmt) {
   return strings_internal::JoinRange(range, separator, fmt);
 }
 
@@ -260,7 +260,7 @@
 
 template <typename... T, typename Formatter>
 std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
-               Formatter&& fmt) {
+                    Formatter&& fmt) {
   return strings_internal::JoinAlgorithm(value, separator, fmt);
 }
 
@@ -280,7 +280,8 @@
 }
 
 template <typename... T>
-std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator) {
+std::string StrJoin(const std::tuple<T...>& value,
+                    absl::string_view separator) {
   return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
 }
 
diff --git a/absl/strings/str_join_benchmark.cc b/absl/strings/str_join_benchmark.cc
index 7fb0e49..d6f689f 100644
--- a/absl/strings/str_join_benchmark.cc
+++ b/absl/strings/str_join_benchmark.cc
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -58,7 +58,8 @@
   const int string_len = state.range(0);
   const int num_pairs = state.range(1);
   const std::string s(string_len, 'x');
-  const std::vector<std::pair<std::string, int>> v(num_pairs, std::make_pair(s, 42));
+  const std::vector<std::pair<std::string, int>> v(num_pairs,
+                                                   std::make_pair(s, 42));
   for (auto _ : state) {
     std::string s = absl::StrJoin(v, ",", absl::PairFormatter("="));
     benchmark::DoNotOptimize(s);
diff --git a/absl/strings/str_join_test.cc b/absl/strings/str_join_test.cc
index c941f9c..921d9c2 100644
--- a/absl/strings/str_join_test.cc
+++ b/absl/strings/str_join_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -118,7 +118,7 @@
 
   {
     // A std::map, which is a collection of std::pair<>s.
-    std::map<std::string, int> m = { {"a", 1}, {"b", 2}, {"c", 3} };
+    std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
     EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
   }
 
@@ -140,7 +140,8 @@
   }
 
   {
-    // A range of 1 element gives a std::string with that element but no separator.
+    // A range of 1 element gives a std::string with that element but no
+    // separator.
     std::vector<std::string> v = {"foo"};
     EXPECT_EQ("foo", absl::StrJoin(v, "-"));
   }
@@ -173,9 +174,10 @@
 TEST(StrJoin, CustomFormatter) {
   std::vector<std::string> v{"One", "Two", "Three"};
   {
-    std::string joined = absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
-      absl::StrAppend(out, "(", in, ")");
-    });
+    std::string joined =
+        absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
+          absl::StrAppend(out, "(", in, ")");
+        });
     EXPECT_EQ("(One)(Two)(Three)", joined);
   }
   {
diff --git a/absl/strings/str_replace.cc b/absl/strings/str_replace.cc
index 69efa35..280f63d 100644
--- a/absl/strings/str_replace.cc
+++ b/absl/strings/str_replace.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -68,11 +68,12 @@
 // aren't inlined.
 
 std::string StrReplaceAll(absl::string_view s,
-                     strings_internal::FixedMapping replacements) {
+                          strings_internal::FixedMapping replacements) {
   return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
 }
 
-int StrReplaceAll(strings_internal::FixedMapping replacements, std::string* target) {
+int StrReplaceAll(strings_internal::FixedMapping replacements,
+                  std::string* target) {
   return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
 }
 
diff --git a/absl/strings/str_replace.h b/absl/strings/str_replace.h
index 3bfe4c6..30540d0 100644
--- a/absl/strings/str_replace.h
+++ b/absl/strings/str_replace.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -29,12 +29,12 @@
 //
 // Example:
 //
-// string html_escaped = absl::StrReplaceAll(user_input, {
-//                                           {"&", "&amp;"},
-//                                           {"<", "&lt;"},
-//                                           {">", "&gt;"},
-//                                           {"\"", "&quot;"},
-//                                           {"'", "&#39;"}});
+// std::string html_escaped = absl::StrReplaceAll(user_input, {
+//                                                {"&", "&amp;"},
+//                                                {"<", "&lt;"},
+//                                                {">", "&gt;"},
+//                                                {"\"", "&quot;"},
+//                                                {"'", "&#39;"}});
 #ifndef ABSL_STRINGS_STR_REPLACE_H_
 #define ABSL_STRINGS_STR_REPLACE_H_
 
@@ -58,10 +58,11 @@
 //
 // Example:
 //
-//   string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-//                                  {{"$count", absl::StrCat(5)},
-//                                   {"$who", "Bob"},
-//                                   {"#Noun", "Apples"}});
+//   std::string s = absl::StrReplaceAll(
+//       "$who bought $count #Noun. Thanks $who!",
+//       {{"$count", absl::StrCat(5)},
+//        {"$who", "Bob"},
+//        {"#Noun", "Apples"}});
 //   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
 ABSL_MUST_USE_RESULT std::string StrReplaceAll(
     absl::string_view s,
@@ -78,20 +79,22 @@
 //   replacements["$who"] = "Bob";
 //   replacements["$count"] = "5";
 //   replacements["#Noun"] = "Apples";
-//   string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-//                                  replacements);
+//   std::string s = absl::StrReplaceAll(
+//       "$who bought $count #Noun. Thanks $who!",
+//       replacements);
 //   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
 //
 //   // A std::vector of std::pair elements can be more efficient.
-//   std::vector<std::pair<const absl::string_view, string>> replacements;
+//   std::vector<std::pair<const absl::string_view, std::string>> replacements;
 //   replacements.push_back({"&", "&amp;"});
 //   replacements.push_back({"<", "&lt;"});
 //   replacements.push_back({">", "&gt;"});
-//   string s = absl::StrReplaceAll("if (ptr < &foo)",
+//   std::string s = absl::StrReplaceAll("if (ptr < &foo)",
 //                                  replacements);
 //   EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
 template <typename StrToStrMapping>
-std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements);
+std::string StrReplaceAll(absl::string_view s,
+                          const StrToStrMapping& replacements);
 
 // Overload of `StrReplaceAll()` to replace character sequences within a given
 // output string *in place* with replacements provided within an initializer
@@ -99,7 +102,7 @@
 //
 // Example:
 //
-//   string s = std::string("$who bought $count #Noun. Thanks $who!");
+//   std::string s = std::string("$who bought $count #Noun. Thanks $who!");
 //   int count;
 //   count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
 //                               {"$who", "Bob"},
@@ -117,7 +120,7 @@
 //
 // Example:
 //
-//   string s = std::string("if (ptr < &foo)");
+//   std::string s = std::string("if (ptr < &foo)");
 //   int count = absl::StrReplaceAll({{"&", "&amp;"},
 //                                    {"<", "&lt;"},
 //                                    {">", "&gt;"}}, &s);
@@ -187,7 +190,8 @@
 }  // namespace strings_internal
 
 template <typename StrToStrMapping>
-std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements) {
+std::string StrReplaceAll(absl::string_view s,
+                          const StrToStrMapping& replacements) {
   auto subs = strings_internal::FindSubstitutions(s, replacements);
   std::string result;
   result.reserve(s.size());
diff --git a/absl/strings/str_replace_benchmark.cc b/absl/strings/str_replace_benchmark.cc
index 8386f2e..95b2dc1 100644
--- a/absl/strings/str_replace_benchmark.cc
+++ b/absl/strings/str_replace_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -54,7 +54,7 @@
     size_t r = 0;
     big_string = new std::string(1000 * 1000, ' ');
     for (std::string phrase : {"the quick brown fox jumped over the lazy dogs",
-                          "pack my box with the five dozen liquor jugs"}) {
+                               "pack my box with the five dozen liquor jugs"}) {
       for (int i = 0; i < 10 * 1000; ++i) {
         r = r * 237 + 41;  // not very random.
         memcpy(&(*big_string)[r % (big_string->size() - phrase.size())],
@@ -108,11 +108,11 @@
   std::string src = *big_string;
   for (auto _ : state) {
     std::string dest = absl::StrReplaceAll(src, {{"the", "box"},
-                                            {"brown", "quick"},
-                                            {"jumped", "liquored"},
-                                            {"dozen", "brown"},
-                                            {"lazy", "pack"},
-                                            {"liquor", "shakes"}});
+                                                 {"brown", "quick"},
+                                                 {"jumped", "liquored"},
+                                                 {"dozen", "brown"},
+                                                 {"lazy", "pack"},
+                                                 {"liquor", "shakes"}});
     ABSL_RAW_CHECK(dest == *after_replacing_many,
                    "not benchmarking intended behavior");
   }
diff --git a/absl/strings/str_replace_test.cc b/absl/strings/str_replace_test.cc
index 5d003a2..1ca23af 100644
--- a/absl/strings/str_replace_test.cc
+++ b/absl/strings/str_replace_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -148,7 +148,7 @@
   replacements["$count"] = "5";
   replacements["#Noun"] = "Apples";
   std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-                                 replacements);
+                                      replacements);
   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
 }
 
diff --git a/absl/strings/str_split.cc b/absl/strings/str_split.cc
index 0a68c52..2593130 100644
--- a/absl/strings/str_split.cc
+++ b/absl/strings/str_split.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h
index c7eb280..7333078 100644
--- a/absl/strings/str_split.h
+++ b/absl/strings/str_split.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -71,23 +71,23 @@
 //   - `ByLength`
 //   - `MaxSplits`
 //
+// A Delimiter's `Find()` member function will be passed an input `text` that is
+// to be split and a position (`pos`) to begin searching for the next delimiter
+// in `text`. The returned absl::string_view should refer to the next occurrence
+// (after `pos`) of the represented delimiter; this returned absl::string_view
+// represents the next location where the input `text` should be broken.
 //
-// A Delimiter's Find() member function will be passed the input text that is to
-// be split and the position to begin searching for the next delimiter in the
-// input text. The returned absl::string_view should refer to the next
-// occurrence (after pos) of the represented delimiter; this returned
-// absl::string_view represents the next location where the input string should
-// be broken. The returned absl::string_view may be zero-length if the Delimiter
-// does not represent a part of the string (e.g., a fixed-length delimiter). If
-// no delimiter is found in the given text, a zero-length absl::string_view
-// referring to text.end() should be returned (e.g.,
-// absl::string_view(text.end(), 0)). It is important that the returned
-// absl::string_view always be within the bounds of input text given as an
+// The returned absl::string_view may be zero-length if the Delimiter does not
+// represent a part of the string (e.g., a fixed-length delimiter). If no
+// delimiter is found in the input `text`, a zero-length absl::string_view
+// referring to `text.end()` should be returned (e.g.,
+// `text.substr(text.size())`). It is important that the returned
+// absl::string_view always be within the bounds of the input `text` given as an
 // argument--it must not refer to a string that is physically located outside of
 // the given string.
 //
 // The following example is a simple Delimiter object that is created with a
-// single char and will look for that char in the text passed to the Find()
+// single char and will look for that char in the text passed to the `Find()`
 // function:
 //
 //   struct SimpleDelimiter {
@@ -96,9 +96,9 @@
 //     absl::string_view Find(absl::string_view text, size_t pos) {
 //       auto found = text.find(c_, pos);
 //       if (found == absl::string_view::npos)
-//         return absl::string_view(text.end(), 0);
+//         return text.substr(text.size());
 //
-//       return absl::string_view(text, found, 1);
+//       return text.substr(found, 1);
 //     }
 //   };
 
@@ -131,8 +131,7 @@
 // ByChar
 //
 // A single character delimiter. `ByChar` is functionally equivalent to a
-// 1-char string within a `ByString` delimiter, but slightly more
-// efficient.
+// 1-char string within a `ByString` delimiter, but slightly more efficient.
 //
 // Example:
 //
@@ -413,10 +412,10 @@
 //
 // The `StrSplit()` function adapts the returned collection to the collection
 // specified by the caller (e.g. `std::vector` above). The returned collections
-// may contain `string`, `absl::string_view` (in which case the original string
-// being split must ensure that it outlives the collection), or any object that
-// can be explicitly created from an `absl::string_view`. This behavior works
-// for:
+// may contain `std::string`, `absl::string_view` (in which case the original
+// string being split must ensure that it outlives the collection), or any
+// object that can be explicitly created from an `absl::string_view`. This
+// behavior works for:
 //
 // 1) All standard STL containers including `std::vector`, `std::list`,
 //    `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
@@ -460,7 +459,7 @@
 // Example:
 //
 //   // Stores first two split strings as the members in a std::pair.
-//   std::pair<string, string> p = absl::StrSplit("a,b,c", ',');
+//   std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
 //   // p.first == "a", p.second == "b"       // "c" is omitted.
 //
 // The `StrSplit()` function can be used multiple times to perform more
@@ -470,7 +469,7 @@
 //
 //   // The input string "a=b=c,d=e,f=,g" becomes
 //   // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
-//   std::map<string, string> m;
+//   std::map<std::string, std::string> m;
 //   for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) {
 //     m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));
 //   }
diff --git a/absl/strings/str_split_benchmark.cc b/absl/strings/str_split_benchmark.cc
index 326ff74..28c25e8 100644
--- a/absl/strings/str_split_benchmark.cc
+++ b/absl/strings/str_split_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -35,16 +35,16 @@
   return test;
 }
 
-void BM_Split2StringPiece(benchmark::State& state) {
+void BM_Split2StringView(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
   for (auto _ : state) {
     std::vector<absl::string_view> result = absl::StrSplit(test, ';');
     benchmark::DoNotOptimize(result);
   }
 }
-BENCHMARK_RANGE(BM_Split2StringPiece, 0, 1 << 20);
+BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20);
 
-void BM_Split2StringPieceLifted(benchmark::State& state) {
+void BM_Split2StringViewLifted(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
   std::vector<absl::string_view> result;
   for (auto _ : state) {
@@ -52,7 +52,7 @@
   }
   benchmark::DoNotOptimize(result);
 }
-BENCHMARK_RANGE(BM_Split2StringPieceLifted, 0, 1 << 20);
+BENCHMARK_RANGE(BM_Split2StringViewLifted, 0, 1 << 20);
 
 void BM_Split2String(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
@@ -69,7 +69,8 @@
 void BM_Split2SplitStringUsing(benchmark::State& state) {
   std::string test = MakeTestString(state.range(0));
   for (auto _ : state) {
-    std::vector<std::string> result = absl::StrSplit(test, ';', absl::SkipEmpty());
+    std::vector<std::string> result =
+        absl::StrSplit(test, ';', absl::SkipEmpty());
     benchmark::DoNotOptimize(result);
   }
 }
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index 413ad31..ef6400e 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -40,8 +40,8 @@
 TEST(Split, TraitsTest) {
   static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value,
                 "");
-  static_assert(!absl::strings_internal::SplitterIsConvertibleTo<std::string>::value,
-                "");
+  static_assert(
+      !absl::strings_internal::SplitterIsConvertibleTo<std::string>::value, "");
   static_assert(absl::strings_internal::SplitterIsConvertibleTo<
                     std::vector<std::string>>::value,
                 "");
@@ -182,7 +182,8 @@
   {
     // Uses the SkipWhitespace predicate.
     using absl::SkipWhitespace;
-    std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
+    std::vector<std::string> v =
+        absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
     EXPECT_THAT(v, ElementsAre(" a ", "b"));
   }
 
@@ -215,7 +216,8 @@
 
   {
     // Results stored in a std::multimap.
-    std::multimap<std::string, std::string> m = absl::StrSplit("a,1,b,2,a,3", ',');
+    std::multimap<std::string, std::string> m =
+        absl::StrSplit("a,1,b,2,a,3", ',');
     EXPECT_EQ(3, m.size());
     auto it = m.find("a");
     EXPECT_EQ("1", it->second);
@@ -271,7 +273,8 @@
   EXPECT_EQ("a", *it);  // tests dereference
   ++it;                 // tests preincrement
   EXPECT_NE(it, end);
-  EXPECT_EQ("b", std::string(it->data(), it->size()));  // tests dereference as ptr
+  EXPECT_EQ("b",
+            std::string(it->data(), it->size()));  // tests dereference as ptr
   it++;                                            // tests postincrement
   EXPECT_EQ(it, end);
 }
@@ -295,7 +298,8 @@
   EXPECT_EQ("a", *it);  // tests dereference
   ++it;                 // tests preincrement -- "b" should be skipped here.
   EXPECT_NE(it, end);
-  EXPECT_EQ("c", std::string(it->data(), it->size()));  // tests dereference as ptr
+  EXPECT_EQ("c",
+            std::string(it->data(), it->size()));  // tests dereference as ptr
   it++;                                            // tests postincrement
   EXPECT_EQ(it, end);
 }
@@ -421,10 +425,13 @@
   TestMapConversionOperator<std::map<std::string, std::string>>(splitter);
   TestMapConversionOperator<
       std::multimap<absl::string_view, absl::string_view>>(splitter);
-  TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(splitter);
-  TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(splitter);
+  TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(
+      splitter);
+  TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(
+      splitter);
   TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);
-  TestMapConversionOperator<std::unordered_map<std::string, std::string>>(splitter);
+  TestMapConversionOperator<std::unordered_map<std::string, std::string>>(
+      splitter);
 
   // Tests conversion to std::pair
 
@@ -568,10 +575,9 @@
 }
 
 TEST(Split, Temporary) {
-  // Use a std::string longer than the small-std::string-optimization length, so that when
-  // the temporary is destroyed, if the splitter keeps a reference to the
-  // std::string's contents, it'll reference freed memory instead of just dead
-  // on-stack memory.
+  // Use a std::string longer than the SSO length, so that when the temporary is
+  // destroyed, if the splitter keeps a reference to the std::string's contents,
+  // it'll reference freed memory instead of just dead on-stack memory.
   const char input[] = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u";
   EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input))
       << "Input should be larger than fits on the stack.";
@@ -647,6 +653,11 @@
   }
 }
 
+#if !defined(__cpp_char8_t)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++2a-compat"
+#endif
 TEST(Split, UTF8) {
   // Tests splitting utf8 strings and utf8 delimiters.
   std::string utf8_string = u8"\u03BA\u1F79\u03C3\u03BC\u03B5";
@@ -673,6 +684,10 @@
     EXPECT_THAT(v, ElementsAre("Foo", u8"h\u00E4llo", u8"th\u4E1Ere"));
   }
 }
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif  // !defined(__cpp_char8_t)
 
 TEST(Split, EmptyStringDelimiter) {
   {
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
index 4ceeb6b..cb79d5d 100644
--- a/absl/strings/string_view.cc
+++ b/absl/strings/string_view.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -228,7 +228,7 @@
 // member definitions that are required by the C++ standard, resulting in
 // LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks
 // MSVC to choose only one definition for the symbol it decorates. See details
-// at http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
+// at https://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
 #ifdef _MSC_VER
 #define ABSL_STRING_VIEW_SELECTANY __declspec(selectany)
 #else
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 6bcd3c4..f8b2001 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -32,7 +32,7 @@
 
 #ifdef ABSL_HAVE_STD_STRING_VIEW
 
-#include <string_view>
+#include <string_view>  // IWYU pragma: export
 
 namespace absl {
 using std::string_view;
@@ -101,7 +101,6 @@
 // example, when splitting a string, `std::vector<absl::string_view>` is a
 // natural data type for the output.
 //
-//
 // 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
@@ -277,7 +276,7 @@
   // Checks if the `string_view` is empty (refers to no characters).
   constexpr bool empty() const noexcept { return length_ == 0; }
 
-  // std::string:view::operator[]
+  // string_view::operator[]
   //
   // Returns the ith element of an `string_view` using the array operator.
   // Note that this operator does not perform any bounds checking.
@@ -355,7 +354,7 @@
   string_view substr(size_type pos, size_type n = npos) const {
     if (ABSL_PREDICT_FALSE(pos > length_))
       base_internal::ThrowStdOutOfRange("absl::string_view::substr");
-    n = std::min(n, length_ - pos);
+    n = (std::min)(n, length_ - pos);
     return string_view(ptr_ + pos, n);
   }
 
@@ -368,7 +367,7 @@
   // on the respective sizes of the two `string_view`s to determine which is
   // smaller, equal, or greater.
   int compare(string_view x) const noexcept {
-    auto min_length = std::min(length_, x.length_);
+    auto min_length = (std::min)(length_, x.length_);
     if (min_length > 0) {
       int r = memcmp(ptr_, x.ptr_, min_length);
       if (r < 0) return -1;
@@ -490,7 +489,7 @@
 
  private:
   static constexpr size_type kMaxSize =
-      std::numeric_limits<difference_type>::max();
+      (std::numeric_limits<difference_type>::max)();
 
   static constexpr size_type CheckLengthInternal(size_type len) {
     return ABSL_ASSERT(len <= kMaxSize), len;
@@ -508,6 +507,7 @@
   if (len != y.size()) {
     return false;
   }
+
   return x.data() == y.data() || len <= 0 ||
          memcmp(x.data(), y.data(), len) == 0;
 }
@@ -517,7 +517,7 @@
 }
 
 inline bool operator<(string_view x, string_view y) noexcept {
-  auto min_size = std::min(x.size(), y.size());
+  auto min_size = (std::min)(x.size(), y.size());
   const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
   return (r < 0) || (r == 0 && x.size() < y.size());
 }
@@ -547,7 +547,7 @@
 // Provided because std::string_view::substr throws if `pos > size()`
 inline string_view ClippedSubstr(string_view s, size_t pos,
                                  size_t n = string_view::npos) {
-  pos = std::min(pos, static_cast<size_t>(s.size()));
+  pos = (std::min)(pos, static_cast<size_t>(s.size()));
   return s.substr(pos, n);
 }
 
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index fb46db1..46909cb 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -151,7 +151,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find("x");  // not present; length 1
+    benchmark::DoNotOptimize(s.find("x"));  // not present; length 1
   }
 }
 BENCHMARK(BM_find_string_view_len_one)->Range(1, 1 << 20);
@@ -160,7 +160,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find("xx");  // not present; length 2
+    benchmark::DoNotOptimize(s.find("xx"));  // not present; length 2
   }
 }
 BENCHMARK(BM_find_string_view_len_two)->Range(1, 1 << 20);
@@ -169,7 +169,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find('x');  // not present
+    benchmark::DoNotOptimize(s.find('x'));  // not present
   }
 }
 BENCHMARK(BM_find_one_char)->Range(1, 1 << 20);
@@ -178,7 +178,7 @@
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.rfind('x');  // not present
+    benchmark::DoNotOptimize(s.rfind('x'));  // not present
   }
 }
 BENCHMARK(BM_rfind_one_char)->Range(1, 1 << 20);
@@ -193,7 +193,7 @@
 
   absl::string_view s(haystack);
   for (auto _ : state) {
-    s.find_first_of(needle);
+    benchmark::DoNotOptimize(s.find_first_of(needle));
   }
 }
 
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index a94e822..f5acf1d 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -284,9 +284,10 @@
 }
 #undef COMPARE
 
-// Sadly, our users often confuse string::npos with absl::string_view::npos;
-// So much so that we test here that they are the same.  They need to
-// both be unsigned, and both be the maximum-valued integer of their type.
+// Sadly, our users often confuse std::string::npos with
+// absl::string_view::npos; So much so that we test here that they are the same.
+// They need to both be unsigned, and both be the maximum-valued integer of
+// their type.
 
 template <typename T>
 struct is_type {
@@ -678,9 +679,9 @@
   EXPECT_EQ(a.substr(23, absl::string_view::npos), c);
   // throw exception
 #ifdef ABSL_HAVE_EXCEPTIONS
-  EXPECT_THROW(a.substr(99, 2), std::out_of_range);
+  EXPECT_THROW((void)a.substr(99, 2), std::out_of_range);
 #else
-  EXPECT_DEATH(a.substr(99, 2), "absl::string_view::substr");
+  EXPECT_DEATH((void)a.substr(99, 2), "absl::string_view::substr");
 #endif
 }
 
@@ -755,7 +756,6 @@
   std::string s1("123");
   s1 += '\0';
   s1 += "456";
-  absl::string_view b(s1);
   absl::string_view e;
   std::string s2;
 
@@ -995,8 +995,8 @@
 TEST(StringViewTest, Noexcept) {
   EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
                                              const std::string&>::value));
-  EXPECT_TRUE(
-      (std::is_nothrow_constructible<absl::string_view, const std::string&>::value));
+  EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
+                                             const std::string&>::value));
   EXPECT_TRUE(std::is_nothrow_constructible<absl::string_view>::value);
   constexpr absl::string_view sp;
   EXPECT_TRUE(noexcept(sp.begin()));
diff --git a/absl/strings/strip.h b/absl/strings/strip.h
index 8d0d7c6..e1341e0 100644
--- a/absl/strings/strip.h
+++ b/absl/strings/strip.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/strip_test.cc b/absl/strings/strip_test.cc
index 40c4c60..e4e00cb 100644
--- a/absl/strings/strip_test.cc
+++ b/absl/strings/strip_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -27,9 +27,6 @@
 
 namespace {
 
-using testing::ElementsAre;
-using testing::IsEmpty;
-
 TEST(Strip, ConsumePrefixOneChar) {
   absl::string_view input("abc");
   EXPECT_TRUE(absl::ConsumePrefix(&input, "a"));
diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc
index 3b20059..bc17695 100644
--- a/absl/strings/substitute.cc
+++ b/absl/strings/substitute.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 4de7b4e..507bc4f 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -36,18 +36,17 @@
 // use at that location within the format string.
 //
 // Example 1:
-//   string s = Substitute("$1 purchased $0 $2. Thanks $1!",
-//                         5, "Bob", "Apples");
+//   std::string s = Substitute("$1 purchased $0 $2. Thanks $1!",
+//                              5, "Bob", "Apples");
 //   EXPECT_EQ("Bob purchased 5 Apples. Thanks Bob!", s);
 //
 // Example 2:
-//   string s = "Hi. ";
+//   std::string s = "Hi. ";
 //   SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
 //   EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
 //
-//
 // Supported types:
-//   * absl::string_view, string, const char* (null is equivalent to "")
+//   * absl::string_view, std::string, const char* (null is equivalent to "")
 //   * int32_t, int64_t, uint32_t, uint64
 //   * float, double
 //   * bool (Printed as "true" or "false")
@@ -456,7 +455,7 @@
 // Example:
 //  template <typename... Args>
 //  void VarMsg(absl::string_view format, const Args&... args) {
-//    string s = absl::Substitute(format, args...);
+//    std::string s = absl::Substitute(format, args...);
 
 ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
   std::string result;
@@ -574,70 +573,70 @@
                      "contains one of $1-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1)
+                       const substitute_internal::Arg& a1)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
                      "There were 2 substitution arguments given, but "
                      "this format std::string is either missing its $0/$1, or "
                      "contains one of $2-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
                      "There were 3 substitution arguments given, but "
                      "this format std::string is either missing its $0/$1/$2, or "
                      "contains one of $3-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
                      "There were 4 substitution arguments given, but "
                      "this format std::string is either missing its $0-$3, or "
                      "contains one of $4-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
                      "There were 5 substitution arguments given, but "
                      "this format std::string is either missing its $0-$4, or "
                      "contains one of $5-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4,
-                  const substitute_internal::Arg& a5)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4,
+                       const substitute_internal::Arg& a5)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
                      "There were 6 substitution arguments given, but "
                      "this format std::string is either missing its $0-$5, or "
                      "contains one of $6-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4,
-                  const substitute_internal::Arg& a5,
-                  const substitute_internal::Arg& a6)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4,
+                       const substitute_internal::Arg& a5,
+                       const substitute_internal::Arg& a6)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
                      "There were 7 substitution arguments given, but "
                      "this format std::string is either missing its $0-$6, or "
                      "contains one of $7-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
-                  const substitute_internal::Arg& a1,
-                  const substitute_internal::Arg& a2,
-                  const substitute_internal::Arg& a3,
-                  const substitute_internal::Arg& a4,
-                  const substitute_internal::Arg& a5,
-                  const substitute_internal::Arg& a6,
-                  const substitute_internal::Arg& a7)
+                       const substitute_internal::Arg& a1,
+                       const substitute_internal::Arg& a2,
+                       const substitute_internal::Arg& a3,
+                       const substitute_internal::Arg& a4,
+                       const substitute_internal::Arg& a5,
+                       const substitute_internal::Arg& a6,
+                       const substitute_internal::Arg& a7)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
                      "There were 8 substitution arguments given, but "
                      "this format std::string is either missing its $0-$7, or "
diff --git a/absl/strings/substitute_test.cc b/absl/strings/substitute_test.cc
index 144df01..f656890 100644
--- a/absl/strings/substitute_test.cc
+++ b/absl/strings/substitute_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index f52e9d4..5e69847 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -69,6 +69,10 @@
         "notification.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
+    linkopts = select({
+        "//absl:windows": [],
+        "//conditions:default": ["-pthread"],
+    }),
     deps = [
         ":graphcycles_internal",
         "//absl/base",
@@ -170,18 +174,31 @@
     ],
 )
 
-cc_test(
-    name = "mutex_benchmark",
+cc_library(
+    name = "mutex_benchmark_common",
+    testonly = 1,
     srcs = ["mutex_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
-    tags = ["benchmark"],
-    visibility = ["//visibility:private"],
+    visibility = [
+        "//absl/synchronization:__pkg__",
+    ],
     deps = [
         ":synchronization",
         ":thread_pool",
         "//absl/base",
         "@com_github_google_benchmark//:benchmark_main",
     ],
+    alwayslink = 1,
+)
+
+cc_binary(
+    name = "mutex_benchmark",
+    testonly = 1,
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":mutex_benchmark_common",
+    ],
 )
 
 cc_test(
@@ -232,10 +249,6 @@
         "lifetime_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
-    linkopts = select({
-        "//absl:windows": [],
-        "//conditions:default": ["-pthread"],
-    }),
     tags = ["no_test_ios_x86_64"],
     deps = [
         ":synchronization",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index de0d7b7..68473b7 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,142 +14,182 @@
 # limitations under the License.
 #
 
-list(APPEND SYNCHRONIZATION_PUBLIC_HEADERS
-  "barrier.h"
-  "blocking_counter.h"
-  "mutex.h"
-  "notification.h"
+absl_cc_library(
+  NAME
+    graphcycles_internal
+  HDRS
+    "internal/graphcycles.h"
+  SRCS
+    "internal/graphcycles.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::base_internal
+    absl::core_headers
+    absl::malloc_internal
 )
 
-
-list(APPEND SYNCHRONIZATION_INTERNAL_HEADERS
-  "internal/create_thread_identity.h"
-  "internal/graphcycles.h"
-  "internal/kernel_timeout.h"
-  "internal/per_thread_sem.h"
-  "internal/thread_pool.h"
-  "internal/waiter.h"
-)
-
-
-
-# synchronization library
-list(APPEND SYNCHRONIZATION_SRC
-  "barrier.cc"
-  "blocking_counter.cc"
-  "internal/create_thread_identity.cc"
-  "internal/per_thread_sem.cc"
-  "internal/waiter.cc"
-  "internal/graphcycles.cc"
-  "notification.cc"
-  "mutex.cc"
-)
-
-set(SYNCHRONIZATION_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::symbolize absl::time)
-
-absl_library(
-  TARGET
-    absl_synchronization
-  SOURCES
-    ${SYNCHRONIZATION_SRC}
-  PUBLIC_LIBRARIES
-    ${SYNCHRONIZATION_PUBLIC_LIBRARIES}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     synchronization
+  HDRS
+    "barrier.h"
+    "blocking_counter.h"
+    "internal/create_thread_identity.h"
+    "internal/kernel_timeout.h"
+    "internal/mutex_nonprod.inc"
+    "internal/per_thread_sem.h"
+    "internal/waiter.h"
+    "mutex.h"
+    "notification.h"
+  SRCS
+    "barrier.cc"
+    "blocking_counter.cc"
+    "internal/create_thread_identity.cc"
+    "internal/per_thread_sem.cc"
+    "internal/waiter.cc"
+    "notification.cc"
+    "mutex.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::graphcycles_internal
+    absl::base
+    absl::base_internal
+    absl::config
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::malloc_internal
+    absl::stacktrace
+    absl::symbolize
+    absl::time
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-
-# test barrier_test
-set(BARRIER_TEST_SRC "barrier_test.cc")
-set(BARRIER_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     barrier_test
-  SOURCES
-    ${BARRIER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${BARRIER_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "barrier_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::time
+    gmock_main
 )
 
-
-# test blocking_counter_test
-set(BLOCKING_COUNTER_TEST_SRC "blocking_counter_test.cc")
-set(BLOCKING_COUNTER_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     blocking_counter_test
-  SOURCES
-    ${BLOCKING_COUNTER_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${BLOCKING_COUNTER_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "blocking_counter_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::time
+    gmock_main
 )
 
-
-# test graphcycles_test
-set(GRAPHCYCLES_TEST_SRC "internal/graphcycles_test.cc")
-set(GRAPHCYCLES_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     graphcycles_test
-  SOURCES
-    ${GRAPHCYCLES_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${GRAPHCYCLES_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/graphcycles_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::graphcycles_internal
+    absl::base
+    absl::core_headers
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    thread_pool
+  HDRS
+    "internal/thread_pool.h"
+  DEPS
+    absl::synchronization
+    absl::core_headers
+  TESTONLY
+)
 
-# test mutex_test
-set(MUTEX_TEST_SRC "mutex_test.cc")
-set(MUTEX_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     mutex_test
-  SOURCES
-    ${MUTEX_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${MUTEX_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "mutex_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::thread_pool
+    absl::base
+    absl::core_headers
+    absl::memory
+    absl::time
+    gmock_main
 )
 
-
-# test notification_test
-set(NOTIFICATION_TEST_SRC "notification_test.cc")
-set(NOTIFICATION_TEST_PUBLIC_LIBRARIES absl::synchronization)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     notification_test
-  SOURCES
-    ${NOTIFICATION_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${NOTIFICATION_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "notification_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::time
+    gmock_main
 )
 
-
-# test per_thread_sem_test_common
-set(PER_THREAD_SEM_TEST_COMMON_SRC "internal/per_thread_sem_test.cc")
-set(PER_THREAD_SEM_TEST_COMMON_PUBLIC_LIBRARIES absl::synchronization absl::strings)
-
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
     per_thread_sem_test_common
-  SOURCES
-    ${PER_THREAD_SEM_TEST_COMMON_SRC}
-  PUBLIC_LIBRARIES
-    ${PER_THREAD_SEM_TEST_COMMON_PUBLIC_LIBRARIES}
+  SRCS
+    "internal/per_thread_sem_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::base
+    absl::strings
+    absl::time
+    gmock
+  TESTONLY
 )
 
+absl_cc_test(
+  NAME
+    per_thread_sem_test
+  SRCS
+    "internal/per_thread_sem_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::per_thread_sem_test_common
+    absl::synchronization
+    absl::base
+    absl::strings
+    absl::time
+    gmock_main
+)
 
-
-
-
-
-
+absl_cc_test(
+  NAME
+    lifetime_test
+  SRCS
+    "lifetime_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::synchronization
+    absl::base
+    absl::core_headers
+    Threads::Threads
+)
diff --git a/absl/synchronization/barrier.cc b/absl/synchronization/barrier.cc
index a1b3ad5..c2c539a 100644
--- a/absl/synchronization/barrier.cc
+++ b/absl/synchronization/barrier.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/barrier.h b/absl/synchronization/barrier.h
index f834fee..23bb2f5 100644
--- a/absl/synchronization/barrier.h
+++ b/absl/synchronization/barrier.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/barrier_test.cc b/absl/synchronization/barrier_test.cc
index d6cabab..bfc6cb1 100644
--- a/absl/synchronization/barrier_test.cc
+++ b/absl/synchronization/barrier_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/blocking_counter.cc b/absl/synchronization/blocking_counter.cc
index 7e68e96..481a06b 100644
--- a/absl/synchronization/blocking_counter.cc
+++ b/absl/synchronization/blocking_counter.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/blocking_counter.h b/absl/synchronization/blocking_counter.h
index 557ed02..4c66e0a 100644
--- a/absl/synchronization/blocking_counter.h
+++ b/absl/synchronization/blocking_counter.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/blocking_counter_test.cc b/absl/synchronization/blocking_counter_test.cc
index e8223f8..c63e339 100644
--- a/absl/synchronization/blocking_counter_test.cc
+++ b/absl/synchronization/blocking_counter_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc
index e7a65cd..6e93605 100644
--- a/absl/synchronization/internal/create_thread_identity.cc
+++ b/absl/synchronization/internal/create_thread_identity.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -67,6 +67,30 @@
   return (addr + align - 1) & ~(align - 1);
 }
 
+static void ResetThreadIdentity(base_internal::ThreadIdentity* identity) {
+  base_internal::PerThreadSynch* pts = &identity->per_thread_synch;
+  pts->next = nullptr;
+  pts->skip = nullptr;
+  pts->may_skip = false;
+  pts->waitp = nullptr;
+  pts->suppress_fatal_errors = false;
+  pts->readers = 0;
+  pts->priority = 0;
+  pts->next_priority_read_cycles = 0;
+  pts->state.store(base_internal::PerThreadSynch::State::kAvailable,
+                   std::memory_order_relaxed);
+  pts->maybe_unlocking = false;
+  pts->wake = false;
+  pts->cond_waiter = false;
+  pts->all_locks = nullptr;
+  identity->waiter_state = {};
+  identity->blocked_count_ptr = nullptr;
+  identity->ticker.store(0, std::memory_order_relaxed);
+  identity->wait_start.store(0, std::memory_order_relaxed);
+  identity->is_idle.store(false, std::memory_order_relaxed);
+  identity->next = nullptr;
+}
+
 static base_internal::ThreadIdentity* NewThreadIdentity() {
   base_internal::ThreadIdentity* identity = nullptr;
 
@@ -90,7 +114,7 @@
         RoundUp(reinterpret_cast<intptr_t>(allocation),
                 base_internal::PerThreadSynch::kAlignment));
   }
-  memset(identity, 0, sizeof(*identity));
+  ResetThreadIdentity(identity);
 
   return identity;
 }
diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h
index 1bb87de..ebb16c5 100644
--- a/absl/synchronization/internal/create_thread_identity.h
+++ b/absl/synchronization/internal/create_thread_identity.h
@@ -5,7 +5,7 @@
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *      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,
@@ -50,4 +50,5 @@
 
 }  // namespace synchronization_internal
 }  // namespace absl
+
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc
index d3878de..0c8c756 100644
--- a/absl/synchronization/internal/graphcycles.cc
+++ b/absl/synchronization/internal/graphcycles.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/internal/graphcycles.h b/absl/synchronization/internal/graphcycles.h
index 2e6686a..e5bde00 100644
--- a/absl/synchronization/internal/graphcycles.h
+++ b/absl/synchronization/internal/graphcycles.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/internal/graphcycles_benchmark.cc b/absl/synchronization/internal/graphcycles_benchmark.cc
index a239c25..54823e0 100644
--- a/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc
index 9a85b39..58e8477 100644
--- a/absl/synchronization/internal/graphcycles_test.cc
+++ b/absl/synchronization/internal/graphcycles_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index bb70800..61c72e7 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -53,6 +53,7 @@
 
   // We explicitly do not support other custom formats: timespec, int64_t nanos.
   // Unify on this and absl::Time, please.
+
   bool has_timeout() const { return ns_ != 0; }
 
  private:
@@ -76,7 +77,7 @@
     if (x <= 0) x = 1;
     // A time larger than what can be represented to the kernel is treated
     // as no timeout.
-    if (x == std::numeric_limits<int64_t>::max()) x = 0;
+    if (x == (std::numeric_limits<int64_t>::max)()) x = 0;
     return x;
   }
 
@@ -90,7 +91,7 @@
           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();
+      n = (std::numeric_limits<int64_t>::max)();
     }
 
     // Kernel APIs validate timespecs as being at or after the epoch,
@@ -100,8 +101,8 @@
     if (n < 0) n = 0;
 
     struct timespec abstime;
-    int64_t seconds = std::min(n / kNanosPerSecond,
-                             int64_t{std::numeric_limits<time_t>::max()});
+    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);
@@ -119,7 +120,7 @@
   // <intsafe.h> and <WinBase.h>.
   typedef unsigned long DWord;  // NOLINT
   DWord InMillisecondsFromNow() const {
-    constexpr DWord kInfinite = std::numeric_limits<DWord>::max();
+    constexpr DWord kInfinite = (std::numeric_limits<DWord>::max)();
     if (!has_timeout()) {
       return kInfinite;
     }
@@ -130,7 +131,7 @@
     if (ns_ >= now) {
       // Round up so that Now() + ms_from_now >= ns_.
       constexpr uint64_t max_nanos =
-          std::numeric_limits<int64_t>::max() - 999999u;
+          (std::numeric_limits<int64_t>::max)() - 999999u;
       uint64_t ms_from_now =
           (std::min<uint64_t>(max_nanos, ns_ - now) + 999999u) / 1000000u;
       if (ms_from_now > kInfinite) {
@@ -148,4 +149,5 @@
 
 }  // namespace synchronization_internal
 }  // namespace absl
+
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc
index 45c6032..267deaf 100644
--- a/absl/synchronization/internal/mutex_nonprod.cc
+++ b/absl/synchronization/internal/mutex_nonprod.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
index 0aab3d1..b8d5af7 100644
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ b/absl/synchronization/internal/mutex_nonprod.inc
@@ -214,6 +214,9 @@
   // stack) should use this constructor.
   explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
 
+  constexpr explicit SynchronizationStorage(absl::ConstInitType)
+      : is_dynamic_(false), once_(), space_{{0}} {}
+
   SynchronizationStorage(SynchronizationStorage&) = delete;
   SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
 
diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc
index caa2baf..b7014fb 100644
--- a/absl/synchronization/internal/per_thread_sem.cc
+++ b/absl/synchronization/internal/per_thread_sem.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -89,6 +89,7 @@
   if (identity->blocked_count_ptr != nullptr) {
     identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed);
   }
+
   identity->is_idle.store(false, std::memory_order_relaxed);
   identity->wait_start.store(0, std::memory_order_relaxed);
   return !timeout;
diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h
index 678b69e..e7da070 100644
--- a/absl/synchronization/internal/per_thread_sem.h
+++ b/absl/synchronization/internal/per_thread_sem.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -104,4 +104,5 @@
     absl::synchronization_internal::KernelTimeout t) {
   return AbslInternalPerThreadSemWait(t);
 }
+
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc
index c29d840..dba7239 100644
--- a/absl/synchronization/internal/per_thread_sem_test.cc
+++ b/absl/synchronization/internal/per_thread_sem_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -114,10 +114,9 @@
       min_cycles = std::min(min_cycles, cycles);
       total_cycles += cycles;
     }
-    std::string out =
-        StrCat(msg, "min cycle count=", min_cycles, " avg cycle count=",
-               absl::SixDigits(static_cast<double>(total_cycles) /
-                               kNumIterations));
+    std::string out = StrCat(
+        msg, "min cycle count=", min_cycles, " avg cycle count=",
+        absl::SixDigits(static_cast<double>(total_cycles) / kNumIterations));
     printf("%s\n", out.c_str());
 
     partner_thread.join();
@@ -152,12 +151,16 @@
 }
 
 TEST_F(PerThreadSemTest, Timeouts) {
-  absl::Time timeout = absl::Now() + absl::Milliseconds(50);
+  const absl::Duration delay = absl::Milliseconds(50);
+  const absl::Time start = absl::Now();
+  EXPECT_FALSE(Wait(start + delay));
+  const absl::Duration elapsed = absl::Now() - start;
   // Allow for a slight early return, to account for quality of implementation
   // issues on various platforms.
   const absl::Duration slop = absl::Microseconds(200);
-  EXPECT_FALSE(Wait(timeout));
-  EXPECT_LE(timeout, absl::Now() + slop);
+  EXPECT_LE(delay - slop, elapsed)
+      << "Wait returned " << delay - elapsed
+      << " early (with " << slop << " slop), start time was " << start;
 
   absl::Time negative_timeout = absl::UnixEpoch() - absl::Milliseconds(100);
   EXPECT_FALSE(Wait(negative_timeout));
diff --git a/absl/synchronization/internal/thread_pool.h b/absl/synchronization/internal/thread_pool.h
index 8464042..7f458f5 100644
--- a/absl/synchronization/internal/thread_pool.h
+++ b/absl/synchronization/internal/thread_pool.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -16,6 +16,7 @@
 #define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
 
 #include <cassert>
+#include <cstddef>
 #include <functional>
 #include <queue>
 #include <thread>  // NOLINT(build/c++11)
@@ -42,7 +43,7 @@
   ~ThreadPool() {
     {
       absl::MutexLock l(&mu_);
-      for (int i = 0; i < threads_.size(); ++i) {
+      for (size_t i = 0; i < threads_.size(); i++) {
         queue_.push(nullptr);  // Shutdown signal.
       }
     }
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index 768c520..74b0965 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -40,6 +40,7 @@
 #include <atomic>
 #include <cassert>
 #include <cstdint>
+
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/thread_identity.h"
 #include "absl/base/optimization.h"
@@ -81,6 +82,7 @@
 #define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
 #endif
 #endif
+
 class Futex {
  public:
   static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index 23166f4..66b4beb 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/synchronization/lifetime_test.cc b/absl/synchronization/lifetime_test.cc
index 90c9009..0279c8f 100644
--- a/absl/synchronization/lifetime_test.cc
+++ b/absl/synchronization/lifetime_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,6 +17,7 @@
 #include <type_traits>
 
 #include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/mutex.h"
@@ -72,23 +73,19 @@
 // Launch thread 1 and thread 2, and block on their completion.
 // If any of 'mutex', 'condvar', or 'notification' is nullptr, use a locally
 // constructed instance instead.
-void RunTests(absl::Mutex* mutex, absl::CondVar* condvar,
-              absl::Notification* notification) {
+void RunTests(absl::Mutex* mutex, absl::CondVar* condvar) {
   absl::Mutex default_mutex;
   absl::CondVar default_condvar;
-  absl::Notification default_notification;
+  absl::Notification notification;
   if (!mutex) {
     mutex = &default_mutex;
   }
   if (!condvar) {
     condvar = &default_condvar;
   }
-  if (!notification) {
-    notification = &default_notification;
-  }
   bool state = false;
-  std::thread thread_one(ThreadOne, mutex, condvar, notification, &state);
-  std::thread thread_two(ThreadTwo, mutex, condvar, notification, &state);
+  std::thread thread_one(ThreadOne, mutex, condvar, &notification, &state);
+  std::thread thread_two(ThreadTwo, mutex, condvar, &notification, &state);
   thread_one.join();
   thread_two.join();
 }
@@ -96,10 +93,13 @@
 void TestLocals() {
   absl::Mutex mutex;
   absl::CondVar condvar;
-  absl::Notification notification;
-  RunTests(&mutex, &condvar, &notification);
+  RunTests(&mutex, &condvar);
 }
 
+// Normal kConstInit usage
+ABSL_CONST_INIT absl::Mutex const_init_mutex(absl::kConstInit);
+void TestConstInitGlobal() { RunTests(&const_init_mutex, nullptr); }
+
 // Global variables during start and termination
 //
 // In a translation unit, static storage duration variables are initialized in
@@ -122,10 +122,53 @@
   Function fn_;
 };
 
+// kConstInit
+// Test early usage.  (Declaration comes first; definitions must appear after
+// the test runner.)
+extern absl::Mutex early_const_init_mutex;
+// (Normally I'd write this +[], to make the cast-to-function-pointer explicit,
+// but in some MSVC setups we support, lambdas provide conversion operators to
+// different flavors of function pointers, making this trick ambiguous.)
+OnConstruction test_early_const_init([] {
+  RunTests(&early_const_init_mutex, nullptr);
+});
+// This definition appears before test_early_const_init, but it should be
+// initialized first (due to constant initialization).  Test that the object
+// actually works when constructed this way.
+ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);
+
+// Furthermore, test that the const-init c'tor doesn't stomp over the state of
+// a Mutex.  Really, this is a test that the platform under test correctly
+// supports C++11 constant initialization.  (The constant-initialization
+// constructors of globals "happen at link time"; memory is pre-initialized,
+// before the constructors of either grab_lock or check_still_locked are run.)
+extern absl::Mutex const_init_sanity_mutex;
+OnConstruction grab_lock([]() NO_THREAD_SAFETY_ANALYSIS {
+  const_init_sanity_mutex.Lock();
+});
+ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
+OnConstruction check_still_locked([]() NO_THREAD_SAFETY_ANALYSIS {
+  const_init_sanity_mutex.AssertHeld();
+  const_init_sanity_mutex.Unlock();
+});
+
+// Test shutdown usage.  (Declarations come first; definitions must appear after
+// the test runner.)
+extern absl::Mutex late_const_init_mutex;
+// OnDestruction is being used here as a global variable, even though it has a
+// non-trivial destructor.  This is against the style guide.  We're violating
+// that rule here to check that the exception we allow for kConstInit is safe.
+// NOLINTNEXTLINE
+OnDestruction test_late_const_init([] {
+  RunTests(&late_const_init_mutex, nullptr);
+});
+ABSL_CONST_INIT absl::Mutex late_const_init_mutex(absl::kConstInit);
+
 }  // namespace
 
 int main() {
   TestLocals();
+  TestConstInitGlobal();
   // Explicitly call exit(0) here, to make it clear that we intend for the
   // above global object destructors to run.
   std::exit(0);
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 9d59a79..97c5919 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -118,6 +118,10 @@
 
 }  // namespace
 
+static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
+                                          bool locking, bool trylock,
+                                          bool read_lock);
+
 void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)) {
   submit_profile_data.Store(fn);
 }
@@ -233,15 +237,14 @@
   SYNCH_EV_SIGNALALL,
 };
 
-enum {                 // Event flags
-  SYNCH_F_R = 0x01,    // reader event
-  SYNCH_F_LCK = 0x02,  // PostSynchEvent called with mutex held
-  SYNCH_F_ACQ = 0x04,  // event is an acquire
+enum {                    // Event flags
+  SYNCH_F_R = 0x01,       // reader event
+  SYNCH_F_LCK = 0x02,     // PostSynchEvent called with mutex held
+  SYNCH_F_TRY = 0x04,     // TryLock or ReaderTryLock
+  SYNCH_F_UNLOCK = 0x08,  // Unlock or ReaderUnlock
 
   SYNCH_F_LCK_W = SYNCH_F_LCK,
   SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R,
-  SYNCH_F_ACQ_W = SYNCH_F_ACQ,
-  SYNCH_F_ACQ_R = SYNCH_F_ACQ | SYNCH_F_R,
 };
 }  // anonymous namespace
 
@@ -250,21 +253,22 @@
   int flags;
   const char *msg;
 } event_properties[] = {
-  { SYNCH_F_LCK_W|SYNCH_F_ACQ_W, "TryLock succeeded " },
-  { 0,                           "TryLock failed " },
-  { SYNCH_F_LCK_R|SYNCH_F_ACQ_R, "ReaderTryLock succeeded " },
-  { 0,                           "ReaderTryLock failed " },
-  {               SYNCH_F_ACQ_W, "Lock blocking " },
-  { SYNCH_F_LCK_W,               "Lock returning " },
-  {               SYNCH_F_ACQ_R, "ReaderLock blocking " },
-  { SYNCH_F_LCK_R,               "ReaderLock returning " },
-  { SYNCH_F_LCK_W,               "Unlock " },
-  { SYNCH_F_LCK_R,               "ReaderUnlock " },
-  { 0,                           "Wait on " },
-  { 0,                           "Wait unblocked " },
-  { 0,                           "Signal on " },
-  { 0,                           "SignalAll on " },
+    {SYNCH_F_LCK_W | SYNCH_F_TRY, "TryLock succeeded "},
+    {0, "TryLock failed "},
+    {SYNCH_F_LCK_R | SYNCH_F_TRY, "ReaderTryLock succeeded "},
+    {0, "ReaderTryLock failed "},
+    {0, "Lock blocking "},
+    {SYNCH_F_LCK_W, "Lock returning "},
+    {0, "ReaderLock blocking "},
+    {SYNCH_F_LCK_R, "ReaderLock returning "},
+    {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, "Unlock "},
+    {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, "ReaderUnlock "},
+    {0, "Wait on "},
+    {0, "Wait unblocked "},
+    {0, "Signal on "},
+    {0, "SignalAll on "},
 };
+
 static absl::base_internal::SpinLock synch_event_mu(
     absl::base_internal::kLinkerInitialized);
 // protects synch_event
@@ -414,9 +418,26 @@
     ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj,
                  (e == nullptr ? "" : e->name), buffer);
   }
-  if ((event_properties[ev].flags & SYNCH_F_LCK) != 0 && e != nullptr &&
-      e->invariant != nullptr) {
-    (*e->invariant)(e->arg);
+  const int flags = event_properties[ev].flags;
+  if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) {
+    // Calling the invariant as is causes problems under ThreadSanitizer.
+    // We are currently inside of Mutex Lock/Unlock and are ignoring all
+    // memory accesses and synchronization. If the invariant transitively
+    // synchronizes something else and we ignore the synchronization, we will
+    // get false positive race reports later.
+    // Reuse EvalConditionAnnotated to properly call into user code.
+    struct local {
+      static bool pred(SynchEvent *ev) {
+        (*ev->invariant)(ev->arg);
+        return false;
+      }
+    };
+    Condition cond(&local::pred, e);
+    Mutex *mu = static_cast<Mutex *>(obj);
+    const bool locking = (flags & SYNCH_F_UNLOCK) == 0;
+    const bool trylock = (flags & SYNCH_F_TRY) != 0;
+    const bool read_lock = (flags & SYNCH_F_R) != 0;
+    EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock);
   }
   UnrefSynchEvent(e);
 }
@@ -1079,7 +1100,7 @@
 // if the wait extends past the absolute time specified, even if "s" is still
 // on the mutex queue.  In this case, remove "s" from the queue and return
 // true, otherwise return false.
-void Mutex::Block(PerThreadSynch *s) {
+ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
   while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
     if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
       // After a timeout, we go into a spin loop until we remove ourselves
@@ -1552,7 +1573,7 @@
   ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
   this->LockSlowLoop(&waitp, flags);
   bool res = waitp.cond != nullptr ||  // => cond known true from LockSlowLoop
-             cond.Eval();
+             EvalConditionAnnotated(&cond, this, true, false, how == kShared);
   ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
   return res;
 }
@@ -1730,12 +1751,17 @@
 
 // Compute cond->Eval() and tell race detectors that we do it under mutex mu.
 static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
-                                          bool locking, Mutex::MuHow how) {
+                                          bool locking, bool trylock,
+                                          bool read_lock) {
   // Delicate annotation dance.
   // We are currently inside of read/write lock/unlock operation.
   // 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 THREAD_SANITIZER
+  const int flags = read_lock ? __tsan_mutex_read_lock : 0;
+  const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
+#endif
   if (locking) {
     // For lock we pretend that we have finished the operation,
     // evaluate the predicate, then unlock the mutex and start locking it again
@@ -1743,24 +1769,26 @@
     // Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan
     // will think the lock acquisition is recursive which will trigger
     // deadlock detector.
-    ABSL_TSAN_MUTEX_POST_LOCK(mu, TsanFlags(how), 0);
+    ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0);
     res = cond->Eval();
-    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_PRE_LOCK(mu, TsanFlags(how));
+    // There is no "try" version of Unlock, so use flags instead of tryflags.
+    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
+    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
+    ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags);
   } else {
     // Similarly, for unlock we pretend that we have unlocked the mutex,
     // lock the mutex, evaluate the predicate, and start unlocking it again
     // to match the annotation at the end of outer unlock operation.
-    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_PRE_LOCK(mu, TsanFlags(how));
-    ABSL_TSAN_MUTEX_POST_LOCK(mu, TsanFlags(how), 0);
+    ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
+    ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags);
+    ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0);
     res = cond->Eval();
-    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, TsanFlags(how));
+    ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
   }
   // Prevent unused param warnings in non-TSAN builds.
   static_cast<void>(mu);
-  static_cast<void>(how);
+  static_cast<void>(trylock);
+  static_cast<void>(read_lock);
   return res;
 }
 
@@ -1806,7 +1834,8 @@
           v, (how->fast_or | (v & zap_desig_waker[flags & kMuHasBlocked])) +
                  how->fast_add,
           std::memory_order_acquire, std::memory_order_relaxed)) {
-    if (cond == nullptr || EvalConditionAnnotated(cond, this, true, how)) {
+    if (cond == nullptr ||
+        EvalConditionAnnotated(cond, this, true, false, how == kShared)) {
       return true;
     }
     unlock = true;
@@ -1824,7 +1853,8 @@
   }
   this->LockSlowLoop(&waitp, flags);
   return waitp.cond != nullptr ||  // => cond known true from LockSlowLoop
-         cond == nullptr || EvalConditionAnnotated(cond, this, true, how);
+         cond == nullptr ||
+         EvalConditionAnnotated(cond, this, true, false, how == kShared);
 }
 
 // RAW_CHECK_FMT() takes a condition, a printf-style format string, and
@@ -1841,7 +1871,7 @@
   // Test for either of two situations that should not occur in v:
   //   kMuWriter and kMuReader
   //   kMuWrWait and !kMuWait
-  const intptr_t w = v ^ kMuWait;
+  const uintptr_t w = v ^ kMuWait;
   // By flipping that bit, we can now test for:
   //   kMuWriter and kMuReader in w
   //   kMuWrWait and kMuWait in w
@@ -1880,7 +1910,8 @@
                      waitp->how->fast_add,
               std::memory_order_acquire, std::memory_order_relaxed)) {
         if (waitp->cond == nullptr ||
-            EvalConditionAnnotated(waitp->cond, this, true, waitp->how)) {
+            EvalConditionAnnotated(waitp->cond, this, true, false,
+                                   waitp->how == kShared)) {
           break;  // we timed out, or condition true, so return
         }
         this->UnlockSlow(waitp);  // got lock but condition false
@@ -1923,7 +1954,8 @@
                                               std::memory_order_release,
                                               std::memory_order_relaxed));
           if (waitp->cond == nullptr ||
-              EvalConditionAnnotated(waitp->cond, this, true, waitp->how)) {
+              EvalConditionAnnotated(waitp->cond, this, true, false,
+                                     waitp->how == kShared)) {
             break;  // we timed out, or condition true, so return
           }
           this->UnlockSlow(waitp);           // got lock but condition false
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index a378190..c38e356 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -61,6 +61,7 @@
 #include <cstdint>
 #include <string>
 
+#include "absl/base/const_init.h"
 #include "absl/base/internal/identity.h"
 #include "absl/base/internal/low_level_alloc.h"
 #include "absl/base/internal/thread_identity.h"
@@ -136,7 +137,27 @@
 
 class LOCKABLE Mutex {
  public:
+  // Creates a `Mutex` that is not held by anyone. This constructor is
+  // typically used for Mutexes allocated on the heap or the stack.
+  //
+  // To create `Mutex` instances with static storage duration
+  // (e.g. a namespace-scoped or global variable), see
+  // `Mutex::Mutex(absl::kConstInit)` below instead.
   Mutex();
+
+  // Creates a mutex with static storage duration.  A global variable
+  // constructed this way avoids the lifetime issues that can occur on program
+  // startup and shutdown.  (See absl/base/const_init.h.)
+  //
+  // For Mutexes allocated on the heap and stack, instead use the default
+  // constructor, which can interact more fully with the thread sanitizer.
+  //
+  // Example usage:
+  //   namespace foo {
+  //   ABSL_CONST_INIT Mutex mu(absl::kConstInit);
+  //   }
+  explicit constexpr Mutex(absl::ConstInitType);
+
   ~Mutex();
 
   // Mutex::Lock()
@@ -584,7 +605,7 @@
 // -----------------------------------------------------------------------------
 //
 // As noted above, `Mutex` contains a number of member functions which take a
-// `Condition` as a argument; clients can wait for conditions to become `true`
+// `Condition` as an argument; clients can wait for conditions to become `true`
 // before attempting to acquire the mutex. These sections are known as
 // "condition critical" sections. To use a `Condition`, you simply need to
 // construct it, and use within an appropriate `Mutex` member function;
@@ -879,11 +900,15 @@
 };
 
 #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);
 }
 
+inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
+
 inline CondVar::CondVar() : cv_(0) {}
 #endif
 
@@ -1025,4 +1050,5 @@
 extern "C" {
 void AbslInternalMutexYield();
 }  // extern "C"
+
 #endif  // ABSL_SYNCHRONIZATION_MUTEX_H_
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index 1e019e0..ab18800 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -12,16 +12,154 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <cstdint>
+#include <mutex>  // NOLINT(build/c++11)
 #include <vector>
 
-#include "benchmark/benchmark.h"
-#include "absl/base/internal/sysinfo.h"
+#include "absl/base/internal/cycleclock.h"
+#include "absl/base/internal/spinlock.h"
 #include "absl/synchronization/blocking_counter.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/synchronization/mutex.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
+void BM_Mutex(benchmark::State& state) {
+  static absl::Mutex* mu = new absl::Mutex;
+  for (auto _ : state) {
+    absl::MutexLock lock(mu);
+  }
+}
+BENCHMARK(BM_Mutex)->UseRealTime()->Threads(1)->ThreadPerCpu();
+
+static void DelayNs(int64_t ns, int* data) {
+  int64_t end = absl::base_internal::CycleClock::Now() +
+                ns * absl::base_internal::CycleClock::Frequency() / 1e9;
+  while (absl::base_internal::CycleClock::Now() < end) {
+    ++(*data);
+    benchmark::DoNotOptimize(*data);
+  }
+}
+
+template <typename MutexType>
+class RaiiLocker {
+ public:
+  explicit RaiiLocker(MutexType* mu) : mu_(mu) { mu_->Lock(); }
+  ~RaiiLocker() { mu_->Unlock(); }
+ private:
+  MutexType* mu_;
+};
+
+template <>
+class RaiiLocker<std::mutex> {
+ public:
+  explicit RaiiLocker(std::mutex* mu) : mu_(mu) { mu_->lock(); }
+  ~RaiiLocker() { mu_->unlock(); }
+ private:
+  std::mutex* mu_;
+};
+
+template <typename MutexType>
+void BM_Contended(benchmark::State& state) {
+  struct Shared {
+    MutexType mu;
+    int data = 0;
+  };
+  static auto* shared = new Shared;
+  int local = 0;
+  for (auto _ : state) {
+    // Here we model both local work outside of the critical section as well as
+    // some work inside of the critical section. The idea is to capture some
+    // more or less realisitic contention levels.
+    // If contention is too low, the benchmark won't measure anything useful.
+    // If contention is unrealistically high, the benchmark will favor
+    // bad mutex implementations that block and otherwise distract threads
+    // from the mutex and shared state for as much as possible.
+    // To achieve this amount of local work is multiplied by number of threads
+    // to keep ratio between local work and critical section approximately
+    // equal regardless of number of threads.
+    DelayNs(100 * state.threads, &local);
+    RaiiLocker<MutexType> locker(&shared->mu);
+    DelayNs(state.range(0), &shared->data);
+  }
+}
+
+BENCHMARK_TEMPLATE(BM_Contended, absl::Mutex)
+    ->UseRealTime()
+    // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+    ->Threads(1)
+    ->Threads(2)
+    ->Threads(4)
+    ->Threads(6)
+    ->Threads(8)
+    ->Threads(12)
+    ->Threads(16)
+    ->Threads(24)
+    ->Threads(32)
+    ->Threads(48)
+    ->Threads(64)
+    ->Threads(96)
+    ->Threads(128)
+    ->Threads(192)
+    ->Threads(256)
+    // Some empirically chosen amounts of work in critical section.
+    // 1 is low contention, 200 is high contention and few values in between.
+    ->Arg(1)
+    ->Arg(20)
+    ->Arg(50)
+    ->Arg(200);
+
+BENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock)
+    ->UseRealTime()
+    // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+    ->Threads(1)
+    ->Threads(2)
+    ->Threads(4)
+    ->Threads(6)
+    ->Threads(8)
+    ->Threads(12)
+    ->Threads(16)
+    ->Threads(24)
+    ->Threads(32)
+    ->Threads(48)
+    ->Threads(64)
+    ->Threads(96)
+    ->Threads(128)
+    ->Threads(192)
+    ->Threads(256)
+    // Some empirically chosen amounts of work in critical section.
+    // 1 is low contention, 200 is high contention and few values in between.
+    ->Arg(1)
+    ->Arg(20)
+    ->Arg(50)
+    ->Arg(200);
+
+BENCHMARK_TEMPLATE(BM_Contended, std::mutex)
+    ->UseRealTime()
+    // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+    ->Threads(1)
+    ->Threads(2)
+    ->Threads(4)
+    ->Threads(6)
+    ->Threads(8)
+    ->Threads(12)
+    ->Threads(16)
+    ->Threads(24)
+    ->Threads(32)
+    ->Threads(48)
+    ->Threads(64)
+    ->Threads(96)
+    ->Threads(128)
+    ->Threads(192)
+    ->Threads(256)
+    // Some empirically chosen amounts of work in critical section.
+    // 1 is low contention, 200 is high contention and few values in between.
+    ->Arg(1)
+    ->Arg(20)
+    ->Arg(50)
+    ->Arg(200);
+
 // Measure the overhead of conditions on mutex release (when they must be
 // evaluated).  Mutex has (some) support for equivalence classes allowing
 // Conditions with the same function/argument to potentially not be multiply
@@ -82,13 +220,4 @@
 #endif
 BENCHMARK(BM_ConditionWaiters)->RangePair(0, 2, 1, kMaxConditionWaiters);
 
-void BM_ContendedMutex(benchmark::State& state) {
-  static absl::Mutex* mu = new absl::Mutex;
-  for (auto _ : state) {
-    absl::MutexLock lock(mu);
-  }
-}
-BENCHMARK(BM_ContendedMutex)->Threads(1);
-BENCHMARK(BM_ContendedMutex)->ThreadPerCpu();
-
 }  // namespace
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index b2820e2..1021122 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -610,9 +610,9 @@
   waiter2.reset();  // "join" waiter2
 }
 
-INSTANTIATE_TEST_CASE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
-                        ::testing::Range(0, 8),
-                        ::testing::PrintToStringParamName());
+INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
+                         ::testing::Range(0, 8),
+                         ::testing::PrintToStringParamName());
 
 // --------------------------------------------------------
 // Test for fix of bug in DequeueAllWakeable()
@@ -1032,9 +1032,9 @@
   ScopedDisableBazelTestWarnings() {
 #ifdef WIN32
     char file[MAX_PATH];
-    if (GetEnvironmentVariable(kVarName, file, sizeof(file)) < sizeof(file)) {
+    if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
       warnings_output_file_ = file;
-      SetEnvironmentVariable(kVarName, nullptr);
+      SetEnvironmentVariableA(kVarName, nullptr);
     }
 #else
     const char *file = getenv(kVarName);
@@ -1048,7 +1048,7 @@
   ~ScopedDisableBazelTestWarnings() {
     if (!warnings_output_file_.empty()) {
 #ifdef WIN32
-      SetEnvironmentVariable(kVarName, warnings_output_file_.c_str());
+      SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
 #else
       setenv(kVarName, warnings_output_file_.c_str(), 0);
 #endif
@@ -1367,8 +1367,8 @@
 }
 
 // Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.
-INSTANTIATE_TEST_CASE_P(All, TimeoutTest,
-                        testing::ValuesIn(MakeTimeoutTestParamValues()));
+INSTANTIATE_TEST_SUITE_P(All, TimeoutTest,
+                         testing::ValuesIn(MakeTimeoutTestParamValues()));
 
 TEST_P(TimeoutTest, Await) {
   const TimeoutTestParam params = GetParam();
@@ -1548,9 +1548,9 @@
 class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};
 
 // Instantiate the above with AllThreadCountOptions().
-INSTANTIATE_TEST_CASE_P(ThreadCounts, MutexVariableThreadCountTest,
-                        ::testing::ValuesIn(AllThreadCountValues()),
-                        ::testing::PrintToStringParamName());
+INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,
+                         ::testing::ValuesIn(AllThreadCountValues()),
+                         ::testing::PrintToStringParamName());
 
 // Reduces iterations by some factor for slow platforms
 // (determined empirically).
diff --git a/absl/synchronization/notification.cc b/absl/synchronization/notification.cc
index ed8cc90..53ace00 100644
--- a/absl/synchronization/notification.cc
+++ b/absl/synchronization/notification.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -22,6 +22,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+
 void Notification::Notify() {
   MutexLock l(&this->mutex_);
 
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
index 107932f..82d111a 100644
--- a/absl/synchronization/notification.h
+++ b/absl/synchronization/notification.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -52,6 +52,7 @@
 
 #include <atomic>
 
+#include "absl/base/macros.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/time/time.h"
 
@@ -109,4 +110,5 @@
 };
 
 }  // namespace absl
+
 #endif  // ABSL_SYNCHRONIZATION_NOTIFICATION_H_
diff --git a/absl/synchronization/notification_test.cc b/absl/synchronization/notification_test.cc
index d8708d5..059d4cd 100644
--- a/absl/synchronization/notification_test.cc
+++ b/absl/synchronization/notification_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -72,12 +72,16 @@
   EXPECT_FALSE(notification->WaitForNotificationWithDeadline(absl::Now()));
 
   const absl::Duration delay = absl::Milliseconds(50);
+  const absl::Time start = absl::Now();
+  EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
+  const absl::Duration elapsed = absl::Now() - start;
+
   // Allow for a slight early return, to account for quality of implementation
   // issues on various platforms.
   const absl::Duration slop = absl::Microseconds(200);
-  absl::Time start = absl::Now();
-  EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
-  EXPECT_LE(start + delay, absl::Now() + slop);
+  EXPECT_LE(delay - slop, elapsed)
+      << "WaitForNotificationWithTimeout returned " << delay - elapsed
+      << " early (with " << slop << " slop), start time was " << start;
 
   ThreadSafeCounter ready_counter;
   ThreadSafeCounter done_counter;
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index c7c16d4..a94be65 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
@@ -27,6 +27,7 @@
 cc_library(
     name = "time",
     srcs = [
+        "civil_time.cc",
         "clock.cc",
         "duration.cc",
         "format.cc",
@@ -35,6 +36,7 @@
         "time.cc",
     ],
     hdrs = [
+        "civil_time.h",
         "clock.h",
         "time.h",
     ],
@@ -72,10 +74,10 @@
 cc_test(
     name = "time_test",
     srcs = [
+        "civil_time_test.cc",
         "clock_test.cc",
         "duration_test.cc",
         "format_test.cc",
-        "time_norm_test.cc",
         "time_test.cc",
         "time_zone_test.cc",
     ],
@@ -94,6 +96,7 @@
 cc_test(
     name = "time_benchmark",
     srcs = [
+        "civil_time_benchmark.cc",
         "clock_benchmark.cc",
         "duration_benchmark.cc",
         "format_benchmark.cc",
@@ -107,6 +110,8 @@
         ":test_util",
         ":time",
         "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/hash",
         "@com_github_google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/time/BUILD.gn b/absl/time/BUILD.gn
index 5758e9d..e3f9e1a 100644
--- a/absl/time/BUILD.gn
+++ b/absl/time/BUILD.gn
@@ -22,6 +22,7 @@
   ]
   public_configs = [ "//third_party/abseil-cpp:absl_include_config" ]
   sources = [
+    "civil_time.cc",
     "clock.cc",
     "duration.cc",
     "format.cc",
@@ -30,6 +31,7 @@
     "time.cc",
   ]
   public = [
+    "civil_time.h",
     "clock.h",
     "time.h",
   ]
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index 0627236..5909832 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,83 +14,114 @@
 # limitations under the License.
 #
 
-list(APPEND TIME_PUBLIC_HEADERS
-  "clock.h"
-  "time.h"
-)
-
-
-list(APPEND TIME_INTERNAL_HEADERS
-  "internal/test_util.h"
-  "internal/cctz/include/cctz/civil_time.h"
-  "internal/cctz/include/cctz/civil_time_detail.h"
-  "internal/cctz/include/cctz/time_zone.h"
-  "internal/cctz/include/cctz/zone_info_source.h"
-)
-
-list(APPEND TIME_SRC
-  "time.cc"
+absl_cc_library(
+  NAME
+    time
+  HDRS
+    "civil_time.h"
+    "clock.h"
+    "time.h"
+  SRCS
+  "civil_time.cc"
   "clock.cc"
   "duration.cc"
   "format.cc"
+  "internal/get_current_time_chrono.inc"
+  "internal/get_current_time_posix.inc"
+  "time.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::core_headers
+    absl::int128
+    absl::strings
+    absl::civil_time
+    absl::time_zone
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    civil_time
+  HDRS
+    "internal/cctz/include/cctz/civil_time.h"
+    "internal/cctz/include/cctz/civil_time_detail.h"
+  SRCS
   "internal/cctz/src/civil_time_detail.cc"
-  "internal/cctz/src/time_zone_fixed.cc"
-  "internal/cctz/src/time_zone_fixed.h"
-  "internal/cctz/src/time_zone_format.cc"
-  "internal/cctz/src/time_zone_if.cc"
-  "internal/cctz/src/time_zone_if.h"
-  "internal/cctz/src/time_zone_impl.cc"
-  "internal/cctz/src/time_zone_impl.h"
-  "internal/cctz/src/time_zone_info.cc"
-  "internal/cctz/src/time_zone_info.h"
-  "internal/cctz/src/time_zone_libc.cc"
-  "internal/cctz/src/time_zone_libc.h"
-  "internal/cctz/src/time_zone_lookup.cc"
-  "internal/cctz/src/time_zone_posix.cc"
-  "internal/cctz/src/time_zone_posix.h"
-  "internal/cctz/src/tzfile.h"
-  "internal/cctz/src/zone_info_source.cc"
-  ${TIME_PUBLIC_HEADERS}
-  ${TIME_INTERNAL_HEADERS}
-)
-set(TIME_PUBLIC_LIBRARIES absl::base absl::stacktrace absl::int128 absl::strings)
-
-absl_library(
-  TARGET
-    absl_time
-  SOURCES
-    ${TIME_SRC}
-  PUBLIC_LIBRARIES
-    ${TIME_PUBLIC_LIBRARIES}
-  EXPORT_NAME
-    time
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
 )
 
+if(APPLE)
+  find_library(CoreFoundation CoreFoundation)
+endif()
 
-
-#
-## TESTS
-#
-
-# test time_test
-list(APPEND TIME_TEST_SRC
-  "time_test.cc"
-  "clock_test.cc"
-  "duration_test.cc"
-  "format_test.cc"
-  "time_norm_test.cc"
-  "time_test.cc"
-  "time_zone_test.cc"
-  "internal/test_util.cc"
+absl_cc_library(
+  NAME
+    time_zone
+  HDRS
+    "internal/cctz/include/cctz/time_zone.h"
+    "internal/cctz/include/cctz/zone_info_source.h"
+  SRCS
+    "internal/cctz/src/time_zone_fixed.cc"
+    "internal/cctz/src/time_zone_fixed.h"
+    "internal/cctz/src/time_zone_format.cc"
+    "internal/cctz/src/time_zone_if.cc"
+    "internal/cctz/src/time_zone_if.h"
+    "internal/cctz/src/time_zone_impl.cc"
+    "internal/cctz/src/time_zone_impl.h"
+    "internal/cctz/src/time_zone_info.cc"
+    "internal/cctz/src/time_zone_info.h"
+    "internal/cctz/src/time_zone_libc.cc"
+    "internal/cctz/src/time_zone_libc.h"
+    "internal/cctz/src/time_zone_lookup.cc"
+    "internal/cctz/src/time_zone_posix.cc"
+    "internal/cctz/src/time_zone_posix.h"
+    "internal/cctz/src/tzfile.h"
+    "internal/cctz/src/zone_info_source.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    $<$<PLATFORM_ID:Darwin>:${CoreFoundation}>
 )
-set(TIME_TEST_PUBLIC_LIBRARIES absl::time)
 
-absl_test(
-  TARGET
+absl_cc_library(
+  NAME
+    test_util
+  HDRS
+    "internal/test_util.h"
+  SRCS
+    "internal/test_util.cc"
+    "internal/zoneinfo.inc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::time
+    absl::base
+    absl::time_zone
+    gmock
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
     time_test
-  SOURCES
-    ${TIME_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${TIME_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "civil_time_test.cc"
+    "clock_test.cc"
+    "duration_test.cc"
+    "format_test.cc"
+    "time_test.cc"
+    "time_zone_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::test_util
+    absl::time
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::time_zone
+    gmock_main
 )
-
diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc
new file mode 100644
index 0000000..7527fc1
--- /dev/null
+++ b/absl/time/civil_time.cc
@@ -0,0 +1,83 @@
+// 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.
+
+#include "absl/time/civil_time.h"
+
+#include <cstdlib>
+#include <string>
+
+#include "absl/strings/str_cat.h"
+#include "absl/time/time.h"
+
+namespace absl {
+
+namespace {
+
+// Since a civil time has a larger year range than absl::Time (64-bit years vs
+// 64-bit seconds, respectively) we normalize years to roughly +/- 400 years
+// around the year 2400, which will produce an equivalent year in a range that
+// absl::Time can handle.
+inline civil_year_t NormalizeYear(civil_year_t year) {
+  return 2400 + year % 400;
+}
+
+// Formats the given CivilSecond according to the given format.
+std::string FormatYearAnd(string_view fmt, CivilSecond cs) {
+  const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(),
+                        cs.hour(), cs.minute(), cs.second());
+  const TimeZone utc = UTCTimeZone();
+  // TODO(absl-team): Avoid conversion of fmt std::string.
+  return StrCat(cs.year(),
+                FormatTime(std::string(fmt), FromCivil(ncs, utc), utc));
+}
+
+}  // namespace
+
+std::string FormatCivilTime(CivilSecond c) {
+  return FormatYearAnd("-%m-%dT%H:%M:%S", c);
+}
+std::string FormatCivilTime(CivilMinute c) {
+  return FormatYearAnd("-%m-%dT%H:%M", c);
+}
+std::string FormatCivilTime(CivilHour c) {
+  return FormatYearAnd("-%m-%dT%H", c);
+}
+std::string FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); }
+std::string FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); }
+std::string FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); }
+
+namespace time_internal {
+
+std::ostream& operator<<(std::ostream& os, CivilYear y) {
+  return os << FormatCivilTime(y);
+}
+std::ostream& operator<<(std::ostream& os, CivilMonth m) {
+  return os << FormatCivilTime(m);
+}
+std::ostream& operator<<(std::ostream& os, CivilDay d) {
+  return os << FormatCivilTime(d);
+}
+std::ostream& operator<<(std::ostream& os, CivilHour h) {
+  return os << FormatCivilTime(h);
+}
+std::ostream& operator<<(std::ostream& os, CivilMinute m) {
+  return os << FormatCivilTime(m);
+}
+std::ostream& operator<<(std::ostream& os, CivilSecond s) {
+  return os << FormatCivilTime(s);
+}
+
+}  // namespace time_internal
+
+}  // namespace absl
diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h
new file mode 100644
index 0000000..2dfcbd2
--- /dev/null
+++ b/absl/time/civil_time.h
@@ -0,0 +1,485 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: civil_time.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines abstractions for computing with "civil time".
+// The term "civil time" refers to the legally recognized human-scale time
+// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date"
+// is perhaps the most common example of a civil time (represented here as
+// an `absl::CivilDay`).
+//
+// Modern-day civil time follows the Gregorian Calendar and is a
+// time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for
+// example, is not tied to a time zone. Put another way, a civil time does not
+// map to a unique point in time; a civil time must be mapped to an absolute
+// time *through* a time zone.
+//
+// Because a civil time is what most people think of as "time," it is common to
+// map absolute times to civil times to present to users.
+//
+// Time zones define the relationship between absolute and civil times. Given an
+// absolute or civil time and a time zone, you can compute the other time:
+//
+//   Civil Time = F(Absolute Time, Time Zone)
+//   Absolute Time = G(Civil Time, Time Zone)
+//
+// The Abseil time library allows you to construct such civil times from
+// absolute times; consult time.h for such functionality.
+//
+// This library provides six classes for constructing civil-time objects, and
+// provides several helper functions for rounding, iterating, and performing
+// arithmetic on civil-time objects, while avoiding complications like
+// daylight-saving time (DST):
+//
+//   * `absl::CivilSecond`
+//   * `absl::CivilMinute`
+//   * `absl::CivilHour`
+//   * `absl::CivilDay`
+//   * `absl::CivilMonth`
+//   * `absl::CivilYear`
+//
+// Example:
+//
+//   // Construct a civil-time object for a specific day
+//   const absl::CivilDay cd(1969, 07, 20);
+//
+//   // Construct a civil-time object for a specific second
+//   const absl::CivilSecond cd(2018, 8, 1, 12, 0, 1);
+//
+// Note: In C++14 and later, this library is usable in a constexpr context.
+//
+// Example:
+//
+//   // Valid in C++14
+//   constexpr absl::CivilDay cd(1969, 07, 20);
+
+#ifndef ABSL_TIME_CIVIL_TIME_H_
+#define ABSL_TIME_CIVIL_TIME_H_
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+
+namespace absl {
+
+namespace time_internal {
+struct second_tag : cctz::detail::second_tag {};
+struct minute_tag : second_tag, cctz::detail::minute_tag {};
+struct hour_tag : minute_tag, cctz::detail::hour_tag {};
+struct day_tag : hour_tag, cctz::detail::day_tag {};
+struct month_tag : day_tag, cctz::detail::month_tag {};
+struct year_tag : month_tag, cctz::detail::year_tag {};
+}  // namespace time_internal
+
+// -----------------------------------------------------------------------------
+// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear
+// -----------------------------------------------------------------------------
+//
+// Each of these civil-time types is a simple value type with the same
+// interface for construction and the same six accessors for each of the civil
+// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These
+// classes differ only in their alignment, which is indicated by the type name
+// and specifies the field on which arithmetic operates.
+//
+// CONSTRUCTION
+//
+// Each of the civil-time types can be constructed in two ways: by directly
+// passing to the constructor up to six integers representing the YMDHMS fields,
+// or by copying the YMDHMS fields from a differently aligned civil-time type.
+// Omitted fields are assigned their minimum valid value. Hours, minutes, and
+// seconds will be set to 0, month and day will be set to 1. Since there is no
+// minimum year, the default is 1970.
+//
+// Examples:
+//
+//   absl::CivilDay default_value;               // 1970-01-01 00:00:00
+//
+//   absl::CivilDay a(2015, 2, 3);               // 2015-02-03 00:00:00
+//   absl::CivilDay b(2015, 2, 3, 4, 5, 6);      // 2015-02-03 00:00:00
+//   absl::CivilDay c(2015);                     // 2015-01-01 00:00:00
+//
+//   absl::CivilSecond ss(2015, 2, 3, 4, 5, 6);  // 2015-02-03 04:05:06
+//   absl::CivilMinute mm(ss);                   // 2015-02-03 04:05:00
+//   absl::CivilHour hh(mm);                     // 2015-02-03 04:00:00
+//   absl::CivilDay d(hh);                       // 2015-02-03 00:00:00
+//   absl::CivilMonth m(d);                      // 2015-02-01 00:00:00
+//   absl::CivilYear y(m);                       // 2015-01-01 00:00:00
+//
+//   m = absl::CivilMonth(y);                    // 2015-01-01 00:00:00
+//   d = absl::CivilDay(m);                      // 2015-01-01 00:00:00
+//   hh = absl::CivilHour(d);                    // 2015-01-01 00:00:00
+//   mm = absl::CivilMinute(hh);                 // 2015-01-01 00:00:00
+//   ss = absl::CivilSecond(mm);                 // 2015-01-01 00:00:00
+//
+// Each civil-time class is aligned to the civil-time field indicated in the
+// class's name after normalization. Alignment is performed by setting all the
+// inferior fields to their minimum valid value (as described above). The
+// following are examples of how each of the six types would align the fields
+// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the
+// string format used here is not important; it's just a shorthand way of
+// showing the six YMDHMS fields.)
+//
+//   absl::CivilSecond   : 2015-11-22 12:34:56
+//   absl::CivilMinute   : 2015-11-22 12:34:00
+//   absl::CivilHour     : 2015-11-22 12:00:00
+//   absl::CivilDay      : 2015-11-22 00:00:00
+//   absl::CivilMonth    : 2015-11-01 00:00:00
+//   absl::CivilYear     : 2015-01-01 00:00:00
+//
+// Each civil-time type performs arithmetic on the field to which it is
+// aligned. This means that adding 1 to an absl::CivilDay increments the day
+// field (normalizing as necessary), and subtracting 7 from an absl::CivilMonth
+// operates on the month field (normalizing as necessary). All arithmetic
+// produces a valid civil time. Difference requires two similarly aligned
+// civil-time objects and returns the scalar answer in units of the objects'
+// alignment. For example, the difference between two absl::CivilHour objects
+// will give an answer in units of civil hours.
+//
+// ALIGNMENT CONVERSION
+//
+// The alignment of a civil-time object cannot change, but the object may be
+// used to construct a new object with a different alignment. This is referred
+// to as "realigning". When realigning to a type with the same or more
+// precision (e.g., absl::CivilDay -> absl::CivilSecond), the conversion may be
+// performed implicitly since no information is lost. However, if information
+// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must
+// be explicit at the call site.
+//
+// Examples:
+//
+//   void UseDay(absl::CivilDay day);
+//
+//   absl::CivilSecond cs;
+//   UseDay(cs);                  // Won't compile because data may be discarded
+//   UseDay(absl::CivilDay(cs));  // OK: explicit conversion
+//
+//   absl::CivilDay cd;
+//   UseDay(cd);                  // OK: no conversion needed
+//
+//   absl::CivilMonth cm;
+//   UseDay(cm);                  // OK: implicit conversion to absl::CivilDay
+//
+// NORMALIZATION
+//
+// Normalization takes invalid values and adjusts them to produce valid values.
+// Within the civil-time library, integer arguments passed to the Civil*
+// constructors may be out-of-range, in which case they are normalized by
+// carrying overflow into a field of courser granularity to produce valid
+// civil-time objects. This normalization enables natural arithmetic on
+// constructor arguments without worrying about the field's range.
+//
+// Examples:
+//
+//   // Out-of-range; normalized to 2016-11-01
+//   absl::CivilDay d(2016, 10, 32);
+//   // Out-of-range, negative: normalized to 2016-10-30T23
+//   absl::CivilHour h1(2016, 10, 31, -1);
+//   // Normalization is cumulative: normalized to 2016-10-30T23
+//   absl::CivilHour h2(2016, 10, 32, -25);
+//
+// Note: If normalization is undesired, you can signal an error by comparing
+// the constructor arguments to the normalized values returned by the YMDHMS
+// properties.
+//
+// COMPARISON
+//
+// Comparison between civil-time objects considers all six YMDHMS fields,
+// regardless of the type's alignment. Comparison between differently aligned
+// civil-time types is allowed.
+//
+// Examples:
+//
+//   absl::CivilDay feb_3(2015, 2, 3);  // 2015-02-03 00:00:00
+//   absl::CivilDay mar_4(2015, 3, 4);  // 2015-03-04 00:00:00
+//   // feb_3 < mar_4
+//   // absl::CivilYear(feb_3) == absl::CivilYear(mar_4)
+//
+//   absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0);  // 2015-02-03 12:00:00
+//   // feb_3 < feb_3_noon
+//   // feb_3 == absl::CivilDay(feb_3_noon)
+//
+//   // Iterates all the days of February 2015.
+//   for (absl::CivilDay d(2015, 2, 1); d < absl::CivilMonth(2015, 3); ++d) {
+//     // ...
+//   }
+//
+// ARITHMETIC
+//
+// Civil-time types support natural arithmetic operators such as addition,
+// subtraction, and difference. Arithmetic operates on the civil-time field
+// indicated in the type's name. Difference operators require arguments with
+// the same alignment and return the answer in units of the alignment.
+//
+// Example:
+//
+//   absl::CivilDay a(2015, 2, 3);
+//   ++a;                              // 2015-02-04 00:00:00
+//   --a;                              // 2015-02-03 00:00:00
+//   absl::CivilDay b = a + 1;         // 2015-02-04 00:00:00
+//   absl::CivilDay c = 1 + b;         // 2015-02-05 00:00:00
+//   int n = c - a;                    // n = 2 (civil days)
+//   int m = c - absl::CivilMonth(c);  // Won't compile: different types.
+//
+// ACCESSORS
+//
+// Each civil-time type has accessors for all six of the civil-time fields:
+// year, month, day, hour, minute, and second.
+//
+// civil_year_t year()
+// int          month()
+// int          day()
+// int          hour()
+// int          minute()
+// int          second()
+//
+// Recall that fields inferior to the type's aligment will be set to their
+// minimum valid value.
+//
+// Example:
+//
+//   absl::CivilDay d(2015, 6, 28);
+//   // d.year() == 2015
+//   // d.month() == 6
+//   // d.day() == 28
+//   // d.hour() == 0
+//   // d.minute() == 0
+//   // d.second() == 0
+//
+// CASE STUDY: Adding a month to January 31.
+//
+// One of the classic questions that arises when considering a civil time
+// library (or a date library or a date/time library) is this:
+//   "What is the result of adding a month to January 31?"
+// This is an interesting question because it is unclear what is meant by a
+// "month", and several different answers are possible, depending on context:
+//
+//   1. March 3 (or 2 if a leap year), if "add a month" means to add a month to
+//      the current month, and adjust the date to overflow the extra days into
+//      March. In this case the result of "February 31" would be normalized as
+//      within the civil-time library.
+//   2. February 28 (or 29 if a leap year), if "add a month" means to add a
+//      month, and adjust the date while holding the resulting month constant.
+//      In this case, the result of "February 31" would be truncated to the last
+//      day in February.
+//   3. An error. The caller may get some error, an exception, an invalid date
+//      object, or perhaps return `false`. This may make sense because there is
+//      no single unambiguously correct answer to the question.
+//
+// Practically speaking, any answer that is not what the programmer intended
+// is the wrong answer.
+//
+// The Abseil time library avoids this problem by making it impossible to
+// ask ambiguous questions. All civil-time objects are aligned to a particular
+// civil-field boundary (such as aligned to a year, month, day, hour, minute,
+// or second), and arithmetic operates on the field to which the object is
+// aligned. This means that in order to "add a month" the object must first be
+// aligned to a month boundary, which is equivalent to the first day of that
+// month.
+//
+// Of course, there are ways to compute an answer the question at hand using
+// this Abseil time library, but they require the programmer to be explicit
+// about the answer they expect. To illustrate, let's see how to compute all
+// three of the above possible answers to the question of "Jan 31 plus 1
+// month":
+//
+// Example:
+//
+//   const absl::CivilDay d(2015, 1, 31);
+//
+//   // Answer 1:
+//   // Add 1 to the month field in the constructor, and rely on normalization.
+//   const auto normalized = absl::CivilDay(d.year(), d.month() + 1, d.day());
+//   // normalized == 2015-03-03 (aka Feb 31)
+//
+//   // Answer 2:
+//   // Add 1 to month field, capping to the end of next month.
+//   const auto next_month = absl::CivilMonth(d) + 1;
+//   const auto last_day_of_next_month = absl::CivilDay(next_month + 1) - 1;
+//   const auto capped = std::min(normalized, last_day_of_next_month);
+//   // capped == 2015-02-28
+//
+//   // Answer 3:
+//   // Signal an error if the normalized answer is not in next month.
+//   if (absl::CivilMonth(normalized) != next_month) {
+//     // error, month overflow
+//   }
+//
+using CivilSecond =
+    time_internal::cctz::detail::civil_time<time_internal::second_tag>;
+using CivilMinute =
+    time_internal::cctz::detail::civil_time<time_internal::minute_tag>;
+using CivilHour =
+    time_internal::cctz::detail::civil_time<time_internal::hour_tag>;
+using CivilDay =
+    time_internal::cctz::detail::civil_time<time_internal::day_tag>;
+using CivilMonth =
+    time_internal::cctz::detail::civil_time<time_internal::month_tag>;
+using CivilYear =
+    time_internal::cctz::detail::civil_time<time_internal::year_tag>;
+
+// civil_year_t
+//
+// Type alias of a civil-time year value. This type is guaranteed to (at least)
+// support any year value supported by `time_t`.
+//
+// Example:
+//
+//   absl::CivilSecond cs = ...;
+//   absl::civil_year_t y = cs.year();
+//   cs = absl::CivilSecond(y, 1, 1, 0, 0, 0);  // CivilSecond(CivilYear(cs))
+//
+using civil_year_t = time_internal::cctz::year_t;
+
+// civil_diff_t
+//
+// Type alias of the difference between two civil-time values.
+// This type is used to indicate arguments that are not
+// normalized (such as parameters to the civil-time constructors), the results
+// of civil-time subtraction, or the operand to civil-time addition.
+//
+// Example:
+//
+//   absl::civil_diff_t n_sec = cs1 - cs2;             // cs1 == cs2 + n_sec;
+//
+using civil_diff_t = time_internal::cctz::diff_t;
+
+// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday,
+// Weekday::friday, Weekday::saturday, Weekday::sunday
+//
+// The Weekday enum class represents the civil-time concept of a "weekday" with
+// members for all days of the week.
+//
+//   absl::Weekday wd = absl::Weekday::thursday;
+//
+using Weekday = time_internal::cctz::weekday;
+
+// GetWeekday()
+//
+// Returns the absl::Weekday for the given absl::CivilDay.
+//
+// Example:
+//
+//   absl::CivilDay a(2015, 8, 13);
+//   absl::Weekday wd = absl::GetWeekday(a);  // wd == absl::Weekday::thursday
+//
+inline Weekday GetWeekday(CivilDay cd) {
+  return time_internal::cctz::get_weekday(cd);
+}
+
+// NextWeekday()
+// PrevWeekday()
+//
+// Returns the absl::CivilDay that strictly follows or precedes a given
+// absl::CivilDay, and that falls on the given absl::Weekday.
+//
+// Example, given the following month:
+//
+//       August 2015
+//   Su Mo Tu We Th Fr Sa
+//                      1
+//    2  3  4  5  6  7  8
+//    9 10 11 12 13 14 15
+//   16 17 18 19 20 21 22
+//   23 24 25 26 27 28 29
+//   30 31
+//
+//   absl::CivilDay a(2015, 8, 13);
+//   // absl::GetWeekday(a) == absl::Weekday::thursday
+//   absl::CivilDay b = absl::NextWeekday(a, absl::Weekday::thursday);
+//   // b = 2015-08-20
+//   absl::CivilDay c = absl::PrevWeekday(a, absl::Weekday::thursday);
+//   // c = 2015-08-06
+//
+//   absl::CivilDay d = ...
+//   // Gets the following Thursday if d is not already Thursday
+//   absl::CivilDay thurs1 = absl::PrevWeekday(d, absl::Weekday::thursday) + 7;
+//   // Gets the previous Thursday if d is not already Thursday
+//   absl::CivilDay thurs2 = absl::NextWeekday(d, absl::Weekday::thursday) - 7;
+//
+inline CivilDay NextWeekday(CivilDay cd, Weekday wd) {
+  return CivilDay(time_internal::cctz::next_weekday(cd, wd));
+}
+inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) {
+  return CivilDay(time_internal::cctz::prev_weekday(cd, wd));
+}
+
+// GetYearDay()
+//
+// Returns the day-of-year for the given absl::CivilDay.
+//
+// Example:
+//
+//   absl::CivilDay a(2015, 1, 1);
+//   int yd_jan_1 = absl::GetYearDay(a);   // yd_jan_1 = 1
+//   absl::CivilDay b(2015, 12, 31);
+//   int yd_dec_31 = absl::GetYearDay(b);  // yd_dec_31 = 365
+//
+inline int GetYearDay(CivilDay cd) {
+  return time_internal::cctz::get_yearday(cd);
+}
+
+// FormatCivilTime()
+//
+// Formats the given civil-time value into a string value of the following
+// format:
+//
+//  Type        | Format
+//  ---------------------------------
+//  CivilSecond | YYYY-MM-DDTHH:MM:SS
+//  CivilMinute | YYYY-MM-DDTHH:MM
+//  CivilHour   | YYYY-MM-DDTHH
+//  CivilDay    | YYYY-MM-DD
+//  CivilMonth  | YYYY-MM
+//  CivilYear   | YYYY
+//
+// Example:
+//
+//   absl::CivilDay d = absl::CivilDay(1969, 7, 20);
+//   std::string day_string = absl::FormatCivilTime(d);  // "1969-07-20"
+//
+std::string FormatCivilTime(CivilSecond c);
+std::string FormatCivilTime(CivilMinute c);
+std::string FormatCivilTime(CivilHour c);
+std::string FormatCivilTime(CivilDay c);
+std::string FormatCivilTime(CivilMonth c);
+std::string FormatCivilTime(CivilYear c);
+
+namespace time_internal {  // For functions found via ADL on civil-time tags.
+
+// Streaming Operators
+//
+// Each civil-time type may be sent to an output stream using operator<<().
+// The result matches the string produced by `FormatCivilTime()`.
+//
+// Example:
+//
+//   absl::CivilDay d = absl::CivilDay("1969-07-20");
+//   std::cout << "Date is: " << d << "\n";
+//
+std::ostream& operator<<(std::ostream& os, CivilYear y);
+std::ostream& operator<<(std::ostream& os, CivilMonth m);
+std::ostream& operator<<(std::ostream& os, CivilDay d);
+std::ostream& operator<<(std::ostream& os, CivilHour h);
+std::ostream& operator<<(std::ostream& os, CivilMinute m);
+std::ostream& operator<<(std::ostream& os, CivilSecond s);
+
+}  // namespace time_internal
+
+}  // namespace absl
+
+#endif  // ABSL_TIME_CIVIL_TIME_H_
diff --git a/absl/time/civil_time_benchmark.cc b/absl/time/civil_time_benchmark.cc
new file mode 100644
index 0000000..4086983
--- /dev/null
+++ b/absl/time/civil_time_benchmark.cc
@@ -0,0 +1,107 @@
+// 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.
+
+#include "absl/time/civil_time.h"
+
+#include <numeric>
+#include <vector>
+
+#include "absl/hash/hash.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+// Run on (12 X 3492 MHz CPUs); 2018-11-05T13:44:29.814239103-08:00
+// CPU: Intel Haswell with HyperThreading (6 cores) dL1:32KB dL2:256KB dL3:15MB
+// Benchmark                 Time(ns)        CPU(ns)     Iterations
+// ----------------------------------------------------------------
+// BM_Difference_Days              14.5           14.5     48531105
+// BM_Step_Days                    12.6           12.6     54876006
+// BM_Format                      587            587        1000000
+// BM_Parse                       692            692        1000000
+// BM_RoundTripFormatParse       1309           1309         532075
+// BM_CivilYearAbslHash             0.710          0.710  976400000
+// BM_CivilMonthAbslHash            1.13           1.13   619500000
+// BM_CivilDayAbslHash              1.70           1.70   426000000
+// BM_CivilHourAbslHash             2.45           2.45   287600000
+// BM_CivilMinuteAbslHash           3.21           3.21   226200000
+// BM_CivilSecondAbslHash           4.10           4.10   171800000
+
+void BM_Difference_Days(benchmark::State& state) {
+  const absl::CivilDay c(2014, 8, 22);
+  const absl::CivilDay epoch(1970, 1, 1);
+  while (state.KeepRunning()) {
+    const absl::civil_diff_t n = c - epoch;
+    benchmark::DoNotOptimize(n);
+  }
+}
+BENCHMARK(BM_Difference_Days);
+
+void BM_Step_Days(benchmark::State& state) {
+  const absl::CivilDay kStart(2014, 8, 22);
+  absl::CivilDay c = kStart;
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(++c);
+  }
+}
+BENCHMARK(BM_Step_Days);
+
+void BM_Format(benchmark::State& state) {
+  const absl::CivilSecond c(2014, 1, 2, 3, 4, 5);
+  while (state.KeepRunning()) {
+    const std::string s = absl::FormatCivilTime(c);
+    benchmark::DoNotOptimize(s);
+  }
+}
+BENCHMARK(BM_Format);
+
+template <typename T>
+void BM_CivilTimeAbslHash(benchmark::State& state) {
+  const int kSize = 100000;
+  std::vector<T> civil_times(kSize);
+  std::iota(civil_times.begin(), civil_times.end(), T(2018));
+
+  absl::Hash<T> absl_hasher;
+  while (state.KeepRunningBatch(kSize)) {
+    for (const T civil_time : civil_times) {
+      benchmark::DoNotOptimize(absl_hasher(civil_time));
+    }
+  }
+}
+void BM_CivilYearAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilYear>(state);
+}
+void BM_CivilMonthAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilMonth>(state);
+}
+void BM_CivilDayAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilDay>(state);
+}
+void BM_CivilHourAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilHour>(state);
+}
+void BM_CivilMinuteAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilMinute>(state);
+}
+void BM_CivilSecondAbslHash(benchmark::State& state) {
+  BM_CivilTimeAbslHash<absl::CivilSecond>(state);
+}
+BENCHMARK(BM_CivilYearAbslHash);
+BENCHMARK(BM_CivilMonthAbslHash);
+BENCHMARK(BM_CivilDayAbslHash);
+BENCHMARK(BM_CivilHourAbslHash);
+BENCHMARK(BM_CivilMinuteAbslHash);
+BENCHMARK(BM_CivilSecondAbslHash);
+
+}  // namespace
diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc
new file mode 100644
index 0000000..b8d5713
--- /dev/null
+++ b/absl/time/civil_time_test.cc
@@ -0,0 +1,1073 @@
+// 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.
+
+#include "absl/time/civil_time.h"
+
+#include <limits>
+#include <sstream>
+#include <type_traits>
+
+#include "absl/base/macros.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(CivilTime, DefaultConstruction) {
+  absl::CivilSecond ss;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_EQ("1970", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, StructMember) {
+  struct S {
+    absl::CivilDay day;
+  };
+  S s = {};
+  EXPECT_EQ(absl::CivilDay{}, s.day);
+}
+
+TEST(CivilTime, FieldsConstruction) {
+  EXPECT_EQ("2015-01-02T03:04:05",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02T03:04:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02T03:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02T00:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01T00:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015, 1)));
+  EXPECT_EQ("2015-01-01T00:00:00",
+            absl::FormatCivilTime(absl::CivilSecond(2015)));
+
+  EXPECT_EQ("2015-01-02T03:04",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02T03:04",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02T03:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02T00:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01T00:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015, 1)));
+  EXPECT_EQ("2015-01-01T00:00",
+            absl::FormatCivilTime(absl::CivilMinute(2015)));
+
+  EXPECT_EQ("2015-01-02T03",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02T03",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02T03",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02T00",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01T00",
+            absl::FormatCivilTime(absl::CivilHour(2015, 1)));
+  EXPECT_EQ("2015-01-01T00",
+            absl::FormatCivilTime(absl::CivilHour(2015)));
+
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01-02",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1, 2)));
+  EXPECT_EQ("2015-01-01",
+            absl::FormatCivilTime(absl::CivilDay(2015, 1)));
+  EXPECT_EQ("2015-01-01",
+            absl::FormatCivilTime(absl::CivilDay(2015)));
+
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2, 3)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1, 2)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015, 1)));
+  EXPECT_EQ("2015-01",
+            absl::FormatCivilTime(absl::CivilMonth(2015)));
+
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4, 5)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3, 4)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2, 3)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1, 2)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015, 1)));
+  EXPECT_EQ("2015",
+            absl::FormatCivilTime(absl::CivilYear(2015)));
+}
+
+TEST(CivilTime, FieldsConstructionLimits) {
+  const int kIntMax = std::numeric_limits<int>::max();
+  EXPECT_EQ("2038-01-19T03:14:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, 0, kIntMax)));
+  EXPECT_EQ("6121-02-11T05:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, kIntMax, kIntMax)));
+  EXPECT_EQ("251104-11-20T12:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, kIntMax, kIntMax, kIntMax)));
+  EXPECT_EQ("6130715-05-30T12:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, kIntMax, kIntMax, kIntMax, kIntMax)));
+  EXPECT_EQ("185087685-11-26T12:21:07",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, kIntMax, kIntMax, kIntMax, kIntMax, kIntMax)));
+
+  const int kIntMin = std::numeric_limits<int>::min();
+  EXPECT_EQ("1901-12-13T20:45:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, 0, kIntMin)));
+  EXPECT_EQ("-2182-11-20T18:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, 0, kIntMin, kIntMin)));
+  EXPECT_EQ("-247165-02-11T10:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, 1, kIntMin, kIntMin, kIntMin)));
+  EXPECT_EQ("-6126776-08-01T10:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, 1, kIntMin, kIntMin, kIntMin, kIntMin)));
+  EXPECT_EQ("-185083747-10-31T10:37:52",
+            absl::FormatCivilTime(absl::CivilSecond(
+                1970, kIntMin, kIntMin, kIntMin, kIntMin, kIntMin)));
+}
+
+TEST(CivilTime, RangeLimits) {
+  const absl::civil_year_t kYearMax =
+      std::numeric_limits<absl::civil_year_t>::max();
+  EXPECT_EQ(absl::CivilYear(kYearMax),
+            absl::CivilYear::max());
+  EXPECT_EQ(absl::CivilMonth(kYearMax, 12),
+            absl::CivilMonth::max());
+  EXPECT_EQ(absl::CivilDay(kYearMax, 12, 31),
+            absl::CivilDay::max());
+  EXPECT_EQ(absl::CivilHour(kYearMax, 12, 31, 23),
+            absl::CivilHour::max());
+  EXPECT_EQ(absl::CivilMinute(kYearMax, 12, 31, 23, 59),
+            absl::CivilMinute::max());
+  EXPECT_EQ(absl::CivilSecond(kYearMax, 12, 31, 23, 59, 59),
+            absl::CivilSecond::max());
+
+  const absl::civil_year_t kYearMin =
+      std::numeric_limits<absl::civil_year_t>::min();
+  EXPECT_EQ(absl::CivilYear(kYearMin),
+            absl::CivilYear::min());
+  EXPECT_EQ(absl::CivilMonth(kYearMin, 1),
+            absl::CivilMonth::min());
+  EXPECT_EQ(absl::CivilDay(kYearMin, 1, 1),
+            absl::CivilDay::min());
+  EXPECT_EQ(absl::CivilHour(kYearMin, 1, 1, 0),
+            absl::CivilHour::min());
+  EXPECT_EQ(absl::CivilMinute(kYearMin, 1, 1, 0, 0),
+            absl::CivilMinute::min());
+  EXPECT_EQ(absl::CivilSecond(kYearMin, 1, 1, 0, 0, 0),
+            absl::CivilSecond::min());
+}
+
+TEST(CivilTime, ImplicitCrossAlignment) {
+  absl::CivilYear year(2015);
+  absl::CivilMonth month = year;
+  absl::CivilDay day = month;
+  absl::CivilHour hour = day;
+  absl::CivilMinute minute = hour;
+  absl::CivilSecond second = minute;
+
+  second = year;
+  EXPECT_EQ(second, year);
+  second = month;
+  EXPECT_EQ(second, month);
+  second = day;
+  EXPECT_EQ(second, day);
+  second = hour;
+  EXPECT_EQ(second, hour);
+  second = minute;
+  EXPECT_EQ(second, minute);
+
+  minute = year;
+  EXPECT_EQ(minute, year);
+  minute = month;
+  EXPECT_EQ(minute, month);
+  minute = day;
+  EXPECT_EQ(minute, day);
+  minute = hour;
+  EXPECT_EQ(minute, hour);
+
+  hour = year;
+  EXPECT_EQ(hour, year);
+  hour = month;
+  EXPECT_EQ(hour, month);
+  hour = day;
+  EXPECT_EQ(hour, day);
+
+  day = year;
+  EXPECT_EQ(day, year);
+  day = month;
+  EXPECT_EQ(day, month);
+
+  month = year;
+  EXPECT_EQ(month, year);
+
+  // Ensures unsafe conversions are not allowed.
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilMinute>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilHour>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilDay>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilSecond, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilHour>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilDay>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMinute, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilHour, absl::CivilDay>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilHour, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilHour, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilDay, absl::CivilMonth>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilDay, absl::CivilYear>::value));
+
+  EXPECT_FALSE(
+      (std::is_convertible<absl::CivilMonth, absl::CivilYear>::value));
+}
+
+TEST(CivilTime, ExplicitCrossAlignment) {
+  //
+  // Assign from smaller units -> larger units
+  //
+
+  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second));
+
+  absl::CivilMinute minute(second);
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute));
+
+  absl::CivilHour hour(minute);
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour));
+
+  absl::CivilDay day(hour);
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day));
+
+  absl::CivilMonth month(day);
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month));
+
+  absl::CivilYear year(month);
+  EXPECT_EQ("2015", absl::FormatCivilTime(year));
+
+  //
+  // Now assign from larger units -> smaller units
+  //
+
+  month = absl::CivilMonth(year);
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month));
+
+  day = absl::CivilDay(month);
+  EXPECT_EQ("2015-01-01", absl::FormatCivilTime(day));
+
+  hour = absl::CivilHour(day);
+  EXPECT_EQ("2015-01-01T00", absl::FormatCivilTime(hour));
+
+  minute = absl::CivilMinute(hour);
+  EXPECT_EQ("2015-01-01T00:00", absl::FormatCivilTime(minute));
+
+  second = absl::CivilSecond(minute);
+  EXPECT_EQ("2015-01-01T00:00:00", absl::FormatCivilTime(second));
+}
+
+// Metafunction to test whether difference is allowed between two types.
+template <typename T1, typename T2>
+struct HasDiff {
+  template <typename U1, typename U2>
+  static std::false_type test(...);
+  template <typename U1, typename U2>
+  static std::true_type test(decltype(std::declval<U1>() - std::declval<U2>()));
+  static constexpr bool value = decltype(test<T1, T2>(0))::value;
+};
+
+TEST(CivilTime, DisallowCrossAlignedDifference) {
+  // Difference is allowed between types with the same alignment.
+  static_assert(HasDiff<absl::CivilSecond, absl::CivilSecond>::value, "");
+  static_assert(HasDiff<absl::CivilMinute, absl::CivilMinute>::value, "");
+  static_assert(HasDiff<absl::CivilHour, absl::CivilHour>::value, "");
+  static_assert(HasDiff<absl::CivilDay, absl::CivilDay>::value, "");
+  static_assert(HasDiff<absl::CivilMonth, absl::CivilMonth>::value, "");
+  static_assert(HasDiff<absl::CivilYear, absl::CivilYear>::value, "");
+
+  // Difference is disallowed between types with different alignments.
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilMinute>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilHour>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilDay>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilSecond, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilHour>::value, "");
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilDay>::value, "");
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilMinute, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilHour, absl::CivilDay>::value, "");
+  static_assert(!HasDiff<absl::CivilHour, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilHour, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilDay, absl::CivilMonth>::value, "");
+  static_assert(!HasDiff<absl::CivilDay, absl::CivilYear>::value, "");
+
+  static_assert(!HasDiff<absl::CivilMonth, absl::CivilYear>::value, "");
+}
+
+TEST(CivilTime, ValueSemantics) {
+  const absl::CivilHour a(2015, 1, 2, 3);
+  const absl::CivilHour b = a;
+  const absl::CivilHour c(b);
+  absl::CivilHour d;
+  d = c;
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(d));
+}
+
+TEST(CivilTime, Relational) {
+  // Tests that the alignment unit is ignored in comparison.
+  const absl::CivilYear year(2014);
+  const absl::CivilMonth month(year);
+  EXPECT_EQ(year, month);
+
+#define TEST_RELATIONAL(OLDER, YOUNGER) \
+  do {                                  \
+    EXPECT_FALSE(OLDER < OLDER);        \
+    EXPECT_FALSE(OLDER > OLDER);        \
+    EXPECT_TRUE(OLDER >= OLDER);        \
+    EXPECT_TRUE(OLDER <= OLDER);        \
+    EXPECT_FALSE(YOUNGER < YOUNGER);    \
+    EXPECT_FALSE(YOUNGER > YOUNGER);    \
+    EXPECT_TRUE(YOUNGER >= YOUNGER);    \
+    EXPECT_TRUE(YOUNGER <= YOUNGER);    \
+    EXPECT_EQ(OLDER, OLDER);            \
+    EXPECT_NE(OLDER, YOUNGER);          \
+    EXPECT_LT(OLDER, YOUNGER);          \
+    EXPECT_LE(OLDER, YOUNGER);          \
+    EXPECT_GT(YOUNGER, OLDER);          \
+    EXPECT_GE(YOUNGER, OLDER);          \
+  } while (0)
+
+  // Alignment is ignored in comparison (verified above), so CivilSecond is
+  // used to test comparison in all field positions.
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2015, 1, 1, 0, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2014, 2, 1, 0, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2014, 1, 2, 0, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 0, 0, 0),
+                  absl::CivilSecond(2014, 1, 1, 1, 0, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 0, 0),
+                  absl::CivilSecond(2014, 1, 1, 1, 1, 0));
+  TEST_RELATIONAL(absl::CivilSecond(2014, 1, 1, 1, 1, 0),
+                  absl::CivilSecond(2014, 1, 1, 1, 1, 1));
+
+  // Tests the relational operators of two different civil-time types.
+  TEST_RELATIONAL(absl::CivilDay(2014, 1, 1),
+                  absl::CivilMinute(2014, 1, 1, 1, 1));
+  TEST_RELATIONAL(absl::CivilDay(2014, 1, 1),
+                  absl::CivilMonth(2014, 2));
+
+#undef TEST_RELATIONAL
+}
+
+TEST(CivilTime, Arithmetic) {
+  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);
+  EXPECT_EQ("2015-01-02T03:04:06", absl::FormatCivilTime(second += 1));
+  EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(second + 1));
+  EXPECT_EQ("2015-01-02T03:04:08", absl::FormatCivilTime(2 + second));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second - 1));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second -= 1));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(second++));
+  EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(++second));
+  EXPECT_EQ("2015-01-02T03:04:07", absl::FormatCivilTime(second--));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(--second));
+
+  absl::CivilMinute minute(2015, 1, 2, 3, 4);
+  EXPECT_EQ("2015-01-02T03:05", absl::FormatCivilTime(minute += 1));
+  EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(minute + 1));
+  EXPECT_EQ("2015-01-02T03:07", absl::FormatCivilTime(2 + minute));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute - 1));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute -= 1));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(minute++));
+  EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(++minute));
+  EXPECT_EQ("2015-01-02T03:06", absl::FormatCivilTime(minute--));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(--minute));
+
+  absl::CivilHour hour(2015, 1, 2, 3);
+  EXPECT_EQ("2015-01-02T04", absl::FormatCivilTime(hour += 1));
+  EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(hour + 1));
+  EXPECT_EQ("2015-01-02T06", absl::FormatCivilTime(2 + hour));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour - 1));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour -= 1));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hour++));
+  EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(++hour));
+  EXPECT_EQ("2015-01-02T05", absl::FormatCivilTime(hour--));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(--hour));
+
+  absl::CivilDay day(2015, 1, 2);
+  EXPECT_EQ("2015-01-03", absl::FormatCivilTime(day += 1));
+  EXPECT_EQ("2015-01-04", absl::FormatCivilTime(day + 1));
+  EXPECT_EQ("2015-01-05", absl::FormatCivilTime(2 + day));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day - 1));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day -= 1));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(day++));
+  EXPECT_EQ("2015-01-04", absl::FormatCivilTime(++day));
+  EXPECT_EQ("2015-01-04", absl::FormatCivilTime(day--));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(--day));
+
+  absl::CivilMonth month(2015, 1);
+  EXPECT_EQ("2015-02", absl::FormatCivilTime(month += 1));
+  EXPECT_EQ("2015-03", absl::FormatCivilTime(month + 1));
+  EXPECT_EQ("2015-04", absl::FormatCivilTime(2 + month));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month - 1));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month -= 1));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(month++));
+  EXPECT_EQ("2015-03", absl::FormatCivilTime(++month));
+  EXPECT_EQ("2015-03", absl::FormatCivilTime(month--));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(--month));
+
+  absl::CivilYear year(2015);
+  EXPECT_EQ("2016", absl::FormatCivilTime(year += 1));
+  EXPECT_EQ("2017", absl::FormatCivilTime(year + 1));
+  EXPECT_EQ("2018", absl::FormatCivilTime(2 + year));
+  EXPECT_EQ("2015", absl::FormatCivilTime(year - 1));
+  EXPECT_EQ("2015", absl::FormatCivilTime(year -= 1));
+  EXPECT_EQ("2015", absl::FormatCivilTime(year++));
+  EXPECT_EQ("2017", absl::FormatCivilTime(++year));
+  EXPECT_EQ("2017", absl::FormatCivilTime(year--));
+  EXPECT_EQ("2015", absl::FormatCivilTime(--year));
+}
+
+TEST(CivilTime, ArithmeticLimits) {
+  const int kIntMax = std::numeric_limits<int>::max();
+  const int kIntMin = std::numeric_limits<int>::min();
+
+  absl::CivilSecond second(1970, 1, 1, 0, 0, 0);
+  second += kIntMax;
+  EXPECT_EQ("2038-01-19T03:14:07", absl::FormatCivilTime(second));
+  second -= kIntMax;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(second));
+  second += kIntMin;
+  EXPECT_EQ("1901-12-13T20:45:52", absl::FormatCivilTime(second));
+  second -= kIntMin;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(second));
+
+  absl::CivilMinute minute(1970, 1, 1, 0, 0);
+  minute += kIntMax;
+  EXPECT_EQ("6053-01-23T02:07", absl::FormatCivilTime(minute));
+  minute -= kIntMax;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(minute));
+  minute += kIntMin;
+  EXPECT_EQ("-2114-12-08T21:52", absl::FormatCivilTime(minute));
+  minute -= kIntMin;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(minute));
+
+  absl::CivilHour hour(1970, 1, 1, 0);
+  hour += kIntMax;
+  EXPECT_EQ("246953-10-09T07", absl::FormatCivilTime(hour));
+  hour -= kIntMax;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hour));
+  hour += kIntMin;
+  EXPECT_EQ("-243014-03-24T16", absl::FormatCivilTime(hour));
+  hour -= kIntMin;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hour));
+
+  absl::CivilDay day(1970, 1, 1);
+  day += kIntMax;
+  EXPECT_EQ("5881580-07-11", absl::FormatCivilTime(day));
+  day -= kIntMax;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(day));
+  day += kIntMin;
+  EXPECT_EQ("-5877641-06-23", absl::FormatCivilTime(day));
+  day -= kIntMin;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(day));
+
+  absl::CivilMonth month(1970, 1);
+  month += kIntMax;
+  EXPECT_EQ("178958940-08", absl::FormatCivilTime(month));
+  month -= kIntMax;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(month));
+  month += kIntMin;
+  EXPECT_EQ("-178955001-05", absl::FormatCivilTime(month));
+  month -= kIntMin;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(month));
+
+  absl::CivilYear year(0);
+  year += kIntMax;
+  EXPECT_EQ("2147483647", absl::FormatCivilTime(year));
+  year -= kIntMax;
+  EXPECT_EQ("0", absl::FormatCivilTime(year));
+  year += kIntMin;
+  EXPECT_EQ("-2147483648", absl::FormatCivilTime(year));
+  year -= kIntMin;
+  EXPECT_EQ("0", absl::FormatCivilTime(year));
+}
+
+TEST(CivilTime, Difference) {
+  absl::CivilSecond second(2015, 1, 2, 3, 4, 5);
+  EXPECT_EQ(0, second - second);
+  EXPECT_EQ(10, (second + 10) - second);
+  EXPECT_EQ(-10, (second - 10) - second);
+
+  absl::CivilMinute minute(2015, 1, 2, 3, 4);
+  EXPECT_EQ(0, minute - minute);
+  EXPECT_EQ(10, (minute + 10) - minute);
+  EXPECT_EQ(-10, (minute - 10) - minute);
+
+  absl::CivilHour hour(2015, 1, 2, 3);
+  EXPECT_EQ(0, hour - hour);
+  EXPECT_EQ(10, (hour + 10) - hour);
+  EXPECT_EQ(-10, (hour - 10) - hour);
+
+  absl::CivilDay day(2015, 1, 2);
+  EXPECT_EQ(0, day - day);
+  EXPECT_EQ(10, (day + 10) - day);
+  EXPECT_EQ(-10, (day - 10) - day);
+
+  absl::CivilMonth month(2015, 1);
+  EXPECT_EQ(0, month - month);
+  EXPECT_EQ(10, (month + 10) - month);
+  EXPECT_EQ(-10, (month - 10) - month);
+
+  absl::CivilYear year(2015);
+  EXPECT_EQ(0, year - year);
+  EXPECT_EQ(10, (year + 10) - year);
+  EXPECT_EQ(-10, (year - 10) - year);
+}
+
+TEST(CivilTime, DifferenceLimits) {
+  const absl::civil_diff_t kDiffMax =
+      std::numeric_limits<absl::civil_diff_t>::max();
+  const absl::civil_diff_t kDiffMin =
+      std::numeric_limits<absl::civil_diff_t>::min();
+
+  // Check day arithmetic at the end of the year range.
+  const absl::CivilDay max_day(kDiffMax, 12, 31);
+  EXPECT_EQ(1, max_day - (max_day - 1));
+  EXPECT_EQ(-1, (max_day - 1) - max_day);
+
+  // Check day arithmetic at the start of the year range.
+  const absl::CivilDay min_day(kDiffMin, 1, 1);
+  EXPECT_EQ(1, (min_day + 1) - min_day);
+  EXPECT_EQ(-1, min_day - (min_day + 1));
+
+  // Check the limits of the return value.
+  const absl::CivilDay d1(1970, 1, 1);
+  const absl::CivilDay d2(25252734927768524, 7, 27);
+  EXPECT_EQ(kDiffMax, d2 - d1);
+  EXPECT_EQ(kDiffMin, d1 - (d2 + 1));
+}
+
+TEST(CivilTime, Properties) {
+  absl::CivilSecond ss(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, ss.year());
+  EXPECT_EQ(2, ss.month());
+  EXPECT_EQ(3, ss.day());
+  EXPECT_EQ(4, ss.hour());
+  EXPECT_EQ(5, ss.minute());
+  EXPECT_EQ(6, ss.second());
+
+  absl::CivilMinute mm(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, mm.year());
+  EXPECT_EQ(2, mm.month());
+  EXPECT_EQ(3, mm.day());
+  EXPECT_EQ(4, mm.hour());
+  EXPECT_EQ(5, mm.minute());
+  EXPECT_EQ(0, mm.second());
+
+  absl::CivilHour hh(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, hh.year());
+  EXPECT_EQ(2, hh.month());
+  EXPECT_EQ(3, hh.day());
+  EXPECT_EQ(4, hh.hour());
+  EXPECT_EQ(0, hh.minute());
+  EXPECT_EQ(0, hh.second());
+
+  absl::CivilDay d(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, d.year());
+  EXPECT_EQ(2, d.month());
+  EXPECT_EQ(3, d.day());
+  EXPECT_EQ(0, d.hour());
+  EXPECT_EQ(0, d.minute());
+  EXPECT_EQ(0, d.second());
+
+  absl::CivilMonth m(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, m.year());
+  EXPECT_EQ(2, m.month());
+  EXPECT_EQ(1, m.day());
+  EXPECT_EQ(0, m.hour());
+  EXPECT_EQ(0, m.minute());
+  EXPECT_EQ(0, m.second());
+
+  absl::CivilYear y(2015, 2, 3, 4, 5, 6);
+  EXPECT_EQ(2015, y.year());
+  EXPECT_EQ(1, y.month());
+  EXPECT_EQ(1, y.day());
+  EXPECT_EQ(0, y.hour());
+  EXPECT_EQ(0, y.minute());
+  EXPECT_EQ(0, y.second());
+}
+
+TEST(CivilTime, Format) {
+  absl::CivilSecond ss;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_EQ("1970", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, FormatAndParseLenient) {
+  absl::CivilSecond ss;
+  EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_EQ("1970-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_EQ("1970-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_EQ("1970-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_EQ("1970-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_EQ("1970", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, OutputStream) {
+  absl::CivilSecond cs(2016, 2, 3, 4, 5, 6);
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilYear(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016.................X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilMonth(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02..............X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilDay(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03...........X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilHour(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03T04........X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilMinute(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03T04:05.....X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::CivilSecond(cs);
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..2016-02-03T04:05:06..X..", ss.str());
+  }
+  {
+    std::stringstream ss;
+    ss << std::left << std::setfill('.');
+    ss << std::setw(3) << 'X';
+    ss << std::setw(21) << absl::Weekday::wednesday;
+    ss << std::setw(3) << 'X';
+    EXPECT_EQ("X..Wednesday............X..", ss.str());
+  }
+}
+
+TEST(CivilTime, Weekday) {
+  absl::CivilDay d(1970, 1, 1);
+  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(d)) << d;
+
+  // We used to get this wrong for years < -30.
+  d = absl::CivilDay(-31, 12, 24);
+  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(d)) << d;
+}
+
+TEST(CivilTime, NextPrevWeekday) {
+  // Jan 1, 1970 was a Thursday.
+  const absl::CivilDay thursday(1970, 1, 1);
+
+  // Thursday -> Thursday
+  absl::CivilDay d = absl::NextWeekday(thursday, absl::Weekday::thursday);
+  EXPECT_EQ(7, d - thursday) << d;
+  EXPECT_EQ(d - 14, absl::PrevWeekday(thursday, absl::Weekday::thursday));
+
+  // Thursday -> Friday
+  d = absl::NextWeekday(thursday, absl::Weekday::friday);
+  EXPECT_EQ(1, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::friday));
+
+  // Thursday -> Saturday
+  d = absl::NextWeekday(thursday, absl::Weekday::saturday);
+  EXPECT_EQ(2, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::saturday));
+
+  // Thursday -> Sunday
+  d = absl::NextWeekday(thursday, absl::Weekday::sunday);
+  EXPECT_EQ(3, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::sunday));
+
+  // Thursday -> Monday
+  d = absl::NextWeekday(thursday, absl::Weekday::monday);
+  EXPECT_EQ(4, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::monday));
+
+  // Thursday -> Tuesday
+  d = absl::NextWeekday(thursday, absl::Weekday::tuesday);
+  EXPECT_EQ(5, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::tuesday));
+
+  // Thursday -> Wednesday
+  d = absl::NextWeekday(thursday, absl::Weekday::wednesday);
+  EXPECT_EQ(6, d - thursday) << d;
+  EXPECT_EQ(d - 7, absl::PrevWeekday(thursday, absl::Weekday::wednesday));
+}
+
+// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+TEST(CivilTime, DifferenceWithHugeYear) {
+  absl::CivilDay d1(9223372036854775807, 1, 1);
+  absl::CivilDay d2(9223372036854775807, 12, 31);
+  EXPECT_EQ(364, d2 - d1);
+
+  d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1);
+  d2 = absl::CivilDay(-9223372036854775807 - 1, 12, 31);
+  EXPECT_EQ(365, d2 - d1);
+
+  // Check the limits of the return value at the end of the year range.
+  d1 = absl::CivilDay(9223372036854775807, 1, 1);
+  d2 = absl::CivilDay(9198119301927009252, 6, 6);
+  EXPECT_EQ(9223372036854775807, d1 - d2);
+  d2 = d2 - 1;
+  EXPECT_EQ(-9223372036854775807 - 1, d2 - d1);
+
+  // Check the limits of the return value at the start of the year range.
+  d1 = absl::CivilDay(-9223372036854775807 - 1, 1, 1);
+  d2 = absl::CivilDay(-9198119301927009254, 7, 28);
+  EXPECT_EQ(9223372036854775807, d2 - d1);
+  d2 = d2 + 1;
+  EXPECT_EQ(-9223372036854775807 - 1, d1 - d2);
+
+  // Check the limits of the return value from either side of year 0.
+  d1 = absl::CivilDay(-12626367463883278, 9, 3);
+  d2 = absl::CivilDay(12626367463883277, 3, 28);
+  EXPECT_EQ(9223372036854775807, d2 - d1);
+  d2 = d2 + 1;
+  EXPECT_EQ(-9223372036854775807 - 1, d1 - d2);
+}
+
+// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+TEST(CivilTime, DifferenceNoIntermediateOverflow) {
+  // The difference up to the minute field would be below the minimum
+  // int64_t, but the 52 extra seconds brings us back to the minimum.
+  absl::CivilSecond s1(-292277022657, 1, 27, 8, 29 - 1, 52);
+  absl::CivilSecond s2(1970, 1, 1, 0, 0 - 1, 0);
+  EXPECT_EQ(-9223372036854775807 - 1, s1 - s2);
+
+  // The difference up to the minute field would be above the maximum
+  // int64_t, but the -53 extra seconds brings us back to the maximum.
+  s1 = absl::CivilSecond(292277026596, 12, 4, 15, 30, 7 - 7);
+  s2 = absl::CivilSecond(1970, 1, 1, 0, 0, 0 - 7);
+  EXPECT_EQ(9223372036854775807, s1 - s2);
+}
+
+TEST(CivilTime, NormalizeSimpleOverflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 59 + 1);
+  EXPECT_EQ("2013-11-15T16:33:00", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 59 + 1, 14);
+  EXPECT_EQ("2013-11-15T17:00:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 23 + 1, 32, 14);
+  EXPECT_EQ("2013-11-16T00:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 30 + 1, 16, 32, 14);
+  EXPECT_EQ("2013-12-01T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 12 + 1, 15, 16, 32, 14);
+  EXPECT_EQ("2014-01-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeSimpleUnderflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 0 - 1);
+  EXPECT_EQ("2013-11-15T16:31:59", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 0 - 1, 14);
+  EXPECT_EQ("2013-11-15T15:59:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 0 - 1, 32, 14);
+  EXPECT_EQ("2013-11-14T23:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 1 - 1, 16, 32, 14);
+  EXPECT_EQ("2013-10-31T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 1 - 1, 15, 16, 32, 14);
+  EXPECT_EQ("2012-12-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeMultipleOverflow) {
+  absl::CivilSecond cs(2013, 12, 31, 23, 59, 59 + 1);
+  EXPECT_EQ("2014-01-01T00:00:00", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeMultipleUnderflow) {
+  absl::CivilSecond cs(2014, 1, 1, 0, 0, 0 - 1);
+  EXPECT_EQ("2013-12-31T23:59:59", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeOverflowLimits) {
+  absl::CivilSecond cs;
+
+  const int kintmax = std::numeric_limits<int>::max();
+  cs = absl::CivilSecond(0, kintmax, kintmax, kintmax, kintmax, kintmax);
+  EXPECT_EQ("185085715-11-27T12:21:07", absl::FormatCivilTime(cs));
+
+  const int kintmin = std::numeric_limits<int>::min();
+  cs = absl::CivilSecond(0, kintmin, kintmin, kintmin, kintmin, kintmin);
+  EXPECT_EQ("-185085717-10-31T10:37:52", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeComplexOverflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 + 123456789);
+  EXPECT_EQ("2017-10-14T14:05:23", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32 + 1234567, 14);
+  EXPECT_EQ("2016-03-22T00:39:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16 + 123456, 32, 14);
+  EXPECT_EQ("2027-12-16T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15 + 1234, 16, 32, 14);
+  EXPECT_EQ("2017-04-02T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 + 123, 15, 16, 32, 14);
+  EXPECT_EQ("2024-02-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeComplexUnderflow) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(1999, 3, 0, 0, 0, 0);  // year 400
+  EXPECT_EQ("1999-02-28T00:00:00", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32, 14 - 123456789);
+  EXPECT_EQ("2009-12-17T18:59:05", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16, 32 - 1234567, 14);
+  EXPECT_EQ("2011-07-12T08:25:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15, 16 - 123456, 32, 14);
+  EXPECT_EQ("1999-10-16T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11, 15 - 1234, 16, 32, 14);
+  EXPECT_EQ("2010-06-30T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 - 123, 15, 16, 32, 14);
+  EXPECT_EQ("2003-08-15T16:32:14", absl::FormatCivilTime(cs));
+}
+
+TEST(CivilTime, NormalizeMishmash) {
+  absl::CivilSecond cs;
+  cs = absl::CivilSecond(2013, 11 - 123, 15 + 1234, 16 - 123456, 32 + 1234567,
+                         14 - 123456789);
+  EXPECT_EQ("1991-05-09T03:06:05", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 + 123, 15 - 1234, 16 + 123456, 32 - 1234567,
+                         14 + 123456789);
+  EXPECT_EQ("2036-05-24T05:58:23", absl::FormatCivilTime(cs));
+
+  cs = absl::CivilSecond(2013, 11, -146097 + 1, 16, 32, 14);
+  EXPECT_EQ("1613-11-01T16:32:14", absl::FormatCivilTime(cs));
+  cs = absl::CivilSecond(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14);
+  EXPECT_EQ("2013-11-01T16:32:14", absl::FormatCivilTime(cs));
+}
+
+// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)
+// and check that they normalize to the expected time.  146097 days span
+// the 400-year Gregorian cycle used during normalization.
+TEST(CivilTime, NormalizeAllTheDays) {
+  absl::CivilDay expected(1970, 1, 1);
+  for (int day = 1; day <= 146097; ++day) {
+    absl::CivilSecond cs(1970, 1, day, 0, 0, 0);
+    EXPECT_EQ(expected, cs);
+    ++expected;
+  }
+}
+
+TEST(CivilTime, NormalizeWithHugeYear) {
+  absl::CivilMonth c(9223372036854775807, 1);
+  EXPECT_EQ("9223372036854775807-01", absl::FormatCivilTime(c));
+  c = c - 1;  // Causes normalization
+  EXPECT_EQ("9223372036854775806-12", absl::FormatCivilTime(c));
+
+  c = absl::CivilMonth(-9223372036854775807 - 1, 1);
+  EXPECT_EQ("-9223372036854775808-01", absl::FormatCivilTime(c));
+  c = c + 12;  // Causes normalization
+  EXPECT_EQ("-9223372036854775807-01", absl::FormatCivilTime(c));
+}
+
+TEST(CivilTime, LeapYears) {
+  const absl::CivilSecond s1(2013, 2, 28 + 1, 0, 0, 0);
+  EXPECT_EQ("2013-03-01T00:00:00", absl::FormatCivilTime(s1));
+
+  const absl::CivilSecond s2(2012, 2, 28 + 1, 0, 0, 0);
+  EXPECT_EQ("2012-02-29T00:00:00", absl::FormatCivilTime(s2));
+
+  const absl::CivilSecond s3(1900, 2, 28 + 1, 0, 0, 0);
+  EXPECT_EQ("1900-03-01T00:00:00", absl::FormatCivilTime(s3));
+
+  const struct {
+    int year;
+    int days;
+    struct {
+      int month;
+      int day;
+    } leap_day;  // The date of the day after Feb 28.
+  } kLeapYearTable[]{
+      {1900, 365, {3, 1}},
+      {1999, 365, {3, 1}},
+      {2000, 366, {2, 29}},  // leap year
+      {2001, 365, {3, 1}},
+      {2002, 365, {3, 1}},
+      {2003, 365, {3, 1}},
+      {2004, 366, {2, 29}},  // leap year
+      {2005, 365, {3, 1}},
+      {2006, 365, {3, 1}},
+      {2007, 365, {3, 1}},
+      {2008, 366, {2, 29}},  // leap year
+      {2009, 365, {3, 1}},
+      {2100, 365, {3, 1}},
+  };
+
+  for (int i = 0; i < ABSL_ARRAYSIZE(kLeapYearTable); ++i) {
+    const int y = kLeapYearTable[i].year;
+    const int m = kLeapYearTable[i].leap_day.month;
+    const int d = kLeapYearTable[i].leap_day.day;
+    const int n = kLeapYearTable[i].days;
+
+    // Tests incrementing through the leap day.
+    const absl::CivilDay feb28(y, 2, 28);
+    const absl::CivilDay next_day = feb28 + 1;
+    EXPECT_EQ(m, next_day.month());
+    EXPECT_EQ(d, next_day.day());
+
+    // Tests difference in days of leap years.
+    const absl::CivilYear year(feb28);
+    const absl::CivilYear next_year = year + 1;
+    EXPECT_EQ(n, absl::CivilDay(next_year) - absl::CivilDay(year));
+  }
+}
+
+TEST(CivilTime, FirstThursdayInMonth) {
+  const absl::CivilDay nov1(2014, 11, 1);
+  const absl::CivilDay thursday =
+      absl::PrevWeekday(nov1, absl::Weekday::thursday) + 7;
+  EXPECT_EQ("2014-11-06", absl::FormatCivilTime(thursday));
+
+  // Bonus: Date of Thanksgiving in the United States
+  // Rule: Fourth Thursday of November
+  const absl::CivilDay thanksgiving = thursday +  7 * 3;
+  EXPECT_EQ("2014-11-27", absl::FormatCivilTime(thanksgiving));
+}
+
+TEST(CivilTime, DocumentationExample) {
+  absl::CivilSecond second(2015, 6, 28, 1, 2, 3);  // 2015-06-28 01:02:03
+  absl::CivilMinute minute(second);                // 2015-06-28 01:02:00
+  absl::CivilDay day(minute);                      // 2015-06-28 00:00:00
+
+  second -= 1;                    // 2015-06-28 01:02:02
+  --second;                       // 2015-06-28 01:02:01
+  EXPECT_EQ(minute, second - 1);  // Comparison between types
+  EXPECT_LT(minute, second);
+
+  // int diff = second - minute;  // ERROR: Mixed types, won't compile
+
+  absl::CivilDay june_1(2015, 6, 1);  // Pass fields to c'tor.
+  int diff = day - june_1;            // Num days between 'day' and June 1
+  EXPECT_EQ(27, diff);
+
+  // Fields smaller than alignment are floored to their minimum value.
+  absl::CivilDay day_floor(2015, 1, 2, 9, 9, 9);
+  EXPECT_EQ(0, day_floor.hour());  // 09:09:09 is floored
+  EXPECT_EQ(absl::CivilDay(2015, 1, 2), day_floor);
+
+  // Unspecified fields default to their minium value
+  absl::CivilDay day_default(2015);  // Defaults to Jan 1
+  EXPECT_EQ(absl::CivilDay(2015, 1, 1), day_default);
+
+  // Iterates all the days of June.
+  absl::CivilMonth june(day);  // CivilDay -> CivilMonth
+  absl::CivilMonth july = june + 1;
+  for (absl::CivilDay day = june_1; day < july; ++day) {
+    // ...
+  }
+}
+
+}  // namespace
diff --git a/absl/time/clock.cc b/absl/time/clock.cc
index 74ee140..fa0ed34 100644
--- a/absl/time/clock.cc
+++ b/absl/time/clock.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -379,7 +379,7 @@
 //
 // Manually mark this 'noinline' to minimize stack frame size of the fast
 // path.  Without this, sometimes a compiler may inline this big block of code
-// into the fast past.  That causes lots of register spills and reloads that
+// into the fast path.  That causes lots of register spills and reloads that
 // are unnecessary unless the slow path is taken.
 //
 // TODO(absl-team): Remove this attribute when our compiler is smart enough
diff --git a/absl/time/clock.h b/absl/time/clock.h
index 3753d4e..bb52e4f 100644
--- a/absl/time/clock.h
+++ b/absl/time/clock.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/time/clock_benchmark.cc b/absl/time/clock_benchmark.cc
index 3d3cd9d..a69fe00 100644
--- a/absl/time/clock_benchmark.cc
+++ b/absl/time/clock_benchmark.cc
@@ -3,7 +3,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/time/clock_test.cc b/absl/time/clock_test.cc
index 707166d..4bcfc6b 100644
--- a/absl/time/clock_test.cc
+++ b/absl/time/clock_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 2950c7c..67791fe 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -78,10 +78,16 @@
 
 // Can't use std::isinfinite() because it doesn't exist on windows.
 inline bool IsFinite(double d) {
+  if (std::isnan(d)) return false;
   return d != std::numeric_limits<double>::infinity() &&
          d != -std::numeric_limits<double>::infinity();
 }
 
+inline bool IsValidDivisor(double d) {
+  if (std::isnan(d)) return false;
+  return d != 0.0;
+}
+
 // Can't use std::round() because it is only available in C++11.
 // Note that we ignore the possibility of floating-point over/underflow.
 template <typename Double>
@@ -455,7 +461,7 @@
 }
 
 Duration& Duration::operator/=(double r) {
-  if (time_internal::IsInfiniteDuration(*this) || r == 0.0) {
+  if (time_internal::IsInfiniteDuration(*this) || !IsValidDivisor(r)) {
     const bool is_neg = (std::signbit(r) != 0) != (rep_hi_ < 0);
     return *this = is_neg ? -InfiniteDuration() : InfiniteDuration();
   }
@@ -743,9 +749,9 @@
 
 }  // namespace
 
-// From Go's doc at http://golang.org/pkg/time/#Duration.String
+// From Go's doc at https://golang.org/pkg/time/#Duration.String
 //   [FormatDuration] returns a string representing the duration in the
-//   form "72h3m0.5s".  Leading zero units are omitted.  As a special
+//   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.
@@ -849,8 +855,8 @@
 
 }  // namespace
 
-// From Go's doc at http://golang.org/pkg/time/#ParseDuration
-//   [ParseDuration] parses a duration string.  A duration string is
+// From Go's doc at https://golang.org/pkg/time/#ParseDuration
+//   [ParseDuration] parses a duration string. A duration string is
 //   a possibly signed sequence of decimal numbers, each with optional
 //   fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
 //   Valid time units are "ns", "us" "ms", "s", "m", "h".
@@ -895,6 +901,7 @@
   *d = dur;
   return true;
 }
+
 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
   return ParseDuration(text, dst);
 }
diff --git a/absl/time/duration_benchmark.cc b/absl/time/duration_benchmark.cc
index d5657bd..83a836c 100644
--- a/absl/time/duration_benchmark.cc
+++ b/absl/time/duration_benchmark.cc
@@ -3,7 +3,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,6 +17,7 @@
 #include <ctime>
 #include <string>
 
+#include "absl/base/attributes.h"
 #include "absl/time/time.h"
 #include "benchmark/benchmark.h"
 
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 7ae25dc..e3cede6 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -56,6 +56,17 @@
   return false;
 }
 
+TEST(Duration, ConstExpr) {
+  constexpr absl::Duration d0 = absl::ZeroDuration();
+  static_assert(d0 == absl::ZeroDuration(), "ZeroDuration()");
+  constexpr absl::Duration d1 = absl::Seconds(1);
+  static_assert(d1 == absl::Seconds(1), "Seconds(1)");
+  static_assert(d1 != absl::ZeroDuration(), "Seconds(1)");
+  constexpr absl::Duration d2 = absl::InfiniteDuration();
+  static_assert(d2 == absl::InfiniteDuration(), "InfiniteDuration()");
+  static_assert(d2 != absl::ZeroDuration(), "InfiniteDuration()");
+}
+
 TEST(Duration, ValueSemantics) {
   // If this compiles, the test passes.
   constexpr absl::Duration a;      // Default construction
@@ -792,6 +803,40 @@
   EXPECT_EQ(-dbl_inf, absl::FDivDuration(-any_dur, zero));
 }
 
+TEST(Duration, NaN) {
+  // Note that IEEE 754 does not define the behavior of a nan's sign when it is
+  // copied, so the code below allows for either + or - InfiniteDuration.
+#define TEST_NAN_HANDLING(NAME, NAN)           \
+  do {                                         \
+    const auto inf = absl::InfiniteDuration(); \
+    auto x = NAME(NAN);                        \
+    EXPECT_TRUE(x == inf || x == -inf);        \
+    auto y = NAME(42);                         \
+    y *= NAN;                                  \
+    EXPECT_TRUE(y == inf || y == -inf);        \
+    auto z = NAME(42);                         \
+    z /= NAN;                                  \
+    EXPECT_TRUE(z == inf || z == -inf);        \
+  } while (0)
+
+  const double nan = std::numeric_limits<double>::quiet_NaN();
+  TEST_NAN_HANDLING(absl::Nanoseconds, nan);
+  TEST_NAN_HANDLING(absl::Microseconds, nan);
+  TEST_NAN_HANDLING(absl::Milliseconds, nan);
+  TEST_NAN_HANDLING(absl::Seconds, nan);
+  TEST_NAN_HANDLING(absl::Minutes, nan);
+  TEST_NAN_HANDLING(absl::Hours, nan);
+
+  TEST_NAN_HANDLING(absl::Nanoseconds, -nan);
+  TEST_NAN_HANDLING(absl::Microseconds, -nan);
+  TEST_NAN_HANDLING(absl::Milliseconds, -nan);
+  TEST_NAN_HANDLING(absl::Seconds, -nan);
+  TEST_NAN_HANDLING(absl::Minutes, -nan);
+  TEST_NAN_HANDLING(absl::Hours, -nan);
+
+#undef TEST_NAN_HANDLING
+}
+
 TEST(Duration, Range) {
   const absl::Duration range = ApproxYears(100 * 1e9);
   const absl::Duration range_future = range;
@@ -1726,7 +1771,7 @@
 TEST(Duration, FormatParseRoundTrip) {
 #define TEST_PARSE_ROUNDTRIP(d)                \
   do {                                         \
-    std::string s = absl::FormatDuration(d);        \
+    std::string s = absl::FormatDuration(d);   \
     absl::Duration dur;                        \
     EXPECT_TRUE(absl::ParseDuration(s, &dur)); \
     EXPECT_EQ(d, dur);                         \
diff --git a/absl/time/format.cc b/absl/time/format.cc
index ee597e4..d6ca860 100644
--- a/absl/time/format.cc
+++ b/absl/time/format.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -67,7 +67,8 @@
 
 }  // namespace
 
-std::string FormatTime(const std::string& format, absl::Time t, absl::TimeZone tz) {
+std::string FormatTime(const std::string& format, absl::Time t,
+                       absl::TimeZone tz) {
   if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
   if (t == absl::InfinitePast()) return kInfinitePastStr;
   const auto parts = Split(t);
@@ -83,15 +84,15 @@
   return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
 }
 
-bool ParseTime(const std::string& format, const std::string& input, absl::Time* time,
-               std::string* err) {
+bool ParseTime(const std::string& format, const std::string& input,
+               absl::Time* time, std::string* err) {
   return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);
 }
 
 // If the input string does not contain an explicit UTC offset, interpret
 // the fields with respect to the given TimeZone.
-bool ParseTime(const std::string& format, const std::string& input, absl::TimeZone tz,
-               absl::Time* time, std::string* err) {
+bool ParseTime(const std::string& format, const std::string& input,
+               absl::TimeZone tz, absl::Time* time, std::string* err) {
   const char* data = input.c_str();
   while (std::isspace(*data)) ++data;
 
diff --git a/absl/time/format_benchmark.cc b/absl/time/format_benchmark.cc
index ee53d71..249c51d 100644
--- a/absl/time/format_benchmark.cc
+++ b/absl/time/format_benchmark.cc
@@ -3,7 +3,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -38,7 +38,8 @@
   const absl::TimeZone lax =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
   const absl::Time t =
-      absl::FromDateTime(1977, 6, 28, 9, 8, 7, lax) + absl::Nanoseconds(1);
+      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) +
+      absl::Nanoseconds(1);
   while (state.KeepRunning()) {
     benchmark::DoNotOptimize(absl::FormatTime(fmt, t, lax).length());
   }
@@ -50,8 +51,8 @@
   state.SetLabel(fmt);
   const absl::TimeZone lax =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
-  absl::Time t =
-      absl::FromDateTime(1977, 6, 28, 9, 8, 7, lax) + absl::Nanoseconds(1);
+  absl::Time t = absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax) +
+                 absl::Nanoseconds(1);
   const std::string when = absl::FormatTime(fmt, t, lax);
   std::string err;
   while (state.KeepRunning()) {
diff --git a/absl/time/format_test.cc b/absl/time/format_test.cc
index 7c84c33..4a1f1aa 100644
--- a/absl/time/format_test.cc
+++ b/absl/time/format_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -27,8 +27,8 @@
 
 // A helper that tests the given format specifier by itself, and with leading
 // and trailing characters.  For example: TestFormatSpecifier(t, "%a", "Thu").
-void TestFormatSpecifier(absl::Time t, absl::TimeZone tz, const std::string& fmt,
-                         const std::string& ans) {
+void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
+                         const std::string& fmt, const std::string& ans) {
   EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
   EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
   EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
@@ -118,7 +118,7 @@
   absl::TimeZone tz = absl::UTCTimeZone();
 
   // A year of 77 should be padded to 0077.
-  absl::Time t = absl::FromDateTime(77, 6, 28, 9, 8, 7, tz);
+  absl::Time t = absl::FromCivil(absl::CivilSecond(77, 6, 28, 9, 8, 7), tz);
   EXPECT_EQ("Mon, 28 Jun 0077 09:08:07 +0000",
             absl::FormatTime(absl::RFC1123_full, t, tz));
   EXPECT_EQ("28 Jun 0077 09:08:07 +0000",
@@ -154,9 +154,9 @@
   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
                               "2013-06-28 19:08:09 -0800", &t, &err))
       << err;
-  absl::Time::Breakdown bd = t.In(absl::FixedTimeZone(-8 * 60 * 60));
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -8 * 60 * 60, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
+  const auto ci = absl::FixedTimeZone(-8 * 60 * 60).At(t);
+  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 }
 
 TEST(ParseTime, NullErrorString) {
@@ -177,17 +177,17 @@
   EXPECT_TRUE(
       absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
       << e;
-  absl::Time::Breakdown bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
+  auto ci = tz.At(t);
+  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 
   // But the timezone is ignored when a UTC offset is present.
   EXPECT_TRUE(absl::ParseTime("%Y-%m-%d %H:%M:%S %z",
                               "2013-06-28 19:08:09 +0800", tz, &t, &e))
       << e;
-  bd = t.In(absl::FixedTimeZone(8 * 60 * 60));
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 6, 28, 19, 8, 9, 8 * 60 * 60, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
+  ci = absl::FixedTimeZone(8 * 60 * 60).At(t);
+  EXPECT_EQ(absl::CivilSecond(2013, 6, 28, 19, 8, 9), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
 }
 
 TEST(ParseTime, ErrorCases) {
@@ -332,15 +332,15 @@
   EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
                               &t, &err));
   EXPECT_NE(absl::InfiniteFuture(), t);
-  EXPECT_EQ(3, t.In(tz).hour);
-  EXPECT_EQ(4, t.In(tz).minute);
+  EXPECT_EQ(3, tz.At(t).cs.hour());
+  EXPECT_EQ(4, tz.At(t).cs.minute());
 
   // "infinite-past" as literal std::string
   EXPECT_TRUE(
       absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
   EXPECT_NE(absl::InfinitePast(), t);
-  EXPECT_EQ(3, t.In(tz).hour);
-  EXPECT_EQ(4, t.In(tz).minute);
+  EXPECT_EQ(3, tz.At(t).cs.hour());
+  EXPECT_EQ(4, tz.At(t).cs.minute());
 
   // The input doesn't match the format.
   EXPECT_FALSE(absl::ParseTime("infinite-future %H:%M", "03:04", &t, &err));
@@ -365,16 +365,18 @@
 //
 
 TEST(FormatParse, RoundTrip) {
-  const absl::TimeZone gst =
+  const absl::TimeZone lax =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
-  const absl::Time in = absl::FromDateTime(1977, 6, 28, 9, 8, 7, gst);
+  const absl::Time in =
+      absl::FromCivil(absl::CivilSecond(1977, 6, 28, 9, 8, 7), lax);
   const absl::Duration subseconds = absl::Nanoseconds(654321);
   std::string err;
 
   // RFC3339, which renders subseconds.
   {
     absl::Time out;
-    const std::string s = absl::FormatTime(absl::RFC3339_full, in + subseconds, gst);
+    const std::string s =
+        absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
     EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
         << s << ": " << err;
     EXPECT_EQ(in + subseconds, out);  // RFC3339_full includes %Ez
@@ -383,7 +385,7 @@
   // RFC1123, which only does whole seconds.
   {
     absl::Time out;
-    const std::string s = absl::FormatTime(absl::RFC1123_full, in, gst);
+    const std::string s = absl::FormatTime(absl::RFC1123_full, in, lax);
     EXPECT_TRUE(absl::ParseTime(absl::RFC1123_full, s, &out, &err))
         << s << ": " << err;
     EXPECT_EQ(in, out);  // RFC1123_full includes %z
@@ -393,7 +395,12 @@
   // work. On Windows, `absl::ParseTime()` falls back to std::get_time() which
   // appears to fail on "%c" (or at least on the "%c" text produced by
   // `strftime()`). This makes it fail the round-trip test.
-#ifndef _MSC_VER
+  //
+  // Under the emscripten compiler `absl::ParseTime() falls back to
+  // `strptime()`, but that ends up using a different definition for "%c"
+  // compared to `strftime()`, also causing the round-trip test to fail
+  // (see https://github.com/kripken/emscripten/pull/7491).
+#if !defined(_MSC_VER) && !defined(__EMSCRIPTEN__)
   // Even though we don't know what %c will produce, it should roundtrip,
   // but only in the 0-offset timezone.
   {
@@ -402,7 +409,7 @@
     EXPECT_TRUE(absl::ParseTime("%c", s, &out, &err)) << s << ": " << err;
     EXPECT_EQ(in, out);
   }
-#endif  // _MSC_VER
+#endif  // !_MSC_VER && !__EMSCRIPTEN__
 }
 
 TEST(FormatParse, RoundTripDistantFuture) {
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 9f1ba21..903499b 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -4,7 +4,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#   http://www.apache.org/licenses/LICENSE-2.0
+#   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,
@@ -12,6 +12,8 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+package(features = ["-parse_headers"])
+
 licenses(["notice"])  # Apache License
 
 ### libraries
@@ -85,6 +87,7 @@
         "no_test_android_arm",
         "no_test_android_arm64",
         "no_test_android_x86",
+        "no_test_wasm",
     ],
     deps = [
         ":civil_time",
@@ -96,12 +99,14 @@
 cc_test(
     name = "time_zone_lookup_test",
     size = "small",
+    timeout = "moderate",
     srcs = ["src/time_zone_lookup_test.cc"],
     data = [":zoneinfo"],
     tags = [
         "no_test_android_arm",
         "no_test_android_arm64",
         "no_test_android_x86",
+        "no_test_wasm",
     ],
     deps = [
         ":civil_time",
diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h
index 0842fa4..f844182 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
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 d7f7271..a5923f1 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -326,6 +326,37 @@
 
 ////////////////////////////////////////////////////////////////////////
 
+namespace impl {
+
+template <typename H>
+H AbslHashValueImpl(second_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss);
+}
+template <typename H>
+H AbslHashValueImpl(minute_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm);
+}
+template <typename H>
+H AbslHashValueImpl(hour_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d, f.hh);
+}
+template <typename H>
+H AbslHashValueImpl(day_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m, f.d);
+}
+template <typename H>
+H AbslHashValueImpl(month_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y, f.m);
+}
+template <typename H>
+H AbslHashValueImpl(year_tag, H h, fields f) {
+  return H::combine(std::move(h), f.y);
+}
+
+}  // namespace impl
+
+////////////////////////////////////////////////////////////////////////
+
 template <typename T>
 class civil_time {
  public:
@@ -355,12 +386,12 @@
       : civil_time(ct.f_) {}
 
   // Factories for the maximum/minimum representable civil_time.
-  static CONSTEXPR_F civil_time max() {
-    const auto max_year = std::numeric_limits<std::int_least64_t>::max();
+  static CONSTEXPR_F civil_time (max)() {
+    const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
     return civil_time(max_year, 12, 31, 23, 59, 59);
   }
-  static CONSTEXPR_F civil_time min() {
-    const auto min_year = std::numeric_limits<std::int_least64_t>::min();
+  static CONSTEXPR_F civil_time (min)() {
+    const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
     return civil_time(min_year, 1, 1, 0, 0, 0);
   }
 
@@ -378,7 +409,7 @@
     return *this;
   }
   CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
-    if (n != std::numeric_limits<diff_t>::min()) {
+    if (n != (std::numeric_limits<diff_t>::min)()) {
       f_ = step(T{}, f_, -n);
     } else {
       f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
@@ -418,8 +449,7 @@
 
   template <typename H>
   friend H AbslHashValue(H h, civil_time a) {
-    return H::combine(std::move(h), a.f_.y, a.f_.m, a.f_.d,
-                                    a.f_.hh, a.f_.mm, a.f_.ss);
+    return impl::AbslHashValueImpl(T{}, std::move(h), a.f_);
   }
 
  private:
@@ -506,9 +536,11 @@
 };
 
 CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept {
-  CONSTEXPR_D weekday k_weekday_by_sun_off[7] = {
-      weekday::sunday,     weekday::monday,    weekday::tuesday,
-      weekday::wednesday,  weekday::thursday,  weekday::friday,
+  CONSTEXPR_D weekday k_weekday_by_mon_off[13] = {
+      weekday::monday,    weekday::tuesday,  weekday::wednesday,
+      weekday::thursday,  weekday::friday,   weekday::saturday,
+      weekday::sunday,    weekday::monday,   weekday::tuesday,
+      weekday::wednesday, weekday::thursday, weekday::friday,
       weekday::saturday,
   };
   CONSTEXPR_D int k_weekday_offsets[1 + 12] = {
@@ -517,7 +549,7 @@
   year_t wd = 2400 + (cd.year() % 400) - (cd.month() < 3);
   wd += wd / 4 - wd / 100 + wd / 400;
   wd += k_weekday_offsets[cd.month()] + cd.day();
-  return k_weekday_by_sun_off[(wd % 7 + 7) % 7];
+  return k_weekday_by_mon_off[wd % 7 + 6];
 }
 
 ////////////////////////////////////////////////////////////////////////
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index f28dad1..ef6c4ba 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -72,7 +72,7 @@
 //
 // See also:
 // - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://en.wikipedia.org/wiki/Zoneinfo
 class time_zone {
  public:
   time_zone() : time_zone(nullptr) {}  // Equivalent to UTC
diff --git a/absl/time/internal/cctz/include/cctz/zone_info_source.h b/absl/time/internal/cctz/include/cctz/zone_info_source.h
index 20a7697..2b898d1 100644
--- a/absl/time/internal/cctz/include/cctz/zone_info_source.h
+++ b/absl/time/internal/cctz/include/cctz/zone_info_source.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index 4498d7d..445366e 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -357,6 +357,7 @@
   "Asia/Pontianak",
   "Asia/Pyongyang",
   "Asia/Qatar",
+  "Asia/Qostanay",
   "Asia/Qyzylorda",
   "Asia/Rangoon",
   "Asia/Riyadh",
diff --git a/absl/time/internal/cctz/src/civil_time_detail.cc b/absl/time/internal/cctz/src/civil_time_detail.cc
index 780d5c9..cb40b6b 100644
--- a/absl/time/internal/cctz/src/civil_time_detail.cc
+++ b/absl/time/internal/cctz/src/civil_time_detail.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc
index faffde4..e590ee3 100644
--- a/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/absl/time/internal/cctz/src/civil_time_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index db9a475..81ece72 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.h b/absl/time/internal/cctz/src/time_zone_fixed.h
index 489b857..9c1f5e7 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.h
+++ b/absl/time/internal/cctz/src/time_zone_fixed.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index a02b1e3..2585098 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -13,7 +13,7 @@
 //   limitations under the License.
 
 #if !defined(HAS_STRPTIME)
-# if !defined(_MSC_VER)
+# if !defined(_MSC_VER) && !defined(__MINGW32__)
 #  define HAS_STRPTIME 1  // assume everyone has strptime() except windows
 # endif
 #endif
@@ -149,15 +149,25 @@
     offset = -offset;  // bounded by 24h so no overflow
     sign = '-';
   }
-  char sep = mode[0];
-  if (sep != '\0' && mode[1] == '*') {
-    ep = Format02d(ep, offset % 60);
+  const int seconds = offset % 60;
+  const int minutes = (offset /= 60) % 60;
+  const int hours = offset /= 60;
+  const char sep = mode[0];
+  const bool ext = (sep != '\0' && mode[1] == '*');
+  const bool ccc = (ext && mode[2] == ':');
+  if (ext && (!ccc || seconds != 0)) {
+    ep = Format02d(ep, seconds);
     *--ep = sep;
+  } else {
+    // If we're not rendering seconds, sub-minute negative offsets
+    // should get a positive sign (e.g., offset=-10s => "+00:00").
+    if (hours == 0 && minutes == 0) sign = '+';
   }
-  int minutes = offset / 60;
-  ep = Format02d(ep, minutes % 60);
-  if (sep != '\0') *--ep = sep;
-  ep = Format02d(ep, minutes / 60);
+  if (!ccc || minutes != 0 || seconds != 0) {
+    ep = Format02d(ep, minutes);
+    if (sep != '\0') *--ep = sep;
+  }
+  ep = Format02d(ep, hours);
   *--ep = sign;
   return ep;
 }
@@ -384,6 +394,44 @@
       continue;
     }
 
+    // More complex specifiers that we handle ourselves.
+    if (*cur == ':' && cur + 1 != end) {
+      if (*(cur + 1) == 'z') {
+        // Formats %:z.
+        if (cur - 1 != pending) {
+          FormatTM(&result, std::string(pending, cur - 1), tm);
+        }
+        bp = FormatOffset(ep, al.offset, ":");
+        result.append(bp, static_cast<std::size_t>(ep - bp));
+        pending = cur += 2;
+        continue;
+      }
+      if (*(cur + 1) == ':' && cur + 2 != end) {
+        if (*(cur + 2) == 'z') {
+          // Formats %::z.
+          if (cur - 1 != pending) {
+            FormatTM(&result, std::string(pending, cur - 1), tm);
+          }
+          bp = FormatOffset(ep, al.offset, ":*");
+          result.append(bp, static_cast<std::size_t>(ep - bp));
+          pending = cur += 3;
+          continue;
+        }
+        if (*(cur + 2) == ':' && cur + 3 != end) {
+          if (*(cur + 3) == 'z') {
+            // Formats %:::z.
+            if (cur - 1 != pending) {
+              FormatTM(&result, std::string(pending, cur - 1), tm);
+            }
+            bp = FormatOffset(ep, al.offset, ":*:");
+            result.append(bp, static_cast<std::size_t>(ep - bp));
+            pending = cur += 4;
+            continue;
+          }
+        }
+      }
+    }
+
     // Loop if there is no E modifier.
     if (*cur != 'E' || ++cur == end) continue;
 
@@ -668,17 +716,27 @@
                         &percent_s);
         if (data != nullptr) saw_percent_s = true;
         continue;
+      case ':':
+        if (fmt[0] == 'z' ||
+            (fmt[0] == ':' &&
+             (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {
+          data = ParseOffset(data, ":", &offset);
+          if (data != nullptr) saw_offset = true;
+          fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;
+          continue;
+        }
+        break;
       case '%':
         data = (*data == '%' ? data + 1 : nullptr);
         continue;
       case 'E':
-        if (*fmt == 'z' || (*fmt == '*' && *(fmt + 1) == 'z')) {
+        if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
           data = ParseOffset(data, ":", &offset);
           if (data != nullptr) saw_offset = true;
-          fmt += (*fmt == 'z') ? 1 : 2;
+          fmt += (fmt[0] == 'z') ? 1 : 2;
           continue;
         }
-        if (*fmt == '*' && *(fmt + 1) == 'S') {
+        if (fmt[0] == '*' && fmt[1] == 'S') {
           data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
           if (data != nullptr && *data == '.') {
             data = ParseSubSeconds(data + 1, &subseconds);
@@ -686,14 +744,14 @@
           fmt += 2;
           continue;
         }
-        if (*fmt == '*' && *(fmt + 1) == 'f') {
+        if (fmt[0] == '*' && fmt[1] == 'f') {
           if (data != nullptr && std::isdigit(*data)) {
             data = ParseSubSeconds(data, &subseconds);
           }
           fmt += 2;
           continue;
         }
-        if (*fmt == '4' && *(fmt + 1) == 'Y') {
+        if (fmt[0] == '4' && fmt[1] == 'Y') {
           const char* bp = data;
           data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
           if (data != nullptr) {
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index 6b9928e..705ccdc 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -64,17 +64,6 @@
   EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
 }
 
-// These tests sometimes run on platforms that have zoneinfo data so old
-// that the transition we are attempting to check does not exist, most
-// notably Android emulators.  Fortunately, AndroidZoneInfoSource supports
-// time_zone::version() so, in cases where we've learned that it matters,
-// we can make the check conditionally.
-int VersionCmp(time_zone tz, const std::string& target) {
-  std::string version = tz.version();
-  if (version.empty() && !target.empty()) return 1;  // unknown > known
-  return version.compare(target);
-}
-
 }  // namespace
 
 //
@@ -174,7 +163,9 @@
   TestFormatSpecifier(tp, tz, "%M", "00");
   TestFormatSpecifier(tp, tz, "%S", "00");
   TestFormatSpecifier(tp, tz, "%U", "00");
+#if !defined(__EMSCRIPTEN__)
   TestFormatSpecifier(tp, tz, "%w", "4");  // 4=Thursday
+#endif
   TestFormatSpecifier(tp, tz, "%W", "00");
   TestFormatSpecifier(tp, tz, "%y", "70");
   TestFormatSpecifier(tp, tz, "%Y", "1970");
@@ -436,51 +427,165 @@
 }
 
 TEST(Format, ExtendedOffset) {
-  auto tp = chrono::system_clock::from_time_t(0);
+  const auto tp = chrono::system_clock::from_time_t(0);
 
-  time_zone tz = utc_time_zone();
+  auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+  TestFormatSpecifier(tp, tz, "%z", "+0000");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:00");
   TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
 
-  EXPECT_TRUE(load_time_zone("America/New_York", &tz));
-  TestFormatSpecifier(tp, tz, "%Ez", "-05:00");
+  tz = fixed_time_zone(chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+0000");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
 
-  EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
-  TestFormatSpecifier(tp, tz, "%Ez", "-08:00");
+  tz = fixed_time_zone(-chrono::seconds(56));  // NOTE: +00:00
+  TestFormatSpecifier(tp, tz, "%z", "+0000");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
 
-  EXPECT_TRUE(load_time_zone("Australia/Sydney", &tz));
-  TestFormatSpecifier(tp, tz, "%Ez", "+10:00");
+  tz = fixed_time_zone(chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "+0034");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
 
-  EXPECT_TRUE(load_time_zone("Africa/Monrovia", &tz));
-  // The true offset is -00:44:30 but %z only gives (truncated) minutes.
-  TestFormatSpecifier(tp, tz, "%z", "-0044");
-  TestFormatSpecifier(tp, tz, "%Ez", "-00:44");
+  tz = fixed_time_zone(-chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "-0034");
+  TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+  tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+0034");
+  TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
+
+  tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "-0034");
+  TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+  tz = fixed_time_zone(chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%z", "+1200");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+  tz = fixed_time_zone(-chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%z", "-1200");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+1200");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "-1200");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "+1234");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%z", "-1234");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "+1234");
+  TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%z", "-1234");
+  TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+  TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
 }
 
 TEST(Format, ExtendedSecondOffset) {
-  const time_zone utc = utc_time_zone();
-  time_point<chrono::seconds> tp;
-  time_zone tz;
+  const auto tp = chrono::system_clock::from_time_t(0);
 
-  EXPECT_TRUE(load_time_zone("America/New_York", &tz));
-  tp = convert(civil_second(1883, 11, 18, 16, 59, 59), utc);
-  if (tz.lookup(tp).offset == -5 * 60 * 60) {
-    // It looks like the tzdata is only 32 bit (probably macOS),
-    // which bottoms out at 1901-12-13T20:45:52+00:00.
-  } else {
-    TestFormatSpecifier(tp, tz, "%E*z", "-04:56:02");
-    TestFormatSpecifier(tp, tz, "%Ez", "-04:56");
-  }
-  tp += chrono::seconds(1);
-  TestFormatSpecifier(tp, tz, "%E*z", "-05:00:00");
+  auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00");
 
-  EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz));
-  tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc);
-  if (VersionCmp(tz, "2016g") >= 0) {
-    TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
-    TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
-  }
-  tp += chrono::seconds(1);
-  TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00");
+  tz = fixed_time_zone(chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
+
+  tz = fixed_time_zone(-chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
+
+  tz = fixed_time_zone(chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
+
+  tz = fixed_time_zone(-chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
+
+  tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
+
+  tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
+
+  tz = fixed_time_zone(chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12");
+
+  tz = fixed_time_zone(-chrono::hours(12));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
+
+  tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
+
+  tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+                       chrono::seconds(56));
+  TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
+  TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
+  TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
 }
 
 TEST(Format, ExtendedYears) {
@@ -1160,25 +1265,6 @@
   const time_zone utc = utc_time_zone();
   time_point<absl::time_internal::cctz::seconds> tp;
 
-  // %z against +-HHMM.
-  EXPECT_TRUE(parse("%z", "+0000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "-1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "+1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%z", "-123", utc, &tp));
-
-  // %z against +-HH.
-  EXPECT_TRUE(parse("%z", "+00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "-12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%z", "+12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
-  EXPECT_FALSE(parse("%z", "-1", utc, &tp));
-
-  // %Ez against +-HH:MM.
   EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
   EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
   EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
@@ -1187,91 +1273,70 @@
   EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
   EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
 
-  // %Ez against +-HHMM.
-  EXPECT_TRUE(parse("%Ez", "+0000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-123", utc, &tp));
+  for (auto fmt : {"%Ez", "%z"}) {
+    EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
 
-  // %Ez against +-HH.
-  EXPECT_TRUE(parse("%Ez", "+00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-1", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+  }
 }
 
 TEST(Parse, ExtendedSecondOffset) {
   const time_zone utc = utc_time_zone();
   time_point<absl::time_internal::cctz::seconds> tp;
 
-  // %Ez against +-HH:MM:SS.
-  EXPECT_TRUE(parse("%Ez", "+00:00:00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-12:34:5", utc, &tp));
+  for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
+    EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
 
-  // %Ez against +-HHMMSS.
-  EXPECT_TRUE(parse("%Ez", "+000000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "-123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%Ez", "+123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%Ez", "-12345", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
 
-  // %E*z against +-HH:MM:SS.
-  EXPECT_TRUE(parse("%E*z", "+00:00:00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+12:34:56", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-12:34:5", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
 
-  // %E*z against +-HHMMSS.
-  EXPECT_TRUE(parse("%E*z", "+000000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+123456", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-12345", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
 
-  // %E*z against +-HH:MM.
-  EXPECT_TRUE(parse("%E*z", "+00:00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-12:34", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+12:34", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-12:3", utc, &tp));
-
-  // %E*z against +-HHMM.
-  EXPECT_TRUE(parse("%E*z", "+0000", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+1234", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-123", utc, &tp));
-
-  // %E*z against +-HH.
-  EXPECT_TRUE(parse("%E*z", "+00", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "-12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
-  EXPECT_TRUE(parse("%E*z", "+12", utc, &tp));
-  EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
-  EXPECT_FALSE(parse("%E*z", "-1", utc, &tp));
+    EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+    EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+    EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+    EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+  }
 }
 
 TEST(Parse, ExtendedYears) {
@@ -1390,6 +1455,10 @@
 #if defined(_WIN32) || defined(_WIN64)
   // Initial investigations indicate the %c does not roundtrip on Windows.
   // TODO: Figure out what is going on here (perhaps a locale problem).
+#elif defined(__EMSCRIPTEN__)
+  // strftime() and strptime() use different defintions for "%c" under
+  // emscripten (see https://github.com/kripken/emscripten/pull/7491),
+  // causing its round-trip test to fail.
 #else
   // Even though we don't know what %c will produce, it should roundtrip,
   // but only in the 0-offset timezone.
diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc
index 380834a..09aaee5 100644
--- a/absl/time/internal/cctz/src/time_zone_if.cc
+++ b/absl/time/internal/cctz/src/time_zone_if.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h
index e4bd386..d000b7a 100644
--- a/absl/time/internal/cctz/src/time_zone_if.h
+++ b/absl/time/internal/cctz/src/time_zone_if.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc
index 3062ccd..3cbc674 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h
index 14965ef..b73fad9 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/absl/time/internal/cctz/src/time_zone_impl.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index 2cb358d..50f7de5 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -25,7 +25,7 @@
 // a grain of salt.
 //
 // For more information see tzfile(5), http://www.iana.org/time-zones, or
-// http://en.wikipedia.org/wiki/Zoneinfo.
+// https://en.wikipedia.org/wiki/Zoneinfo.
 //
 // Note that we assume the proleptic Gregorian calendar and 60-second
 // minutes throughout.
@@ -921,7 +921,7 @@
     ++begin;
   }
   std::int_fast64_t unix_time = ToUnixSeconds(tp);
-  const Transition target = { unix_time };
+  const Transition target = {unix_time, 0, civil_second(), civil_second()};
   const Transition* tr = std::upper_bound(begin, end, target,
                                           Transition::ByUnixTime());
   for (; tr != end; ++tr) {  // skip no-op transitions
@@ -956,7 +956,7 @@
     }
     unix_time += 1;  // ceils
   }
-  const Transition target = { unix_time };
+  const Transition target = {unix_time, 0, civil_second(), civil_second()};
   const Transition* tr = std::lower_bound(begin, end, target,
                                           Transition::ByUnixTime());
   for (; tr != begin; --tr) {  // skip no-op transitions
diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h
index 958e9b6..bff639f 100644
--- a/absl/time/internal/cctz/src/time_zone_info.h
+++ b/absl/time/internal/cctz/src/time_zone_info.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 074c8d0..3ab1623 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -20,6 +20,7 @@
 
 #include <chrono>
 #include <ctime>
+#include <limits>
 #include <tuple>
 #include <utility>
 
@@ -85,6 +86,76 @@
 #endif  // !defined(__tm_gmtoff) && !defined(__tm_zone)
 #endif
 
+inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
+#if defined(_WIN32) || defined(_WIN64)
+    return gmtime_s(result, timep) ? nullptr : result;
+#else
+    return gmtime_r(timep, result);
+#endif
+}
+
+inline std::tm* local_time(const std::time_t *timep, std::tm *result) {
+#if defined(_WIN32) || defined(_WIN64)
+    return localtime_s(result, timep) ? nullptr : result;
+#else
+    return localtime_r(timep, result);
+#endif
+}
+
+// Converts a civil second and "dst" flag into a time_t and UTC offset.
+// Returns false if time_t cannot represent the requested civil second.
+// Caller must have already checked that cs.year() will fit into a tm_year.
+bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) {
+  std::tm tm;
+  tm.tm_year = static_cast<int>(cs.year() - year_t{1900});
+  tm.tm_mon = cs.month() - 1;
+  tm.tm_mday = cs.day();
+  tm.tm_hour = cs.hour();
+  tm.tm_min = cs.minute();
+  tm.tm_sec = cs.second();
+  tm.tm_isdst = is_dst;
+  *t = std::mktime(&tm);
+  if (*t == std::time_t{-1}) {
+    std::tm tm2;
+    const std::tm* tmp = local_time(t, &tm2);
+    if (tmp == nullptr || tmp->tm_year != tm.tm_year ||
+        tmp->tm_mon != tm.tm_mon || tmp->tm_mday != tm.tm_mday ||
+        tmp->tm_hour != tm.tm_hour || tmp->tm_min != tm.tm_min ||
+        tmp->tm_sec != tm.tm_sec) {
+      // A true error (not just one second before the epoch).
+      return false;
+    }
+  }
+  *off = get_offset_abbr(tm).first;
+  return true;
+}
+
+// Find the least time_t in [lo:hi] where local time matches offset, given:
+// (1) lo doesn't match, (2) hi does, and (3) there is only one transition.
+std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
+  std::tm tm;
+  while (lo + 1 != hi) {
+    const std::time_t mid = lo + (hi - lo) / 2;
+    if (std::tm* tmp = local_time(&mid, &tm)) {
+      if (get_offset_abbr(*tmp).first == offset) {
+        hi = mid;
+      } else {
+        lo = mid;
+      }
+    } else {
+      // If std::tm cannot hold some result we resort to a linear search,
+      // ignoring all failed conversions.  Slow, but never really happens.
+      while (++lo != hi) {
+        if (std::tm* tmp = local_time(&lo, &tm)) {
+          if (get_offset_abbr(*tmp).first == offset) break;
+        }
+      }
+      return lo;
+    }
+  }
+  return hi;
+}
+
 }  // namespace
 
 TimeZoneLibC::TimeZoneLibC(const std::string& name)
@@ -93,59 +164,116 @@
 time_zone::absolute_lookup TimeZoneLibC::BreakTime(
     const time_point<seconds>& tp) const {
   time_zone::absolute_lookup al;
-  std::time_t t = ToUnixSeconds(tp);
-  std::tm tm;
-  if (local_) {
-#if defined(_WIN32) || defined(_WIN64)
-    localtime_s(&tm, &t);
-#else
-    localtime_r(&t, &tm);
-#endif
-    std::tie(al.offset, al.abbr) = get_offset_abbr(tm);
-  } else {
-#if defined(_WIN32) || defined(_WIN64)
-    gmtime_s(&tm, &t);
-#else
-    gmtime_r(&t, &tm);
-#endif
-    al.offset = 0;
-    al.abbr = "UTC";
+  al.offset = 0;
+  al.is_dst = false;
+  al.abbr = "-00";
+
+  const std::int_fast64_t s = ToUnixSeconds(tp);
+
+  // If std::time_t cannot hold the input we saturate the output.
+  if (s < std::numeric_limits<std::time_t>::min()) {
+    al.cs = civil_second::min();
+    return al;
   }
-  al.cs = civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                       tm.tm_hour, tm.tm_min, tm.tm_sec);
-  al.is_dst = tm.tm_isdst > 0;
+  if (s > std::numeric_limits<std::time_t>::max()) {
+    al.cs = civil_second::max();
+    return al;
+  }
+
+  const std::time_t t = static_cast<std::time_t>(s);
+  std::tm tm;
+  std::tm* tmp = local_ ? local_time(&t, &tm) : gm_time(&t, &tm);
+
+  // If std::tm cannot hold the result we saturate the output.
+  if (tmp == nullptr) {
+    al.cs = (s < 0) ? civil_second::min() : civil_second::max();
+    return al;
+  }
+
+  const year_t year = tmp->tm_year + year_t{1900};
+  al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday,
+                       tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
+  std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp);
+  if (!local_) al.abbr = "UTC";  // as expected by cctz
+  al.is_dst = tmp->tm_isdst > 0;
   return al;
 }
 
 time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
-  time_zone::civil_lookup cl;
-  std::time_t t;
-  if (local_) {
-    // Does not handle SKIPPED/AMBIGUOUS or huge years.
-    std::tm tm;
-    tm.tm_year = static_cast<int>(cs.year() - 1900);
-    tm.tm_mon = cs.month() - 1;
-    tm.tm_mday = cs.day();
-    tm.tm_hour = cs.hour();
-    tm.tm_min = cs.minute();
-    tm.tm_sec = cs.second();
-    tm.tm_isdst = -1;
-    t = std::mktime(&tm);
-  } else {
-    t = cs - civil_second();
+  if (!local_) {
+    // If time_point<seconds> cannot hold the result we saturate.
+    static const civil_second min_tp_cs =
+        civil_second() + ToUnixSeconds(time_point<seconds>::min());
+    static const civil_second max_tp_cs =
+        civil_second() + ToUnixSeconds(time_point<seconds>::max());
+    const time_point<seconds> tp =
+        (cs < min_tp_cs)
+            ? time_point<seconds>::min()
+            : (cs > max_tp_cs) ? time_point<seconds>::max()
+                               : FromUnixSeconds(cs - civil_second());
+    return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
   }
-  cl.kind = time_zone::civil_lookup::UNIQUE;
-  cl.pre = cl.trans = cl.post = FromUnixSeconds(t);
-  return cl;
+
+  // If tm_year cannot hold the requested year we saturate the result.
+  if (cs.year() < 0) {
+    if (cs.year() < std::numeric_limits<int>::min() + year_t{1900}) {
+      const time_point<seconds> tp = time_point<seconds>::min();
+      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
+    }
+  } else {
+    if (cs.year() - year_t{1900} > std::numeric_limits<int>::max()) {
+      const time_point<seconds> tp = time_point<seconds>::max();
+      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
+    }
+  }
+
+  // We probe with "is_dst" values of 0 and 1 to try to distinguish unique
+  // civil seconds from skipped or repeated ones.  This is not always possible
+  // however, as the "dst" flag does not change over some offset transitions.
+  // We are also subject to the vagaries of mktime() implementations.
+  std::time_t t0, t1;
+  int offset0, offset1;
+  if (make_time(cs, 0, &t0, &offset0) && make_time(cs, 1, &t1, &offset1)) {
+    if (t0 == t1) {
+      // The civil time was singular (pre == trans == post).
+      const time_point<seconds> tp = FromUnixSeconds(t0);
+      return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
+    }
+
+    if (t0 > t1) {
+      std::swap(t0, t1);
+      std::swap(offset0, offset1);
+    }
+    const std::time_t tt = find_trans(t0, t1, offset1);
+    const time_point<seconds> trans = FromUnixSeconds(tt);
+
+    if (offset0 < offset1) {
+      // The civil time did not exist (pre >= trans > post).
+      const time_point<seconds> pre = FromUnixSeconds(t1);
+      const time_point<seconds> post = FromUnixSeconds(t0);
+      return {time_zone::civil_lookup::SKIPPED, pre, trans, post};
+    }
+
+    // The civil time was ambiguous (pre < trans <= post).
+    const time_point<seconds> pre = FromUnixSeconds(t0);
+    const time_point<seconds> post = FromUnixSeconds(t1);
+    return {time_zone::civil_lookup::REPEATED, pre, trans, post};
+  }
+
+  // make_time() failed somehow so we saturate the result.
+  const time_point<seconds> tp = (cs < civil_second())
+                                     ? time_point<seconds>::min()
+                                     : time_point<seconds>::max();
+  return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
 }
 
-bool TimeZoneLibC::NextTransition(const time_point<seconds>& tp,
-                                  time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::NextTransition(const time_point<seconds>&,
+                                  time_zone::civil_transition*) const {
   return false;
 }
 
-bool TimeZoneLibC::PrevTransition(const time_point<seconds>& tp,
-                                  time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::PrevTransition(const time_point<seconds>&,
+                                  time_zone::civil_transition*) const {
   return false;
 }
 
diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h
index 4e40c61..0d18e9a 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.h
+++ b/absl/time/internal/cctz/src/time_zone_libc.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc
index f2d151e..fd04e2d 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -20,6 +20,11 @@
 #include <dlfcn.h>
 #endif
 #endif
+
+#if defined(__APPLE__)
+#include <CoreFoundation/CFTimeZone.h>
+#endif
+
 #include <cstdlib>
 #include <cstring>
 #include <string>
@@ -121,6 +126,11 @@
   char* tz_env = nullptr;
 #if defined(_MSC_VER)
   _dupenv_s(&tz_env, nullptr, "TZ");
+#elif defined(__APPLE__)
+  CFTimeZoneRef system_time_zone = CFTimeZoneCopyDefault();
+  CFStringRef tz_name = CFTimeZoneGetName(system_time_zone);
+  tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding()));
+  CFRelease(system_time_zone);
 #else
   tz_env = std::getenv("TZ");
 #endif
@@ -153,6 +163,8 @@
 #if defined(_MSC_VER)
   free(localtime_env);
   free(tz_env);
+#elif defined(__APPLE__)
+  free(tz_env);
 #endif
 
   time_zone tz;
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 551292f..8068e2f 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -16,7 +16,9 @@
 
 #include <chrono>
 #include <cstddef>
+#include <cstdlib>
 #include <future>
+#include <limits>
 #include <string>
 #include <thread>
 #include <vector>
@@ -335,6 +337,7 @@
   "Asia/Pontianak",
   "Asia/Pyongyang",
   "Asia/Qatar",
+  "Asia/Qostanay",
   "Asia/Qyzylorda",
   "Asia/Rangoon",
   "Asia/Riyadh",
@@ -664,6 +667,7 @@
 
 }  // namespace
 
+#if !defined(__EMSCRIPTEN__)
 TEST(TimeZones, LoadZonesConcurrently) {
   std::promise<void> ready_promise;
   std::shared_future<void> ready_future(ready_promise.get_future());
@@ -711,6 +715,7 @@
   }
   EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
 }
+#endif
 
 TEST(TimeZone, NamedTimeZones) {
   const time_zone utc = utc_time_zone();
@@ -925,7 +930,7 @@
   EXPECT_EQ(tp, convert(civil_second(2009, 2, 13, 18, 30, 90), tz));   // second
 }
 
-// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+// NOTE: Run this with -ftrapv to detect overflow problems.
 TEST(MakeTime, SysSecondsLimits) {
   const char RFC3339[] =  "%Y-%m-%dT%H:%M:%S%Ez";
   const time_zone utc = utc_time_zone();
@@ -990,6 +995,106 @@
   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
   tp = convert(civil_second::min(), west);
   EXPECT_EQ(time_point<absl::time_internal::cctz::seconds>::min(), tp);
+
+  // Some similar checks for the "libc" time-zone implementation.
+  if (sizeof(std::time_t) >= 8) {
+    // Checks that "tm_year + 1900", as used by the "libc" implementation,
+    // can produce year values beyond the range on an int without overflow.
+#if defined(_WIN32) || defined(_WIN64)
+    // localtime_s() and gmtime_s() don't believe in years outside [1970:3000].
+#else
+    const time_zone utc = 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), utc);
+    EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc));
+    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), utc);
+    EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc));
+#endif
+  }
+}
+
+TEST(MakeTime, LocalTimeLibC) {
+  // Checks that cctz and libc agree on transition points in [1970:2037].
+  //
+  // We limit this test case to environments where:
+  //  1) we know how to change the time zone used by localtime()/mktime(),
+  //  2) cctz and localtime()/mktime() will use similar-enough tzdata, and
+  //  3) we have some idea about how mktime() behaves during transitions.
+#if defined(__linux__) && !defined(__ANDROID__)
+  const char* const ep = getenv("TZ");
+  std::string tz_name = (ep != nullptr) ? ep : "";
+  for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
+    ASSERT_EQ(0, setenv("TZ", *np, 1));  // change what "localtime" means
+    const auto zi = local_time_zone();
+    const auto lc = LoadZone("libc:localtime");
+    time_zone::civil_transition trans;
+    for (auto tp = zi.lookup(civil_second()).trans;
+         zi.next_transition(tp, &trans);
+         tp = zi.lookup(trans.to).trans) {
+      const auto fcl = zi.lookup(trans.from);
+      const auto tcl = zi.lookup(trans.to);
+      civil_second cs;  // compare cs in zi and lc
+      if (fcl.kind == time_zone::civil_lookup::UNIQUE) {
+        if (tcl.kind == time_zone::civil_lookup::UNIQUE) {
+          // Both unique; must be an is_dst or abbr change.
+          ASSERT_EQ(trans.from, trans.to);
+          const auto trans = fcl.trans;
+          const auto tal = zi.lookup(trans);
+          const auto tprev = trans - absl::time_internal::cctz::seconds(1);
+          const auto pal = zi.lookup(tprev);
+          if (pal.is_dst == tal.is_dst) {
+            ASSERT_STRNE(pal.abbr, tal.abbr);
+          }
+          continue;
+        }
+        ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);
+        cs = trans.to;
+      } else {
+        ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);
+        ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);
+        cs = trans.from;
+      }
+      if (cs.year() > 2037) break;  // limit test time (and to 32-bit time_t)
+      const auto cl_zi = zi.lookup(cs);
+      if (zi.lookup(cl_zi.pre).is_dst == zi.lookup(cl_zi.post).is_dst) {
+        // The "libc" implementation cannot correctly classify transitions
+        // that don't change the "tm_isdst" flag.  In Europe/Volgograd, for
+        // example, there is a SKIPPED transition from +03 to +04 with dst=F
+        // on both sides ...
+        //   1540681199 = 2018-10-28 01:59:59 +03:00:00 [dst=F off=10800]
+        //   1540681200 = 2018-10-28 03:00:00 +04:00:00 [dst=F off=14400]
+        // but std::mktime(2018-10-28 02:00:00, tm_isdst=0) fails, unlike,
+        // say, the similar Europe/Chisinau transition from +02 to +03 ...
+        //   1521935999 = 2018-03-25 01:59:59 +02:00:00 [dst=F off=7200]
+        //   1521936000 = 2018-03-25 03:00:00 +03:00:00 [dst=T off=10800]
+        // where std::mktime(2018-03-25 02:00:00, tm_isdst=0) succeeds and
+        // returns 1521936000.
+        continue;
+      }
+      if (cs == civil_second(2037, 10, 4, 2, 0, 0)) {
+        const std::string tzname = *np;
+        if (tzname == "Africa/Casablanca" || tzname == "Africa/El_Aaiun") {
+          // The "libc" implementation gets this transition wrong (at least
+          // until 2018g when it was removed), returning an offset of 3600
+          // instead of 0.  TODO: Revert this when 2018g is ubiquitous.
+          continue;
+        }
+      }
+      const auto cl_lc = lc.lookup(cs);
+      SCOPED_TRACE(testing::Message() << "For " << cs << " in " << *np);
+      EXPECT_EQ(cl_zi.kind, cl_lc.kind);
+      EXPECT_EQ(cl_zi.pre, cl_lc.pre);
+      EXPECT_EQ(cl_zi.trans, cl_lc.trans);
+      EXPECT_EQ(cl_zi.post, cl_lc.post);
+    }
+  }
+  if (ep == nullptr) {
+    ASSERT_EQ(0, unsetenv("TZ"));
+  } else {
+    ASSERT_EQ(0, setenv("TZ", tz_name.c_str(), 1));
+  }
+#endif
 }
 
 TEST(NextTransition, UTC) {
diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc
index 75ad8bc..993901a 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.cc
+++ b/absl/time/internal/cctz/src/time_zone_posix.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h
index 9ccd4a8..6a60022 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.h
+++ b/absl/time/internal/cctz/src/time_zone_posix.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -68,25 +68,35 @@
 // it would take us to another day, and perhaps week, or even month.
 struct PosixTransition {
   enum DateFormat { J, N, M };
-  struct {
-    DateFormat fmt;
-    union {
-      struct {
-        std::int_fast16_t day;  // day of non-leap year [1:365]
-      } j;
-      struct {
-        std::int_fast16_t day;  // day of year [0:365]
-      } n;
-      struct {
-        std::int_fast8_t month;    // month of year [1:12]
-        std::int_fast8_t week;     // week of month [1:5] (5==last)
-        std::int_fast8_t weekday;  // 0==Sun, ..., 6=Sat
-      } m;
+
+  struct Date {
+    struct NonLeapDay {
+      std::int_fast16_t day;  // day of non-leap year [1:365]
     };
-  } date;
-  struct {
+    struct Day {
+      std::int_fast16_t day;  // day of year [0:365]
+    };
+    struct MonthWeekWeekday {
+      std::int_fast8_t month;    // month of year [1:12]
+      std::int_fast8_t week;     // week of month [1:5] (5==last)
+      std::int_fast8_t weekday;  // 0==Sun, ..., 6=Sat
+    };
+
+    DateFormat fmt;
+
+    union {
+      NonLeapDay j;
+      Day n;
+      MonthWeekWeekday m;
+    };
+  };
+
+  struct Time {
     std::int_fast32_t offset;  // seconds before/after 00:00:00
-  } time;
+  };
+
+  Date date;
+  Time time;
 };
 
 // The entirety of a POSIX-string specified time-zone rule. The standard
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 90cfc0c..4485ba5 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -1,3 +1,5 @@
+/* Layout and location of TZif files.  */
+
 #ifndef TZFILE_H
 
 #define TZFILE_H
diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc
index bf2d2d2..1324846 100644
--- a/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/absl/time/internal/cctz/src/zone_info_source.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//   http://www.apache.org/licenses/LICENSE-2.0
+//   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,
@@ -54,7 +54,7 @@
 #pragma comment( \
     linker,      \
     "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA")
-#elif defined(_M_IA_64) || defined(_M_AMD64)
+#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)
 #pragma comment( \
     linker,      \
     "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA")
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index fe86b5c..63f5800 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2018e-2-g99dd695
+2018i
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
index 6fd1af3..65d19ec 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 8726e80..eaaa818 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 39631f2..6e19601 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 2a25f3a..a5867a6 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 39631f2..6e19601 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 39631f2..6e19601 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 6fd1af3..65d19ec 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 b1c97cc..cbdc045 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 6fd1af3..65d19ec 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 8e32be3..82ea5aa 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 5b871db..31cfad7 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 b1c97cc..cbdc045 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 5b871db..31cfad7 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 ba09750..0272fa1 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 65de344..4c57054 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 aaa657f..dd75e3e 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 6fd1af3..65d19ec 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 6fd1af3..65d19ec 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 39631f2..6e19601 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 39631f2..6e19601 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 b1c97cc..cbdc045 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 f5f8ffb..0ea0253 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 6fd1af3..65d19ec 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 5b871db..31cfad7 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 5b871db..31cfad7 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 ddf3652..b8b9270 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 9fa7119..83eca03 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 39631f2..6e19601 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 f2c9e30..549dae2 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 5b871db..31cfad7 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 b1c97cc..cbdc045 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 b1c97cc..cbdc045 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 b1c97cc..cbdc045 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 6fd1af3..65d19ec 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 b1c97cc..cbdc045 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 5b871db..31cfad7 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 5b871db..31cfad7 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 b1c97cc..cbdc045 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 5b871db..31cfad7 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 ddf3652..b8b9270 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 ddf3652..b8b9270 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 39631f2..6e19601 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 b434c67..2a154f4 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 39631f2..6e19601 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 bbfe19d..8779590 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 b1c97cc..cbdc045 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 6fd1af3..65d19ec 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 6fd1af3..65d19ec 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 b1c97cc..cbdc045 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 a4ece7f..59f3759 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 6fd1af3..65d19ec 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 b32e220..bd88531 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 4bd3885..0cd8ffb 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 f5d40ba..6766185 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 5696e0f..4323649 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 6c8bdf2..9bbb2fd 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 447efbe..bdedd1b 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 447efbe..bdedd1b 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 8b295a9..bc9a522 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 e4866ce..dfebfb9 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 9fe9ad6..b798105 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 9fe9ad6..b798105 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 8c58f8c..5df3cf6 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 a74ba04..7d2ba91 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 cb184d6..7654aeb 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 5e8c44c..1032356 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 966a529..3c849fc 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 b19aa22..a4b71c1 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 9e5ade6..948a390 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 af8aa99..acfbbe4 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 bbb03a0..085fc9c 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 07e4e9f..1fc3256 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 d308336..d3b318d 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 3c61ddb..831bf84 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 5708b55..629ed42 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 5696e0f..4323649 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 6008a57..143eafc 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 21e2b71..cd53107 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 6339936..7bb7ac4 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 b8e13b0..ab3c8a6 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 7dcc4fc..fd69321 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 abcde7d..f9f13a1 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 f776904..69e17a0 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 d893446..b7ded8e 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 ada6d64..f8d54e2 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 e4866ce..dfebfb9 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 d322f01..f8db4b6 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 de52bb6..495ef45 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 7e69f73..de6930c 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 c8cab1a..9abd028 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 9fe9ad6..b798105 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 6db6409..ff59657 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 5c1c063..55b0834 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 3dd8f0f..a5b1617 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 e3adbdb..b268724 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 5708b55..629ed42 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 8c58f8c..5df3cf6 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 c247133..525a67e 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 798f627..0fba741 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 145c89e..8a4ee7d 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 d308336..d3b318d 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 ad68c72..9549adc 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 61c9688..db9cead 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 78f9076..db9e339 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 7fc6691..5fbe26b 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 e3ea5c3..5e02260 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 447efbe..bdedd1b 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 d02fbcd..3fa0579 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 41047f2..99b7d06 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 9b8bc7a..ac774e8 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 29c83e7..ada6bf7 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 5923cc6..5a0b7f1 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 4a92c06..09511cc 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 22396bb..e637170 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 f58522b..48412a4 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 ea293cc..0160308 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 b4b945e..a3f2990 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 4c8ca6f..4597a62 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 447efbe..bdedd1b 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 447efbe..bdedd1b 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 abf943b..6118b5c 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 92de38b..bf087a0 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 7d29876..d1dd2fa 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 f86ece4..756099a 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 1a58fcd..8186060 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 ec435c2..26c269d 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 4a92c06..09511cc 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 cc785da..fcd408d 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 a23d7b7..1abf75e 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 f16cb30..0133548 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 0250bf9..4ce95c1 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 e934de6..d236b7c 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 adbdbee..c818929 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 b34f7b2..630935c 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 4a92c06..09511cc 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 1388e8a..e107dc4 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 0785ac5..c8138bd 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 7aedd26..162306f 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 a74ba04..7d2ba91 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 d00668a..451f349 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 fdf2e88..f4c4cf9 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 60991aa..438e3ea 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 cc785da..fcd408d 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 d308336..d3b318d 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 bc3df52..5e5fec5 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 44280a5..d9fec37 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 c0ce440..9dad4f4 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 fdf2e88..f4c4cf9 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 d308336..d3b318d 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 54442dc..fec8a8b 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 c543ffd..69256c6 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 855cb02..b10241e 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 447efbe..bdedd1b 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 f9e2399..79716de 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 5671d25..5c59984 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 afa94c2..43ee12d 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 5e8c44c..1032356 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 55d6e32..3146138 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 ecc1856..b46298e 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 c033597..85a7e16 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 f11e3d2..1434ab0 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 75bbcf2..06ceaad 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 51cb1ba..9df8d0f 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 dcac92b..7dc5057 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 f524fd2..0d1e565 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 7b4682a..6752c5b 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 447efbe..bdedd1b 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 e5d0289..5091eb5 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 7553fee..2f75480 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 f8a0292..f6a856e 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 c886c9b..10998df 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 6d91f91..95ff8a2 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 8174c88..246345d 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 8035b24..1fa0703 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 5b630ee..123f2ae 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/Ojinaga b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
index 190c5c8..37d7830 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 5c1c063..55b0834 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 df78b62..3e4e0db 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 1b608b3..b95c784 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 adf2823..4d51271 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 7306cae..d959010 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 447efbe..bdedd1b 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 b612ac2..16b7f92 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 2423fc1..10cb02b 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 d4525a6..a662a57 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 4d84eed..a5a8af5 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 70dcd2d..ea66099 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 9f50f36..61ff6fc 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 fe55739..c6d99b3 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 5fe8d6b..20c9c84 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 884b1f6..4365a5c 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 b612ac2..16b7f92 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 8c58f8c..5df3cf6 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 29c83e7..ada6bf7 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 d776a43..8080efa 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 ab766a4..816a042 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 cc2cbf2..4e5eba5 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 308a545..c417ba1 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 8e1366c..e20e9e1 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 7fc6691..5fbe26b 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 662b8b6..31f7061 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 447efbe..bdedd1b 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 a1d1485..65a5b0c 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 447efbe..bdedd1b 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 447efbe..bdedd1b 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 447efbe..bdedd1b 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 447efbe..bdedd1b 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 4db1300..8e9ef25 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 7aea8f9..477e939 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 deefcc8..2969ebe 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 aa1d486..e504c9a 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 29c83e7..ada6bf7 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 7b4682a..6752c5b 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 447efbe..bdedd1b 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 9b5d924..0f9f832 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 447efbe..bdedd1b 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 6b62e2d..fb3cd71 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 2ffe3d8..3718d47 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 523b0a1..da209f9 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 d9d6eff..e6afa39 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 d0bbacc..f100f47 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 40a9926..916f2c2 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 0686353..bd6563e 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 aea2be7..83c308a 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 5197dd9..e1f0b09 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 a5f5b6d..60bcef6 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 43a01d3..3dd85f8 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 56913f8..7940e6e 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 a5f5b6d..60bcef6 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 94a9d5a..4bb041a 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 3757fac..5e565da 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 9fa335c..5696abf 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 239c017..c6842af 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 e71bc4e..b2f9a25 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 49a4b4d..d93201c 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 c3f0994..281b304 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 0e623cf..6a96601 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 5803a3d..78cbcf0 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 808a502..7504052 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 046c472..8d9e03c 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 046c472..8d9e03c 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 27072eb..317466d 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 3aacd78..97fa6c7 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 a0c5f66..f514092 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 a17d1ad..8a090d7 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 8db5e8a..7249640 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 60efb41..82cc49c 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 72f0896..efb24c2 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 e3f81ee..f7a7d54 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 cad16b0..8624c7a 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 b57972d..e1cfcb8 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 95f5645..3baf752 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 15b358f..79b9d3c 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 dbd132f..ce9e00a 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 dbd132f..ce9e00a 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 28fe430..4fc96c8 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 98881f0..776f27d 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 ac45764..4b610b5 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 98881f0..776f27d 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 c94fa61..f6ce91a 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 c12f31a..7880d5d 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 67c772b..694f6e6 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 021f8a2..653b146 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 60d0de0..cf54deb 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 dbd132f..ce9e00a 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 a2e1b36..09c876a 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 9264267..eab94fe 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 dc9058e..91eaff4 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 f367a55..8eb5f64 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 8413636..e8c53c0 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 9a53b3a..833d4eb 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 37b4edd..673d480 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 39ddc84..a4c0829 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 df51199..2d14c99 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 80429ec..a22cf59 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 fab27de..b9ed49c 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 b7dcaab..337e1d5 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 b44a1e1..0342b43 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 0cbd295..2f810b1 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 0cbd295..2f810b1 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 9183695..2b2f5bf 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 b57972d..e1cfcb8 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 faec35d..59efd24 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 5c95ebc..6d7d47b 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 62b5389..4878622 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 e71bc4e..b2f9a25 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 2c20a32..d801000 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 2c20a32..d801000 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 2db0635..b20cc57 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 3a5dcb2..ed55442 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 06859a7..2c9220c 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 c12f31a..7880d5d 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 3e663b2..f7f10ab 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 ed4b248..2576a3b 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 a5d39df..95e3c73 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 5e0d9b6..d805e4f 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 b8eb58d..e36aec4 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 8db5e8a..7249640 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 ec98c62..9377d03 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 dc24926..dd54989 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 a0c5f66..f514092 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
new file mode 100644
index 0000000..cb6e2d9
--- /dev/null
+++ 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 0fc7fad..fc636b3 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 3cc2aaf..a00282d 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 e71bc4e..b2f9a25 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 9264267..eab94fe 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 8d6b4df..9c94900 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 10c7af7..a5d1e97 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 312ec40..fa1cbd3 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 dbd132f..ce9e00a 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 7858366..ebc4b0d 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 16b1cd8..f8b7bb2 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 748873b..f9cbe67 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 6f7dea4..e75bb36 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 4b2d2e2..09bb06e 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 3157f80..0ae2f65 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 df51199..2d14c99 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 a8bddb9..06d3324 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 a8bddb9..06d3324 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 8ad44ba..26f4d34 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 919b003..28da9c9 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 3a5dcb2..ed55442 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 94ddfea..82fd476 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 94ddfea..82fd476 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 b44a1e1..0342b43 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 7431eb9..c0c3767 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 8db5e8a..7249640 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 80b170b..15731ab 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 220ad3d..1f86e77 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 3cc2aaf..a00282d 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 c1abb93..fff9f3b 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 4c4e045..409c3b1 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 1895e1b..56593db 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 548d979..3a5c6db 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 544f443..f319215 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 6bda6db..e2a49d2 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 c486518..4dab7ef 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 c486518..4dab7ef 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 239c017..c6842af 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 e25f8a5..5213761 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 dc49c32..ac6bd69 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 56b383b..b3311b6 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 6fd1af3..65d19ec 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 3649415..2fd42a2 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 aaed12c..4ed4467 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 4f331a8..190b0e3 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 a327d83..26ffd9a 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 768b167..874c865 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 aaed12c..4ed4467 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 a3f6f29..865801e 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 c6ae9a7..cf42d1d 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 99f07a9..c49d499 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 07784ce..92d1215 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 57597b0..8c6c7dd 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 71ca143..8ee1a6f 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 57597b0..8c6c7dd 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 ec8dfe0..3f2d3d7 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 aaed12c..4ed4467 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 c6ae9a7..cf42d1d 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 85c26d5..d38b67e 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 a327d83..26ffd9a 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 4f331a8..190b0e3 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 aaed12c..4ed4467 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 07784ce..92d1215 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 ec8dfe0..3f2d3d7 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 85c26d5..d38b67e 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 768b167..874c865 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 b612ac2..16b7f92 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 6d91f91..95ff8a2 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 308a545..c417ba1 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 855cb02..b10241e 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 4c4f8ef..d585656 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 5c8a1d9..41c4136 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 f86ece4..756099a 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 2ffe3d8..3718d47 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 7b4682a..6752c5b 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 d02fbcd..3fa0579 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 a1d1485..65a5b0c 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 9b5d924..0f9f832 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 5fe8d6b..20c9c84 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 6b62e2d..fb3cd71 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 ab766a4..816a042 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 060bef8..cae3744 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 1a58fcd..8186060 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 beb273a..d2f54c9 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 ae34663..074a4fc 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 54541fc..087b641 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 ba09750..0272fa1 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 655daf3..5c5a7a3 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 c05e45f..2ee1429 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 c05e45f..2ee1429 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 082986e..087d1f9 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 23276cd..6437c68 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 28c579d..72a912e 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 c740603..6938a1a 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 721cde2..a315577 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 ae06bcb..ee77619 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 5a7f878..1ea7da2 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 18cbf1f..dda1a9e 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 1aa4be8..f4a0385 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 cd8ed49..2d2ccd0 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 e0ba6b8..826c770 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 eee1bcb..b125ad2 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 c05e45f..2ee1429 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 4ff8701..dde682d 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 e12e461..352ec08 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 37f2739..dfa27fe 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 09297f1..eef949d 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 97ae1e1..f9363b2 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 58d6d1b..35add05 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 f0dc706..315cae4 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 a0790fe..7489a15 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 a75a173..560243e 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 85ebf22..b2bbe97 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 95def1f..b979dbb 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 c6a776e..365ab1f 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 f74a16f..742082f 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 9b647c0..abc0b27 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 c05e45f..2ee1429 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 c05e45f..2ee1429 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 40147b9..a88c4b6 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 c3b97f1..5583f5b 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 c3b97f1..5583f5b 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 c3b97f1..5583f5b 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 6dae5e4..ed064ed 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 b06de7a..5962550 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 90d7c2a..5e069ea 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 0001602..9f3a067 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 4527515..a340326 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 79c25d7..32a5722 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 b4f2a2a..7ddd510 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 ba82f31..85036de 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 d8f19a6..d0d0a08 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 e0eac4c..4eb7ed0 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 3ddf6a5..dfdc6d2 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 9c2b600..ad6cf59 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 2109b52..5bc1bfe 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 be87cf1..cb2ec06 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 655daf3..5c5a7a3 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 a7105fa..117aadb 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 4527515..a340326 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 29b3c81..b4f8f9c 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 4527515..a340326 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 9a53b3a..833d4eb 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 4527515..a340326 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 37280d0..982d82a 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 b3e20a7..9337c9e 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 40b558f..a3b5320 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 a856530..355817b 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 79c25d7..32a5722 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 4527515..a340326 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 6fae86c..6c194a5 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 9b51a73..ccc9d85 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 c1208e2..bf2452d 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 29b3c81..b4f8f9c 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 60041a4..801aead 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 0b40f1e..686ae88 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 906bd05..ddb3f4e 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 3e663b2..f7f10ab 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 239c017..c6842af 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 cf6e2e2..ca85435 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 79c25d7..32a5722 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 ba82f31..85036de 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 b729ee8..8495c50 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 bdd3449..78a131b 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 0539acf..97d5dd9 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 bdd3449..78a131b 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 79c25d7..32a5722 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 e8cd6b1..8fd5f6d 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 f3b42b0..e82dbbc 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 79c25d7..32a5722 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 763e074..dcfdd08 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 43c7f2e..f3e0c7f 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 18f903f..3a744cc 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 52c16a4..0b86017 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 2109b52..5bc1bfe 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 c280f43..7b61bdc 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 8ddba90..677f088 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 9c2b600..ad6cf59 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 bdd3449..78a131b 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 9c0fac5..9e2d0c9 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 da380af..46ce484 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 f4cb64f..8f170dd 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 5cbba41..d6bb156 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 79c25d7..32a5722 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 6f14850..e42edfc 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 9c2b600..ad6cf59 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 afeeb88..95bc3a3 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 4527515..a340326 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 4527515..a340326 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 c05e45f..2ee1429 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 c05e45f..2ee1429 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 c05e45f..2ee1429 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 c05e45f..2ee1429 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 c05e45f..2ee1429 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 03e4db0..616c31b 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 dc9058e..91eaff4 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 dc49c32..ac6bd69 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 39631f2..6e19601 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 0e5e719..f609611 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 066c1e9..6babdee 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 34a2457..58f8051 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 39631f2..6e19601 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 e7d4d3d..2cb6f3e 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 db8ac68..49e23e5 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 3f1a76e..ffa3365 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 fd8d911..b23e2ce 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 39631f2..6e19601 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 d5f9aa4..11c6002 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 3157f80..0ae2f65 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 df51199..2d14c99 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 7aedd26..162306f 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 8ad44ba..26f4d34 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 1a27122..d641357 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 b32e220..bd88531 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 71963d5..388dd74 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 a1bee7c..da3e926 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 726a7e5..ddca8d1 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 29c83e7..ada6bf7 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 afa94c2..43ee12d 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 f11e3d2..1434ab0 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 a5f5b6d..60bcef6 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 957c80b..abe09cb 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 7fc6691..5fbe26b 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 dbd132f..ce9e00a 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 6242ac0..d773e28 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 4091a85..fd03ff7 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 a5f5b6d..60bcef6 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 dc5a7d7..6a6c2da 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 957c80b..abe09cb 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 289b795..8004d65 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 060bef8..cae3744 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 5cee55d..d650a05 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 a3f30e5..8087350 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 6e4b8af..4fa169f 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 912db18..61a6695 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 3289094..e6a1544 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 76b2b3a..859b76d 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 625016d..4e9e36c 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 0c24095..908ccc1 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 4286e6b..e224247 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 bd85577..c7cd060 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 bd85577..c7cd060 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 762275d..cf5b3bd 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 f8222e6..11583b1 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 1a27122..d641357 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 b3a8c18..65990cb 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 10c5c9b..5fad0e1 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 3e38e97..72707b5 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 6092119..86d3b7d 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 df6110d..1d58fe3 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 d0b9607..f630a65 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 d9c68f8..99f6bca 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 3e38e97..72707b5 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 e1bbea5..05633b8 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 54783cf..9092e48 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 9743bc3..090429c 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 9743bc3..090429c 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 3fa1f7f..f6fd51c 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 ace1ce4..9708b87 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 4286e6b..e224247 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 3e38e97..72707b5 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 7867d8b..37e4e88 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 3340413..e23c0cd 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 b3a5a89..35c9e2c 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 289b795..8004d65 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 2dc630c..837ce1f 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 b4f0f9b..8be9ac4 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 289b795..8004d65 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 5cbba41..d6bb156 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 a856530..355817b 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 748873b..f9cbe67 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 312ec40..fa1cbd3 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 7858366..ebc4b0d 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 9a53b3a..833d4eb 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 40147b9..a88c4b6 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 6c8bdf2..9bbb2fd 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 5696e0f..4323649 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 adf2823..4d51271 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 3dd8f0f..a5b1617 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 4a92c06..09511cc 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 7553fee..2f75480 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 bd85577..c7cd060 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 cc785da..fcd408d 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 e3ea5c3..5e02260 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 7fc6691..5fbe26b 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 c0ce440..9dad4f4 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 3e38e97..72707b5 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 c3b97f1..5583f5b 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 c3b97f1..5583f5b 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 906bd05..ddb3f4e 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 444a193..9b03a17 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 c3b97f1..5583f5b 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/internal/cctz/testdata/zoneinfo/iso3166.tab b/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
index c2e0f8e..4e4a5c3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
@@ -10,7 +10,7 @@
 #
 # 1.  ISO 3166-1 alpha-2 country code, current as of
 #     ISO 3166-1 N905 (2016-11-15).  See: Updates on ISO 3166-1
-#     http://isotc.iso.org/livelink/livelink/Open/16944257
+#     https://isotc.iso.org/livelink/livelink/Open/16944257
 # 2.  The usual English name for the coded region,
 #     chosen so that alphabetic sorting of subsets produces helpful lists.
 #     This is not the same as the English name in the ISO 3166 tables.
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
index 2d90ed7..9a8e424 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -1,35 +1,35 @@
-# tz zone descriptions
+# tzdb timezone descriptions
 #
 # This file is in the public domain.
 #
-# From Paul Eggert (2017-10-01):
-# This file contains a table where each row stands for a zone where
-# civil time stamps have agreed since 1970.  Columns are separated by
+# From Paul Eggert (2018-06-27):
+# This file contains a table where each row stands for a timezone where
+# civil timestamps have agreed since 1970.  Columns are separated by
 # a single tab.  Lines beginning with '#' are comments.  All text uses
 # UTF-8 encoding.  The columns of the table are as follows:
 #
-# 1.  The countries that overlap the zone, as a comma-separated list
+# 1.  The countries that overlap the timezone, as a comma-separated list
 #     of ISO 3166 2-character country codes.  See the file 'iso3166.tab'.
-# 2.  Latitude and longitude of the zone's principal location
+# 2.  Latitude and longitude of the timezone's principal location
 #     in ISO 6709 sign-degrees-minutes-seconds format,
 #     either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS,
 #     first latitude (+ is north), then longitude (+ is east).
-# 3.  Zone name used in value of TZ environment variable.
-#     Please see the theory.html file for how zone names are chosen.
-#     If multiple zones overlap a country, each has a row in the
+# 3.  Timezone name used in value of TZ environment variable.
+#     Please see the theory.html file for how these names are chosen.
+#     If multiple timezones overlap a country, each has a row in the
 #     table, with each column 1 containing the country code.
-# 4.  Comments; present if and only if a country has multiple zones.
+# 4.  Comments; present if and only if a country has multiple timezones.
 #
-# If a zone covers multiple countries, the most-populous city is used,
+# If a timezone covers multiple countries, the most-populous city is used,
 # and that country is listed first in column 1; any other countries
 # are listed alphabetically by country code.  The table is sorted
 # first by country code, then (if possible) by an order within the
 # country that (1) makes some geographical sense, and (2) puts the
-# most populous zones first, where that does not contradict (1).
+# most populous timezones first, where that does not contradict (1).
 #
-# This table is intended as an aid for users, to help them select time
-# zone data entries appropriate for their practical needs.  It is not
-# intended to take or endorse any position on legal or territorial claims.
+# This table is intended as an aid for users, to help them select timezones
+# appropriate for their practical needs.  It is not intended to take or
+# endorse any position on legal or territorial claims.
 #
 #country-
 #codes	coordinates	TZ	comments
@@ -211,6 +211,7 @@
 KR	+3733+12658	Asia/Seoul
 KZ	+4315+07657	Asia/Almaty	Kazakhstan (most areas)
 KZ	+4448+06528	Asia/Qyzylorda	Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ	+5312+06337	Asia/Qostanay	Qostanay/Kostanay/Kustanay
 KZ	+5017+05710	Asia/Aqtobe	Aqtöbe/Aktobe
 KZ	+4431+05016	Asia/Aqtau	Mangghystaū/Mankistau
 KZ	+4707+05156	Asia/Atyrau	Atyraū/Atirau/Gur'yev
@@ -231,7 +232,7 @@
 MN	+4755+10653	Asia/Ulaanbaatar	Mongolia (most areas)
 MN	+4801+09139	Asia/Hovd	Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
 MN	+4804+11430	Asia/Choibalsan	Dornod, Sükhbaatar
-MO	+2214+11335	Asia/Macau
+MO	+221150+1133230	Asia/Macau
 MQ	+1436-06105	America/Martinique
 MT	+3554+01431	Europe/Malta
 MU	-2010+05730	Indian/Mauritius
@@ -289,9 +290,9 @@
 RU	+5443+02030	Europe/Kaliningrad	MSK-01 - Kaliningrad
 RU	+554521+0373704	Europe/Moscow	MSK+00 - Moscow area
 RU	+4457+03406	Europe/Simferopol	MSK+00 - Crimea
-RU	+4844+04425	Europe/Volgograd	MSK+00 - Volgograd
 RU	+5836+04939	Europe/Kirov	MSK+00 - Kirov
 RU	+4621+04803	Europe/Astrakhan	MSK+01 - Astrakhan
+RU	+4844+04425	Europe/Volgograd	MSK+01 - Volgograd
 RU	+5134+04602	Europe/Saratov	MSK+01 - Saratov
 RU	+5420+04824	Europe/Ulyanovsk	MSK+01 - Ulyanovsk
 RU	+5312+05009	Europe/Samara	MSK+01 - Samara, Udmurtia
diff --git a/absl/time/internal/get_current_time_chrono.inc b/absl/time/internal/get_current_time_chrono.inc
index cf884a1..5180230 100644
--- a/absl/time/internal/get_current_time_chrono.inc
+++ b/absl/time/internal/get_current_time_chrono.inc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc
index bbbef7d..59166a7 100644
--- a/absl/time/internal/test_util.cc
+++ b/absl/time/internal/test_util.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -26,12 +26,6 @@
 namespace absl {
 namespace time_internal {
 
-#if GTEST_USES_SIMPLE_RE
-extern const char kZoneAbbrRE[] = ".*";  // just punt
-#else
-extern const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
-#endif
-
 TimeZone LoadTimeZone(const std::string& name) {
   TimeZone tz;
   ABSL_RAW_CHECK(LoadTimeZone(name, &tz), name.c_str());
diff --git a/absl/time/internal/test_util.h b/absl/time/internal/test_util.h
index 8fd5fb9..d7319ea 100644
--- a/absl/time/internal/test_util.h
+++ b/absl/time/internal/test_util.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -17,35 +17,11 @@
 
 #include <string>
 
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
 #include "absl/time/time.h"
 
-// This helper is a macro so that failed expectations show up with the
-// correct line numbers.
-//
-// This is for internal testing of the Base Time library itself. This is not
-// part of a public API.
-#define ABSL_INTERNAL_EXPECT_TIME(bd, y, m, d, h, min, s, off, isdst)     \
-  do {                                                                    \
-    EXPECT_EQ(y, bd.year);                                                \
-    EXPECT_EQ(m, bd.month);                                               \
-    EXPECT_EQ(d, bd.day);                                                 \
-    EXPECT_EQ(h, bd.hour);                                                \
-    EXPECT_EQ(min, bd.minute);                                            \
-    EXPECT_EQ(s, bd.second);                                              \
-    EXPECT_EQ(off, bd.offset);                                            \
-    EXPECT_EQ(isdst, bd.is_dst);                                          \
-    EXPECT_THAT(bd.zone_abbr,                                             \
-                testing::MatchesRegex(absl::time_internal::kZoneAbbrRE)); \
-  } while (0)
-
 namespace absl {
 namespace time_internal {
 
-// A regular expression that matches all zone abbreviations (%Z).
-extern const char kZoneAbbrRE[];
-
 // Loads the named timezone, but dies on any failure.
 absl::TimeZone LoadTimeZone(const std::string& name);
 
diff --git a/absl/time/time.cc b/absl/time/time.cc
index 71fd8ee..977a951 100644
--- a/absl/time/time.cc
+++ b/absl/time/time.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -22,13 +22,14 @@
 // NOTE: To keep type verbosity to a minimum, the following variable naming
 // conventions are used throughout this file.
 //
-// cz: A cctz::time_zone
 // tz: An absl::TimeZone
+// ci: An absl::TimeZone::CivilInfo
+// ti: An absl::TimeZone::TimeInfo
+// cd: An absl::CivilDay or a cctz::civil_day
+// cs: An absl::CivilSecond or a cctz::civil_second
+// bd: An absl::Time::Breakdown
 // cl: A cctz::time_zone::civil_lookup
 // al: A cctz::time_zone::absolute_lookup
-// cd: A cctz::civil_day
-// cs: A cctz::civil_second
-// bd: An absl::Time::Breakdown
 
 #include "absl/time/time.h"
 
@@ -40,6 +41,7 @@
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace cctz = absl::time_internal::cctz;
+
 namespace absl {
 
 namespace {
@@ -75,7 +77,7 @@
   return bd;
 }
 
-inline Time::Breakdown InfinitePastBreakdown() {
+inline absl::Time::Breakdown InfinitePastBreakdown() {
   Time::Breakdown bd;
   bd.year = std::numeric_limits<int64_t>::min();
   bd.month = 1;
@@ -92,6 +94,26 @@
   return bd;
 }
 
+inline absl::TimeZone::CivilInfo InfiniteFutureCivilInfo() {
+  TimeZone::CivilInfo ci;
+  ci.cs = CivilSecond::max();
+  ci.subsecond = InfiniteDuration();
+  ci.offset = 0;
+  ci.is_dst = false;
+  ci.zone_abbr = "-00";
+  return ci;
+}
+
+inline absl::TimeZone::CivilInfo InfinitePastCivilInfo() {
+  TimeZone::CivilInfo ci;
+  ci.cs = CivilSecond::min();
+  ci.subsecond = -InfiniteDuration();
+  ci.offset = 0;
+  ci.is_dst = false;
+  ci.zone_abbr = "-00";
+  return ci;
+}
+
 inline absl::TimeConversion InfiniteFutureTimeConversion() {
   absl::TimeConversion tc;
   tc.pre = tc.trans = tc.post = absl::InfiniteFuture();
@@ -134,19 +156,6 @@
   return time_internal::FromUnixDuration(time_internal::MakeDuration(hi));
 }
 
-inline absl::TimeConversion::Kind MapKind(
-    const cctz::time_zone::civil_lookup::civil_kind& kind) {
-  switch (kind) {
-    case cctz::time_zone::civil_lookup::UNIQUE:
-      return absl::TimeConversion::UNIQUE;
-    case cctz::time_zone::civil_lookup::SKIPPED:
-      return absl::TimeConversion::SKIPPED;
-    case cctz::time_zone::civil_lookup::REPEATED:
-      return absl::TimeConversion::REPEATED;
-  }
-  return absl::TimeConversion::UNIQUE;
-}
-
 // Returns Mon=1..Sun=7.
 inline int MapWeekday(const cctz::weekday& wd) {
   switch (wd) {
@@ -168,11 +177,29 @@
   return 1;
 }
 
+bool FindTransition(const cctz::time_zone& tz,
+                    bool (cctz::time_zone::*find_transition)(
+                        const cctz::time_point<cctz::seconds>& tp,
+                        cctz::time_zone::civil_transition* trans) const,
+                    Time t, TimeZone::CivilTransition* trans) {
+  // Transitions are second-aligned, so we can discard any fractional part.
+  const auto tp = unix_epoch() + cctz::seconds(ToUnixSeconds(t));
+  cctz::time_zone::civil_transition tr;
+  if (!(tz.*find_transition)(tp, &tr)) return false;
+  trans->from = CivilSecond(tr.from);
+  trans->to = CivilSecond(tr.to);
+  return true;
+}
+
 }  // namespace
 
+//
+// Time
+//
+
 absl::Time::Breakdown Time::In(absl::TimeZone tz) const {
-  if (*this == absl::InfiniteFuture()) return absl::InfiniteFutureBreakdown();
-  if (*this == absl::InfinitePast()) return absl::InfinitePastBreakdown();
+  if (*this == absl::InfiniteFuture()) return InfiniteFutureBreakdown();
+  if (*this == absl::InfinitePast()) return InfinitePastBreakdown();
 
   const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(rep_));
   const auto al = cctz::time_zone(tz).lookup(tp);
@@ -187,92 +214,18 @@
   bd.minute = cs.minute();
   bd.second = cs.second();
   bd.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(rep_));
-  bd.weekday = MapWeekday(get_weekday(cd));
-  bd.yearday = get_yearday(cd);
+  bd.weekday = MapWeekday(cctz::get_weekday(cd));
+  bd.yearday = cctz::get_yearday(cd);
   bd.offset = al.offset;
   bd.is_dst = al.is_dst;
   bd.zone_abbr = al.abbr;
   return bd;
 }
 
-absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
-  const auto cz = cctz::time_zone(tz);
-  const auto cs =
-      cctz::civil_second(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                         tm.tm_hour, tm.tm_min, tm.tm_sec);
-  const auto cl = cz.lookup(cs);
-  const auto tp = tm.tm_isdst == 0 ? cl.post : cl.pre;
-  return MakeTimeWithOverflow(tp, cs, cz);
-}
-
-struct tm ToTM(absl::Time t, absl::TimeZone tz) {
-  const absl::Time::Breakdown bd = t.In(tz);
-  struct tm tm;
-  std::memset(&tm, 0, sizeof(tm));
-  tm.tm_sec = bd.second;
-  tm.tm_min = bd.minute;
-  tm.tm_hour = bd.hour;
-  tm.tm_mday = bd.day;
-  tm.tm_mon = bd.month - 1;
-
-  // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
-  // that tm.tm_year is years since 1900.
-  if (bd.year < std::numeric_limits<int>::min() + 1900) {
-    tm.tm_year = std::numeric_limits<int>::min();
-  } else if (bd.year > std::numeric_limits<int>::max()) {
-    tm.tm_year = std::numeric_limits<int>::max() - 1900;
-  } else {
-    tm.tm_year = static_cast<int>(bd.year - 1900);
-  }
-
-  tm.tm_wday = bd.weekday % 7;
-  tm.tm_yday = bd.yearday - 1;
-  tm.tm_isdst = bd.is_dst ? 1 : 0;
-
-  return tm;
-}
-
 //
-// Factory functions.
+// Conversions from/to other time types.
 //
 
-absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
-                                     int min, int sec, TimeZone tz) {
-  // Avoids years that are too extreme for civil_second to normalize.
-  if (year > 300000000000) return InfiniteFutureTimeConversion();
-  if (year < -300000000000) return InfinitePastTimeConversion();
-  const auto cz = cctz::time_zone(tz);
-  const auto cs = cctz::civil_second(year, mon, day, hour, min, sec);
-  absl::TimeConversion tc;
-  tc.normalized = year != cs.year() || mon != cs.month() || day != cs.day() ||
-                  hour != cs.hour() || min != cs.minute() || sec != cs.second();
-  const auto cl = cz.lookup(cs);
-  // Converts the civil_lookup struct to a TimeConversion.
-  tc.pre = MakeTimeWithOverflow(cl.pre, cs, cz, &tc.normalized);
-  tc.trans = MakeTimeWithOverflow(cl.trans, cs, cz, &tc.normalized);
-  tc.post = MakeTimeWithOverflow(cl.post, cs, cz, &tc.normalized);
-  tc.kind = MapKind(cl.kind);
-  return tc;
-}
-
-absl::Time FromDateTime(int64_t year, int mon, int day, int hour, int min,
-                        int sec, TimeZone tz) {
-  if (year > 300000000000) return InfiniteFuture();
-  if (year < -300000000000) return InfinitePast();
-  const auto cz = cctz::time_zone(tz);
-  const auto cs = cctz::civil_second(year, mon, day, hour, min, sec);
-  const auto cl = cz.lookup(cs);
-  return MakeTimeWithOverflow(cl.pre, cs, cz);
-}
-
-absl::Time TimeFromTimespec(timespec ts) {
-  return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
-}
-
-absl::Time TimeFromTimeval(timeval tv) {
-  return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
-}
-
 absl::Time FromUDate(double udate) {
   return time_internal::FromUnixDuration(absl::Milliseconds(udate));
 }
@@ -281,10 +234,6 @@
   return absl::UniversalEpoch() + 100 * absl::Nanoseconds(universal);
 }
 
-//
-// Conversion to other time types.
-//
-
 int64_t ToUnixNanos(Time t) {
   if (time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >= 0 &&
       time_internal::GetRepHi(time_internal::ToUnixDuration(t)) >> 33 == 0) {
@@ -321,6 +270,23 @@
 
 time_t ToTimeT(Time t) { return absl::ToTimespec(t).tv_sec; }
 
+double ToUDate(Time t) {
+  return absl::FDivDuration(time_internal::ToUnixDuration(t),
+                            absl::Milliseconds(1));
+}
+
+int64_t ToUniversal(absl::Time t) {
+  return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
+}
+
+absl::Time TimeFromTimespec(timespec ts) {
+  return time_internal::FromUnixDuration(absl::DurationFromTimespec(ts));
+}
+
+absl::Time TimeFromTimeval(timeval tv) {
+  return time_internal::FromUnixDuration(absl::DurationFromTimeval(tv));
+}
+
 timespec ToTimespec(Time t) {
   timespec ts;
   absl::Duration d = time_internal::ToUnixDuration(t);
@@ -359,15 +325,6 @@
   return tv;
 }
 
-double ToUDate(Time t) {
-  return absl::FDivDuration(time_internal::ToUnixDuration(t),
-                            absl::Milliseconds(1));
-}
-
-int64_t ToUniversal(absl::Time t) {
-  return absl::FloorToUnit(t - absl::UniversalEpoch(), absl::Nanoseconds(100));
-}
-
 Time FromChrono(const std::chrono::system_clock::time_point& tp) {
   return time_internal::FromUnixDuration(time_internal::FromChrono(
       tp - std::chrono::system_clock::from_time_t(0)));
@@ -381,4 +338,149 @@
          time_internal::ToChronoDuration<D>(d);
 }
 
+//
+// TimeZone
+//
+
+absl::TimeZone::CivilInfo TimeZone::At(Time t) const {
+  if (t == absl::InfiniteFuture()) return InfiniteFutureCivilInfo();
+  if (t == absl::InfinitePast()) return InfinitePastCivilInfo();
+
+  const auto ud = time_internal::ToUnixDuration(t);
+  const auto tp = unix_epoch() + cctz::seconds(time_internal::GetRepHi(ud));
+  const auto al = cz_.lookup(tp);
+
+  TimeZone::CivilInfo ci;
+  ci.cs = CivilSecond(al.cs);
+  ci.subsecond = time_internal::MakeDuration(0, time_internal::GetRepLo(ud));
+  ci.offset = al.offset;
+  ci.is_dst = al.is_dst;
+  ci.zone_abbr = al.abbr;
+  return ci;
+}
+
+absl::TimeZone::TimeInfo TimeZone::At(CivilSecond ct) const {
+  const cctz::civil_second cs(ct);
+  const auto cl = cz_.lookup(cs);
+
+  TimeZone::TimeInfo ti;
+  switch (cl.kind) {
+    case cctz::time_zone::civil_lookup::UNIQUE:
+      ti.kind = TimeZone::TimeInfo::UNIQUE;
+      break;
+    case cctz::time_zone::civil_lookup::SKIPPED:
+      ti.kind = TimeZone::TimeInfo::SKIPPED;
+      break;
+    case cctz::time_zone::civil_lookup::REPEATED:
+      ti.kind = TimeZone::TimeInfo::REPEATED;
+      break;
+  }
+  ti.pre = MakeTimeWithOverflow(cl.pre, cs, cz_);
+  ti.trans = MakeTimeWithOverflow(cl.trans, cs, cz_);
+  ti.post = MakeTimeWithOverflow(cl.post, cs, cz_);
+  return ti;
+}
+
+bool TimeZone::NextTransition(Time t, CivilTransition* trans) const {
+  return FindTransition(cz_, &cctz::time_zone::next_transition, t, trans);
+}
+
+bool TimeZone::PrevTransition(Time t, CivilTransition* trans) const {
+  return FindTransition(cz_, &cctz::time_zone::prev_transition, t, trans);
+}
+
+//
+// Conversions involving time zones.
+//
+
+absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
+                                     int min, int sec, TimeZone tz) {
+  // Avoids years that are too extreme for CivilSecond to normalize.
+  if (year > 300000000000) return InfiniteFutureTimeConversion();
+  if (year < -300000000000) return InfinitePastTimeConversion();
+
+  const CivilSecond cs(year, mon, day, hour, min, sec);
+  const auto ti = tz.At(cs);
+
+  TimeConversion tc;
+  tc.pre = ti.pre;
+  tc.trans = ti.trans;
+  tc.post = ti.post;
+  switch (ti.kind) {
+    case TimeZone::TimeInfo::UNIQUE:
+      tc.kind = TimeConversion::UNIQUE;
+      break;
+    case TimeZone::TimeInfo::SKIPPED:
+      tc.kind = TimeConversion::SKIPPED;
+      break;
+    case TimeZone::TimeInfo::REPEATED:
+      tc.kind = TimeConversion::REPEATED;
+      break;
+  }
+  tc.normalized = false;
+  if (year != cs.year() || mon != cs.month() || day != cs.day() ||
+      hour != cs.hour() || min != cs.minute() || sec != cs.second()) {
+    tc.normalized = true;
+  }
+  return tc;
+}
+
+absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
+  const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                       tm.tm_hour, tm.tm_min, tm.tm_sec);
+  const auto ti = tz.At(cs);
+  return tm.tm_isdst == 0 ? ti.post : ti.pre;
+}
+
+struct tm ToTM(absl::Time t, absl::TimeZone tz) {
+  struct tm tm = {};
+
+  const auto ci = tz.At(t);
+  const auto& cs = ci.cs;
+  tm.tm_sec = cs.second();
+  tm.tm_min = cs.minute();
+  tm.tm_hour = cs.hour();
+  tm.tm_mday = cs.day();
+  tm.tm_mon = cs.month() - 1;
+
+  // Saturates tm.tm_year in cases of over/underflow, accounting for the fact
+  // that tm.tm_year is years since 1900.
+  if (cs.year() < std::numeric_limits<int>::min() + 1900) {
+    tm.tm_year = std::numeric_limits<int>::min();
+  } else if (cs.year() > std::numeric_limits<int>::max()) {
+    tm.tm_year = std::numeric_limits<int>::max() - 1900;
+  } else {
+    tm.tm_year = static_cast<int>(cs.year() - 1900);
+  }
+
+  const CivilDay cd(cs);
+  switch (GetWeekday(cd)) {
+    case Weekday::sunday:
+      tm.tm_wday = 0;
+      break;
+    case Weekday::monday:
+      tm.tm_wday = 1;
+      break;
+    case Weekday::tuesday:
+      tm.tm_wday = 2;
+      break;
+    case Weekday::wednesday:
+      tm.tm_wday = 3;
+      break;
+    case Weekday::thursday:
+      tm.tm_wday = 4;
+      break;
+    case Weekday::friday:
+      tm.tm_wday = 5;
+      break;
+    case Weekday::saturday:
+      tm.tm_wday = 6;
+      break;
+  }
+  tm.tm_yday = GetYearDay(cd) - 1;
+  tm.tm_isdst = ci.is_dst ? 1 : 0;
+
+  return tm;
+}
+
 }  // namespace absl
diff --git a/absl/time/time.h b/absl/time/time.h
index 50bf971..594396c 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -25,18 +25,29 @@
 //  * `absl::TimeZone` defines geopolitical time zone regions (as collected
 //     within the IANA Time Zone database (https://www.iana.org/time-zones)).
 //
+// Note: Absolute times are distinct from civil times, which refer to the
+// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping
+// between absolute and civil times can be specified by use of time zones
+// (`absl::TimeZone` within this API). That is:
+//
+//   Civil Time = F(Absolute Time, Time Zone)
+//   Absolute Time = G(Civil Time, Time Zone)
+//
+// See civil_time.h for abstractions related to constructing and manipulating
+// civil time.
 //
 // Example:
 //
 //   absl::TimeZone nyc;
-//
 //   // LoadTimeZone() may fail so it's always better to check for success.
 //   if (!absl::LoadTimeZone("America/New_York", &nyc)) {
 //      // handle error case
 //   }
 //
 //   // My flight leaves NYC on Jan 2, 2017 at 03:04:05
-//   absl::Time takeoff = absl::FromDateTime(2017, 1, 2, 3, 4, 5, nyc);
+//   absl::CivilSecond cs(2017, 1, 2, 3, 4, 5);
+//   absl::Time takeoff = absl::FromCivil(cs, nyc);
+//
 //   absl::Duration flight_duration = absl::Hours(21) + absl::Minutes(35);
 //   absl::Time landing = takeoff + flight_duration;
 //
@@ -47,7 +58,7 @@
 //   std::string s = absl::FormatTime(
 //       "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S",
 //       landing, syd);
-//
+
 #ifndef ABSL_TIME_TIME_H_
 #define ABSL_TIME_TIME_H_
 
@@ -57,6 +68,7 @@
 #include <winsock2.h>
 #endif
 #include <chrono>  // NOLINT(build/c++11)
+#include <cmath>
 #include <cstdint>
 #include <ctime>
 #include <ostream>
@@ -64,8 +76,8 @@
 #include <type_traits>
 #include <utility>
 
-#include "absl/base/port.h"  // Needed for string vs std::string
 #include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace absl {
@@ -140,6 +152,16 @@
   // Value semantics.
   constexpr Duration() : rep_hi_(0), rep_lo_(0) {}  // zero-length duration
 
+  // Copyable.
+#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910
+  // Explicitly defining the constexpr copy constructor avoids an MSVC bug.
+  constexpr Duration(const Duration& d)
+      : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {}
+#else
+  constexpr Duration(const Duration& d) = default;
+#endif
+  Duration& operator=(const Duration& d) = default;
+
   // Compound assignment operators.
   Duration& operator+=(Duration d);
   Duration& operator-=(Duration d);
@@ -348,11 +370,11 @@
 // Factory functions for constructing `Duration` values from an integral number
 // of the unit indicated by the factory function's name.
 //
-// Note: no "Days()" factory function exists because "a day" is ambiguous. Civil
-// days are not always 24 hours long, and a 24-hour duration often does not
-// correspond with a civil day. If a 24-hour duration is needed, use
-// `absl::Hours(24)`.
-//
+// Note: no "Days()" factory function exists because "a day" is ambiguous.
+// Civil days are not always 24 hours long, and a 24-hour duration often does
+// not correspond with a civil day. If a 24-hour duration is needed, use
+// `absl::Hours(24)`. (If you actually want a civil day, use absl::CivilDay
+// from civil_time.h.)
 //
 // Example:
 //
@@ -371,6 +393,7 @@
 // factories, which should be preferred.
 //
 // Example:
+//
 //   auto a = absl::Seconds(1.5);        // OK
 //   auto b = absl::Milliseconds(1500);  // BETTER
 template <typename T, time_internal::EnableIfFloat<T> = 0>
@@ -387,11 +410,13 @@
 }
 template <typename T, time_internal::EnableIfFloat<T> = 0>
 Duration Seconds(T n) {
-  if (n >= 0) {
-    if (n >= std::numeric_limits<int64_t>::max()) return InfiniteDuration();
+  if (n >= 0) {  // Note: `NaN >= 0` is false.
+    if (n >= (std::numeric_limits<int64_t>::max)()) return InfiniteDuration();
     return time_internal::MakePosDoubleDuration(n);
   } else {
-    if (n <= std::numeric_limits<int64_t>::min()) return -InfiniteDuration();
+    if (std::isnan(n))
+      return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration();
+    if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration();
     return -time_internal::MakePosDoubleDuration(-n);
   }
 }
@@ -543,10 +568,9 @@
 // The `absl::Time` class represents an instant in time as a count of clock
 // ticks of some granularity (resolution) from some starting point (epoch).
 //
-//
 // `absl::Time` uses a resolution that is high enough to avoid loss in
 // precision, and a range that is wide enough to avoid overflow, when
-// converting between tick counts in most Google time scales (i.e., precision
+// converting between tick counts in most Google time scales (i.e., resolution
 // of at least one nanosecond, and range +/-100 billion years).  Conversions
 // between the time scales are performed by truncating (towards negative
 // infinity) to the nearest representable point.
@@ -556,7 +580,6 @@
 //   absl::Time t1 = ...;
 //   absl::Time t2 = t1 + absl::Minutes(2);
 //   absl::Duration d = t2 - t1;  // == absl::Minutes(2)
-//   absl::Time::Breakdown bd = t1.In(absl::LocalTimeZone());
 //
 class Time {
  public:
@@ -571,7 +594,11 @@
   //   absl::Time t = absl::Now();
   //   absl::Time t = absl::TimeFromTimeval(tv);
   //   absl::Time t = absl::InfinitePast();
-  constexpr Time() {}
+  constexpr Time() = default;
+
+  // Copyable.
+  constexpr Time(const Time& t) = default;
+  Time& operator=(const Time& t) = default;
 
   // Assignment operators.
   Time& operator+=(Duration d) {
@@ -590,7 +617,10 @@
   // intended to represent an instant in time. So, rather than passing
   // a `Time::Breakdown` to a function, pass an `absl::Time` and an
   // `absl::TimeZone`.
-  struct Breakdown {
+  //
+  // Deprecated. Use `absl::TimeZone::CivilInfo`.
+  struct
+      Breakdown {
     int64_t year;          // year (e.g., 2013)
     int month;           // month of year [1:12]
     int day;             // day of month [1:31]
@@ -614,6 +644,8 @@
   // Time::In()
   //
   // Returns the breakdown of this instant in the given TimeZone.
+  //
+  // Deprecated. Use `absl::TimeZone::At(Time)`.
   Breakdown In(TimeZone tz) const;
 
   template <typename H>
@@ -668,7 +700,7 @@
 // Returns an `absl::Time` that is infinitely far in the future.
 constexpr Time InfiniteFuture() {
   return Time(
-      time_internal::MakeDuration(std::numeric_limits<int64_t>::max(), ~0U));
+      time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U));
 }
 
 // InfinitePast()
@@ -676,129 +708,9 @@
 // Returns an `absl::Time` that is infinitely far in the past.
 constexpr Time InfinitePast() {
   return Time(
-      time_internal::MakeDuration(std::numeric_limits<int64_t>::min(), ~0U));
+      time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U));
 }
 
-// TimeConversion
-//
-// An `absl::TimeConversion` represents the conversion of year, month, day,
-// hour, minute, and second values (i.e., a civil time), in a particular
-// `absl::TimeZone`, to a time instant (an absolute time), as returned by
-// `absl::ConvertDateTime()`. (Subseconds must be handled separately.)
-//
-// It is possible, though, for a caller to try to convert values that
-// do not represent an actual or unique instant in time (due to a shift
-// in UTC offset in the `absl::TimeZone`, which results in a discontinuity in
-// the civil-time components). For example, a daylight-saving-time
-// transition skips or repeats civil times---in the United States, March
-// 13, 2011 02:15 never occurred, while November 6, 2011 01:15 occurred
-// twice---so requests for such times are not well-defined.
-//
-// To account for these possibilities, `absl::TimeConversion` is richer
-// than just a single `absl::Time`. When the civil time is skipped or
-// repeated, `absl::ConvertDateTime()` returns times calculated using the
-// pre-transition and post-transition UTC offsets, plus the transition
-// time itself.
-//
-// Examples:
-//
-//   absl::TimeZone lax;
-//   if (!absl::LoadTimeZone("America/Los_Angeles", &lax)) {
-//     // handle error case
-//   }
-//
-//   // A unique civil time
-//   absl::TimeConversion jan01 =
-//       absl::ConvertDateTime(2011, 1, 1, 0, 0, 0, lax);
-//   // jan01.kind == TimeConversion::UNIQUE
-//   // jan01.pre    is 2011/01/01 00:00:00 -0800
-//   // jan01.trans  is 2011/01/01 00:00:00 -0800
-//   // jan01.post   is 2011/01/01 00:00:00 -0800
-//
-//   // A Spring DST transition, when there is a gap in civil time
-//   absl::TimeConversion mar13 =
-//       absl::ConvertDateTime(2011, 3, 13, 2, 15, 0, lax);
-//   // mar13.kind == TimeConversion::SKIPPED
-//   // mar13.pre   is 2011/03/13 03:15:00 -0700
-//   // mar13.trans is 2011/03/13 03:00:00 -0700
-//   // mar13.post  is 2011/03/13 01:15:00 -0800
-//
-//   // A Fall DST transition, when civil times are repeated
-//   absl::TimeConversion nov06 =
-//       absl::ConvertDateTime(2011, 11, 6, 1, 15, 0, lax);
-//   // nov06.kind == TimeConversion::REPEATED
-//   // nov06.pre   is 2011/11/06 01:15:00 -0700
-//   // nov06.trans is 2011/11/06 01:00:00 -0800
-//   // nov06.post  is 2011/11/06 01:15:00 -0800
-//
-// The input month, day, hour, minute, and second values can also be
-// outside of their valid ranges, in which case they will be "normalized"
-// during the conversion.
-//
-// Example:
-//
-//   // "October 32" normalizes to "November 1".
-//   absl::TimeZone tz = absl::LocalTimeZone();
-//   absl::TimeConversion tc =
-//       absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, tz);
-//   // tc.kind == TimeConversion::UNIQUE && tc.normalized == true
-//   // tc.pre.In(tz).month == 11 && tc.pre.In(tz).day == 1
-struct TimeConversion {
-  Time pre;    // time calculated using the pre-transition offset
-  Time trans;  // when the civil-time discontinuity occurred
-  Time post;   // time calculated using the post-transition offset
-
-  enum Kind {
-    UNIQUE,    // the civil time was singular (pre == trans == post)
-    SKIPPED,   // the civil time did not exist
-    REPEATED,  // the civil time was ambiguous
-  };
-  Kind kind;
-
-  bool normalized;  // input values were outside their valid ranges
-};
-
-// ConvertDateTime()
-//
-// The full generality of a civil time to absl::Time conversion.
-TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
-                               int min, int sec, TimeZone tz);
-
-// FromDateTime()
-//
-// A convenience wrapper for `absl::ConvertDateTime()` that simply returns the
-// "pre" `absl::Time`.  That is, the unique result, or the instant that
-// is correct using the pre-transition offset (as if the transition
-// never happened). This is typically the answer that humans expected when
-// faced with non-unique times, such as near daylight-saving time transitions.
-//
-// Example:
-//
-//   absl::TimeZone seattle;
-//   if (!absl::LoadTimeZone("America/Los_Angeles", &seattle)) {
-//     // handle error case
-//   }
-//   absl::Time t =  absl::FromDateTime(2017, 9, 26, 9, 30, 0, seattle);
-Time FromDateTime(int64_t year, int mon, int day, int hour, int min, int sec,
-                  TimeZone tz);
-
-// FromTM()
-//
-// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and
-// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)
-// for a description of the expected values of the tm fields. IFF the indicated
-// time instant is not unique (see `absl::ConvertDateTime()` above), the
-// `tm_isdst` field is consulted to select the desired instant (`tm_isdst` > 0
-// means DST, `tm_isdst` == 0 means no DST, `tm_isdst` < 0 means use the default
-// like `absl::FromDateTime()`).
-Time FromTM(const struct tm& tm, TimeZone tz);
-
-// ToTM()
-//
-// Converts the given `absl::Time` to a struct tm using the given time zone.
-// See ctime(3) for a description of the values of the tm fields.
-struct tm ToTM(Time t, TimeZone tz);
-
 // FromUnixNanos()
 // FromUnixMicros()
 // FromUnixMillis()
@@ -883,140 +795,6 @@
 //   // tp == std::chrono::system_clock::from_time_t(123);
 std::chrono::system_clock::time_point ToChronoTime(Time);
 
-// RFC3339_full
-// RFC3339_sec
-//
-// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings,
-// with trailing zeros trimmed or with fractional seconds omitted altogether.
-//
-// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and
-// time with UTC offset.  Also note the use of "%Y": RFC3339 mandates that
-// years have exactly four digits, but we allow them to take their natural
-// width.
-extern const char RFC3339_full[];  // %Y-%m-%dT%H:%M:%E*S%Ez
-extern const char RFC3339_sec[];   // %Y-%m-%dT%H:%M:%S%Ez
-
-// RFC1123_full
-// RFC1123_no_wday
-//
-// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z
-extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
-
-// FormatTime()
-//
-// Formats the given `absl::Time` in the `absl::TimeZone` according to the
-// provided format string. Uses strftime()-like formatting options, with
-// the following extensions:
-//
-//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
-//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
-//   - %E#S - Seconds with # digits of fractional precision
-//   - %E*S - Seconds with full fractional precision (a literal '*')
-//   - %E#f - Fractional seconds with # digits of precision
-//   - %E*f - Fractional seconds with full precision (a literal '*')
-//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
-//
-// Note that %E0S behaves like %S, and %E0f produces no characters.  In
-// contrast %E*f always produces at least one digit, which may be '0'.
-//
-// Note that %Y produces as many characters as it takes to fully render the
-// year.  A year outside of [-999:9999] when formatted with %E4Y will produce
-// more than four characters, just like %Y.
-//
-// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
-// so that the result uniquely identifies a time instant.
-//
-// Example:
-//
-//   absl::TimeZone lax;
-//   if (!absl::LoadTimeZone("America/Los_Angeles", &lax)) {
-//     // handle error case
-//   }
-//   absl::Time t = absl::FromDateTime(2013, 1, 2, 3, 4, 5, lax);
-//
-//   string f = absl::FormatTime("%H:%M:%S", t, lax);  // "03:04:05"
-//   f = absl::FormatTime("%H:%M:%E3S", t, lax);  // "03:04:05.000"
-//
-// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned
-// string will be exactly "infinite-future". If the given `absl::Time` is
-// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
-// In both cases the given format string and `absl::TimeZone` are ignored.
-//
-std::string FormatTime(const std::string& format, Time t, TimeZone tz);
-
-// Convenience functions that format the given time using the RFC3339_full
-// format.  The first overload uses the provided TimeZone, while the second
-// uses LocalTimeZone().
-std::string FormatTime(Time t, TimeZone tz);
-std::string FormatTime(Time t);
-
-// Output stream operator.
-inline std::ostream& operator<<(std::ostream& os, Time t) {
-  return os << FormatTime(t);
-}
-
-// ParseTime()
-//
-// Parses an input string according to the provided format string and
-// returns the corresponding `absl::Time`. Uses strftime()-like formatting
-// options, with the same extensions as FormatTime(), but with the
-// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez
-// and %E*z also accept the same inputs.
-//
-// %Y consumes as many numeric characters as it can, so the matching data
-// should always be terminated with a non-numeric.  %E4Y always consumes
-// exactly four characters, including any sign.
-//
-// Unspecified fields are taken from the default date and time of ...
-//
-//   "1970-01-01 00:00:00.0 +0000"
-//
-// For example, parsing a string of "15:45" (%H:%M) will return an absl::Time
-// that represents "1970-01-01 15:45:00.0 +0000".
-//
-// Note that since ParseTime() returns time instants, it makes the most sense
-// to parse fully-specified date/time strings that include a UTC offset (%z,
-// %Ez, or %E*z).
-//
-// Note also that `absl::ParseTime()` only heeds the fields year, month, day,
-// hour, minute, (fractional) second, and UTC offset.  Other fields, like
-// weekday (%a or %A), while parsed for syntactic validity, are ignored
-// in the conversion.
-//
-// Date and time fields that are out-of-range will be treated as errors
-// rather than normalizing them like `absl::FromDateTime()` does.  For example,
-// it is an error to parse the date "Oct 32, 2013" because 32 is out of range.
-//
-// A leap second of ":60" is normalized to ":00" of the following minute
-// with fractional seconds discarded.  The following table shows how the
-// given seconds and subseconds will be parsed:
-//
-//   "59.x" -> 59.x  // exact
-//   "60.x" -> 00.0  // normalized
-//   "00.x" -> 00.x  // exact
-//
-// Errors are indicated by returning false and assigning an error message
-// to the "err" out param if it is non-null.
-//
-// Note: If the input string is exactly "infinite-future", the returned
-// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned.
-// If the input string is "infinite-past", the returned `absl::Time` will be
-// `absl::InfinitePast()` and `true` will be returned.
-//
-bool ParseTime(const std::string& format, const std::string& input, Time* time,
-               std::string* err);
-
-// Like ParseTime() above, but if the format string does not contain a UTC
-// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
-// given TimeZone.  This means that the input, by itself, does not identify a
-// unique instant.  Being time-zone dependent, it also admits the possibility
-// of ambiguity or non-existence, in which case the "pre" time (as defined
-// for ConvertDateTime()) is returned.  For these reasons we recommend that
-// all date/time strings include a UTC offset so they're context independent.
-bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
-               Time* time, std::string* err);
-
 // Support for flag values of type Time. Time flags must be specified in a
 // format that matches absl::RFC3339_full. For example:
 //
@@ -1056,12 +834,14 @@
 //
 // See also:
 // - https://github.com/google/cctz
-// - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://www.iana.org/time-zones
+// - https://en.wikipedia.org/wiki/Zoneinfo
 class TimeZone {
  public:
   explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {}
   TimeZone() = default;  // UTC, but prefer UTCTimeZone() to be explicit.
+
+  // Copyable.
   TimeZone(const TimeZone&) = default;
   TimeZone& operator=(const TimeZone&) = default;
 
@@ -1069,6 +849,136 @@
 
   std::string name() const { return cz_.name(); }
 
+  // TimeZone::CivilInfo
+  //
+  // Information about the civil time corresponding to an absolute time.
+  // This struct is not intended to represent an instant in time. So, rather
+  // than passing a `TimeZone::CivilInfo` to a function, pass an `absl::Time`
+  // and an `absl::TimeZone`.
+  struct CivilInfo {
+    CivilSecond cs;
+    Duration subsecond;
+
+    // Note: The following fields exist for backward compatibility
+    // with older APIs.  Accessing these fields directly is a sign of
+    // imprudent logic in the calling code.  Modern time-related code
+    // should only access this data indirectly by way of FormatTime().
+    // These fields are undefined for InfiniteFuture() and InfinitePast().
+    int offset;             // seconds east of UTC
+    bool is_dst;            // is offset non-standard?
+    const char* zone_abbr;  // time-zone abbreviation (e.g., "PST")
+  };
+
+  // TimeZone::At(Time)
+  //
+  // Returns the civil time for this TimeZone at a certain `absl::Time`.
+  // If the input time is infinite, the output civil second will be set to
+  // CivilSecond::max() or min(), and the subsecond will be infinite.
+  //
+  // Example:
+  //
+  //   const auto epoch = lax.At(absl::UnixEpoch());
+  //   // epoch.cs == 1969-12-31 16:00:00
+  //   // epoch.subsecond == absl::ZeroDuration()
+  //   // epoch.offset == -28800
+  //   // epoch.is_dst == false
+  //   // epoch.abbr == "PST"
+  CivilInfo At(Time t) const;
+
+  // TimeZone::TimeInfo
+  //
+  // Information about the absolute times corresponding to a civil time.
+  // (Subseconds must be handled separately.)
+  //
+  // It is possible for a caller to pass a civil-time value that does
+  // not represent an actual or unique instant in time (due to a shift
+  // in UTC offset in the TimeZone, which results in a discontinuity in
+  // the civil-time components). For example, a daylight-saving-time
+  // transition skips or repeats civil times---in the United States,
+  // March 13, 2011 02:15 never occurred, while November 6, 2011 01:15
+  // occurred twice---so requests for such times are not well-defined.
+  // To account for these possibilities, `absl::TimeZone::TimeInfo` is
+  // richer than just a single `absl::Time`.
+  struct TimeInfo {
+    enum CivilKind {
+      UNIQUE,    // the civil time was singular (pre == trans == post)
+      SKIPPED,   // the civil time did not exist (pre >= trans > post)
+      REPEATED,  // the civil time was ambiguous (pre < trans <= post)
+    } kind;
+    Time pre;    // time calculated using the pre-transition offset
+    Time trans;  // when the civil-time discontinuity occurred
+    Time post;   // time calculated using the post-transition offset
+  };
+
+  // TimeZone::At(CivilSecond)
+  //
+  // Returns an `absl::TimeInfo` containing the absolute time(s) for this
+  // TimeZone at an `absl::CivilSecond`. When the civil time is skipped or
+  // repeated, returns times calculated using the pre-transition and post-
+  // transition UTC offsets, plus the transition time itself.
+  //
+  // Examples:
+  //
+  //   // A unique civil time
+  //   const auto jan01 = lax.At(absl::CivilSecond(2011, 1, 1, 0, 0, 0));
+  //   // jan01.kind == TimeZone::TimeInfo::UNIQUE
+  //   // jan01.pre    is 2011-01-01 00:00:00 -0800
+  //   // jan01.trans  is 2011-01-01 00:00:00 -0800
+  //   // jan01.post   is 2011-01-01 00:00:00 -0800
+  //
+  //   // A Spring DST transition, when there is a gap in civil time
+  //   const auto mar13 = lax.At(absl::CivilSecond(2011, 3, 13, 2, 15, 0));
+  //   // mar13.kind == TimeZone::TimeInfo::SKIPPED
+  //   // mar13.pre   is 2011-03-13 03:15:00 -0700
+  //   // mar13.trans is 2011-03-13 03:00:00 -0700
+  //   // mar13.post  is 2011-03-13 01:15:00 -0800
+  //
+  //   // A Fall DST transition, when civil times are repeated
+  //   const auto nov06 = lax.At(absl::CivilSecond(2011, 11, 6, 1, 15, 0));
+  //   // nov06.kind == TimeZone::TimeInfo::REPEATED
+  //   // nov06.pre   is 2011-11-06 01:15:00 -0700
+  //   // nov06.trans is 2011-11-06 01:00:00 -0800
+  //   // nov06.post  is 2011-11-06 01:15:00 -0800
+  TimeInfo At(CivilSecond ct) const;
+
+  // TimeZone::NextTransition()
+  // TimeZone::PrevTransition()
+  //
+  // Finds the time of the next/previous offset change in this time zone.
+  //
+  // By definition, `NextTransition(t, &trans)` returns false when `t` is
+  // `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false
+  // when `t` is `InfinitePast()`. If the zone has no transitions, the
+  // result will also be false no matter what the argument.
+  //
+  // Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)`
+  // returns true and sets `trans` to the first recorded transition. Chains
+  // of calls to `NextTransition()/PrevTransition()` will eventually return
+  // false, but it is unspecified exactly when `NextTransition(t, &trans)`
+  // jumps to false, or what time is set by `PrevTransition(t, &trans)` for
+  // a very distant `t`.
+  //
+  // Note: Enumeration of time-zone transitions is for informational purposes
+  // only. Modern time-related code should not care about when offset changes
+  // occur.
+  //
+  // Example:
+  //   absl::TimeZone nyc;
+  //   if (!absl::LoadTimeZone("America/New_York", &nyc)) { ... }
+  //   const auto now = absl::Now();
+  //   auto t = absl::InfinitePast();
+  //   absl::TimeZone::CivilTransition trans;
+  //   while (t <= now && nyc.NextTransition(t, &trans)) {
+  //     // transition: trans.from -> trans.to
+  //     t = nyc.At(trans.to).trans;
+  //   }
+  struct CivilTransition {
+    CivilSecond from;  // the civil time we jump from
+    CivilSecond to;    // the civil time we jump to
+  };
+  bool NextTransition(Time t, CivilTransition* trans) const;
+  bool PrevTransition(Time t, CivilTransition* trans) const;
+
   template <typename H>
   friend H AbslHashValue(H h, TimeZone tz) {
     return H::combine(std::move(h), tz.cz_);
@@ -1127,6 +1037,270 @@
   return TimeZone(time_internal::cctz::local_time_zone());
 }
 
+// ToCivilSecond()
+// ToCivilMinute()
+// ToCivilHour()
+// ToCivilDay()
+// ToCivilMonth()
+// ToCivilYear()
+//
+// Helpers for TimeZone::At(Time) to return particularly aligned civil times.
+//
+// Example:
+//
+//   absl::Time t = ...;
+//   absl::TimeZone tz = ...;
+//   const auto cd = absl::ToCivilDay(t, tz);
+inline CivilSecond ToCivilSecond(Time t, TimeZone tz) {
+  return tz.At(t).cs;  // already a CivilSecond
+}
+inline CivilMinute ToCivilMinute(Time t, TimeZone tz) {
+  return CivilMinute(tz.At(t).cs);
+}
+inline CivilHour ToCivilHour(Time t, TimeZone tz) {
+  return CivilHour(tz.At(t).cs);
+}
+inline CivilDay ToCivilDay(Time t, TimeZone tz) {
+  return CivilDay(tz.At(t).cs);
+}
+inline CivilMonth ToCivilMonth(Time t, TimeZone tz) {
+  return CivilMonth(tz.At(t).cs);
+}
+inline CivilYear ToCivilYear(Time t, TimeZone tz) {
+  return CivilYear(tz.At(t).cs);
+}
+
+// FromCivil()
+//
+// Helper for TimeZone::At(CivilSecond) that provides "order-preserving
+// semantics." If the civil time maps to a unique time, that time is
+// returned. If the civil time is repeated in the given time zone, the
+// time using the pre-transition offset is returned. Otherwise, the
+// civil time is skipped in the given time zone, and the transition time
+// is returned. This means that for any two civil times, ct1 and ct2,
+// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case
+// being when two non-existent civil times map to the same transition time.
+//
+// Note: Accepts civil times of any alignment.
+inline Time FromCivil(CivilSecond ct, TimeZone tz) {
+  const auto ti = tz.At(ct);
+  if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans;
+  return ti.pre;
+}
+
+// TimeConversion
+//
+// An `absl::TimeConversion` represents the conversion of year, month, day,
+// hour, minute, and second values (i.e., a civil time), in a particular
+// `absl::TimeZone`, to a time instant (an absolute time), as returned by
+// `absl::ConvertDateTime()`. Lecacy version of `absl::TimeZone::TimeInfo`.
+//
+// Deprecated. Use `absl::TimeZone::TimeInfo`.
+struct
+    TimeConversion {
+  Time pre;    // time calculated using the pre-transition offset
+  Time trans;  // when the civil-time discontinuity occurred
+  Time post;   // time calculated using the post-transition offset
+
+  enum Kind {
+    UNIQUE,    // the civil time was singular (pre == trans == post)
+    SKIPPED,   // the civil time did not exist
+    REPEATED,  // the civil time was ambiguous
+  };
+  Kind kind;
+
+  bool normalized;  // input values were outside their valid ranges
+};
+
+// ConvertDateTime()
+//
+// Legacy version of `absl::TimeZone::At(absl::CivilSecond)` that takes
+// the civil time as six, separate values (YMDHMS).
+//
+// The input month, day, hour, minute, and second values can be outside
+// of their valid ranges, in which case they will be "normalized" during
+// the conversion.
+//
+// Example:
+//
+//   // "October 32" normalizes to "November 1".
+//   absl::TimeConversion tc =
+//       absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, lax);
+//   // tc.kind == TimeConversion::UNIQUE && tc.normalized == true
+//   // absl::ToCivilDay(tc.pre, tz).month() == 11
+//   // absl::ToCivilDay(tc.pre, tz).day() == 1
+//
+// Deprecated. Use `absl::TimeZone::At(CivilSecond)`.
+TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
+                               int min, int sec, TimeZone tz);
+
+// FromDateTime()
+//
+// A convenience wrapper for `absl::ConvertDateTime()` that simply returns
+// the "pre" `absl::Time`.  That is, the unique result, or the instant that
+// is correct using the pre-transition offset (as if the transition never
+// happened).
+//
+// Example:
+//
+//   absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax);
+//   // t = 2017-09-26 09:30:00 -0700
+//
+// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the
+// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil
+// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`.
+inline Time FromDateTime(int64_t year, int mon, int day, int hour,
+                         int min, int sec, TimeZone tz) {
+  return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre;
+}
+
+// FromTM()
+//
+// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and
+// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)
+// for a description of the expected values of the tm fields. If the indicated
+// time instant is not unique (see `absl::TimeZone::At(absl::CivilSecond)`
+// above), the `tm_isdst` field is consulted to select the desired instant
+// (`tm_isdst` > 0 means DST, `tm_isdst` == 0 means no DST, `tm_isdst` < 0
+// means use the post-transition offset).
+Time FromTM(const struct tm& tm, TimeZone tz);
+
+// ToTM()
+//
+// Converts the given `absl::Time` to a struct tm using the given time zone.
+// See ctime(3) for a description of the values of the tm fields.
+struct tm ToTM(Time t, TimeZone tz);
+
+// RFC3339_full
+// RFC3339_sec
+//
+// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings,
+// with trailing zeros trimmed or with fractional seconds omitted altogether.
+//
+// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and
+// time with UTC offset.  Also note the use of "%Y": RFC3339 mandates that
+// years have exactly four digits, but we allow them to take their natural
+// width.
+extern const char RFC3339_full[];  // %Y-%m-%dT%H:%M:%E*S%Ez
+extern const char RFC3339_sec[];   // %Y-%m-%dT%H:%M:%S%Ez
+
+// RFC1123_full
+// RFC1123_no_wday
+//
+// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
+extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z
+extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
+
+// FormatTime()
+//
+// Formats the given `absl::Time` in the `absl::TimeZone` according to the
+// provided format string. Uses strftime()-like formatting options, with
+// the following extensions:
+//
+//   - %Ez  - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
+//   - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
+//   - %E#S - Seconds with # digits of fractional precision
+//   - %E*S - Seconds with full fractional precision (a literal '*')
+//   - %E#f - Fractional seconds with # digits of precision
+//   - %E*f - Fractional seconds with full precision (a literal '*')
+//   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+//
+// Note that %E0S behaves like %S, and %E0f produces no characters.  In
+// contrast %E*f always produces at least one digit, which may be '0'.
+//
+// Note that %Y produces as many characters as it takes to fully render the
+// year.  A year outside of [-999:9999] when formatted with %E4Y will produce
+// more than four characters, just like %Y.
+//
+// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
+// so that the result uniquely identifies a time instant.
+//
+// Example:
+//
+//   absl::CivilSecond cs(2013, 1, 2, 3, 4, 5);
+//   absl::Time t = absl::FromCivil(cs, lax);
+//   std::string f = absl::FormatTime("%H:%M:%S", t, lax);  // "03:04:05"
+//   f = absl::FormatTime("%H:%M:%E3S", t, lax);  // "03:04:05.000"
+//
+// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned
+// string will be exactly "infinite-future". If the given `absl::Time` is
+// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
+// In both cases the given format string and `absl::TimeZone` are ignored.
+//
+std::string FormatTime(const std::string& format, Time t, TimeZone tz);
+
+// Convenience functions that format the given time using the RFC3339_full
+// format.  The first overload uses the provided TimeZone, while the second
+// uses LocalTimeZone().
+std::string FormatTime(Time t, TimeZone tz);
+std::string FormatTime(Time t);
+
+// Output stream operator.
+inline std::ostream& operator<<(std::ostream& os, Time t) {
+  return os << FormatTime(t);
+}
+
+// ParseTime()
+//
+// Parses an input string according to the provided format string and
+// returns the corresponding `absl::Time`. Uses strftime()-like formatting
+// options, with the same extensions as FormatTime(), but with the
+// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez
+// and %E*z also accept the same inputs.
+//
+// %Y consumes as many numeric characters as it can, so the matching data
+// should always be terminated with a non-numeric.  %E4Y always consumes
+// exactly four characters, including any sign.
+//
+// Unspecified fields are taken from the default date and time of ...
+//
+//   "1970-01-01 00:00:00.0 +0000"
+//
+// For example, parsing a string of "15:45" (%H:%M) will return an absl::Time
+// that represents "1970-01-01 15:45:00.0 +0000".
+//
+// Note that since ParseTime() returns time instants, it makes the most sense
+// to parse fully-specified date/time strings that include a UTC offset (%z,
+// %Ez, or %E*z).
+//
+// Note also that `absl::ParseTime()` only heeds the fields year, month, day,
+// hour, minute, (fractional) second, and UTC offset.  Other fields, like
+// weekday (%a or %A), while parsed for syntactic validity, are ignored
+// in the conversion.
+//
+// Date and time fields that are out-of-range will be treated as errors
+// rather than normalizing them like `absl::CivilSecond` does.  For example,
+// it is an error to parse the date "Oct 32, 2013" because 32 is out of range.
+//
+// A leap second of ":60" is normalized to ":00" of the following minute
+// with fractional seconds discarded.  The following table shows how the
+// given seconds and subseconds will be parsed:
+//
+//   "59.x" -> 59.x  // exact
+//   "60.x" -> 00.0  // normalized
+//   "00.x" -> 00.x  // exact
+//
+// Errors are indicated by returning false and assigning an error message
+// to the "err" out param if it is non-null.
+//
+// Note: If the input string is exactly "infinite-future", the returned
+// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned.
+// If the input string is "infinite-past", the returned `absl::Time` will be
+// `absl::InfinitePast()` and `true` will be returned.
+//
+bool ParseTime(const std::string& format, const std::string& input, Time* time,
+               std::string* err);
+
+// Like ParseTime() above, but if the format string does not contain a UTC
+// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
+// given TimeZone.  This means that the input, by itself, does not identify a
+// unique instant.  Being time-zone dependent, it also admits the possibility
+// of ambiguity or non-existence, in which case the "pre" time (as defined
+// by TimeZone::TimeInfo) is returned.  For these reasons we recommend that
+// all date/time strings include a UTC offset so they're context independent.
+bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
+               Time* time, std::string* err);
+
 // ============================================================================
 // Implementation Details Follow
 // ============================================================================
@@ -1164,17 +1338,20 @@
   return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond)
                      : MakeDuration(sec, ticks);
 }
+
 // Provide access to the Duration representation.
 constexpr int64_t GetRepHi(Duration d) { return d.rep_hi_; }
 constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; }
+
+// Returns true iff d is positive or negative infinity.
 constexpr bool IsInfiniteDuration(Duration d) { return GetRepLo(d) == ~0U; }
 
 // Returns an infinite Duration with the opposite sign.
 // REQUIRES: IsInfiniteDuration(d)
 constexpr Duration OppositeInfinity(Duration d) {
   return GetRepHi(d) < 0
-             ? MakeDuration(std::numeric_limits<int64_t>::max(), ~0U)
-             : MakeDuration(std::numeric_limits<int64_t>::min(), ~0U);
+             ? MakeDuration((std::numeric_limits<int64_t>::max)(), ~0U)
+             : MakeDuration((std::numeric_limits<int64_t>::min)(), ~0U);
 }
 
 // Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow.
@@ -1199,14 +1376,14 @@
       v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N);
 }
 constexpr Duration FromInt64(int64_t v, std::ratio<60>) {
-  return (v <= std::numeric_limits<int64_t>::max() / 60 &&
-          v >= std::numeric_limits<int64_t>::min() / 60)
+  return (v <= (std::numeric_limits<int64_t>::max)() / 60 &&
+          v >= (std::numeric_limits<int64_t>::min)() / 60)
              ? MakeDuration(v * 60)
              : v > 0 ? InfiniteDuration() : -InfiniteDuration();
 }
 constexpr Duration FromInt64(int64_t v, std::ratio<3600>) {
-  return (v <= std::numeric_limits<int64_t>::max() / 3600 &&
-          v >= std::numeric_limits<int64_t>::min() / 3600)
+  return (v <= (std::numeric_limits<int64_t>::max)() / 3600 &&
+          v >= (std::numeric_limits<int64_t>::min)() / 3600)
              ? MakeDuration(v * 3600)
              : v > 0 ? InfiniteDuration() : -InfiniteDuration();
 }
@@ -1263,14 +1440,15 @@
   using Period = typename T::period;
   static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid");
   if (time_internal::IsInfiniteDuration(d))
-    return d < ZeroDuration() ? T::min() : T::max();
+    return d < ZeroDuration() ? (T::min)() : (T::max)();
   const auto v = ToInt64(d, Period{});
-  if (v > std::numeric_limits<Rep>::max()) return T::max();
-  if (v < std::numeric_limits<Rep>::min()) return T::min();
+  if (v > (std::numeric_limits<Rep>::max)()) return (T::max)();
+  if (v < (std::numeric_limits<Rep>::min)()) return (T::min)();
   return T{v};
 }
 
 }  // namespace time_internal
+
 constexpr Duration Nanoseconds(int64_t n) {
   return time_internal::FromInt64(n, std::nano{});
 }
@@ -1293,7 +1471,8 @@
 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::GetRepHi(lhs) ==
+                       (std::numeric_limits<int64_t>::min)()
                    ? time_internal::GetRepLo(lhs) + 1 <
                          time_internal::GetRepLo(rhs) + 1
                    : time_internal::GetRepLo(lhs) <
@@ -1318,7 +1497,8 @@
   // a second's worth of ticks and avoid overflow (as negating int64_t-min + 1
   // is safe).
   return time_internal::GetRepLo(d) == 0
-             ? time_internal::GetRepHi(d) == std::numeric_limits<int64_t>::min()
+             ? time_internal::GetRepHi(d) ==
+                       (std::numeric_limits<int64_t>::min)()
                    ? InfiniteDuration()
                    : time_internal::MakeDuration(-time_internal::GetRepHi(d))
              : time_internal::IsInfiniteDuration(d)
@@ -1331,7 +1511,8 @@
 }
 
 constexpr Duration InfiniteDuration() {
-  return time_internal::MakeDuration(std::numeric_limits<int64_t>::max(), ~0U);
+  return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),
+                                     ~0U);
 }
 
 constexpr Duration FromChrono(const std::chrono::nanoseconds& d) {
diff --git a/absl/time/time_benchmark.cc b/absl/time/time_benchmark.cc
index e100994..99e6279 100644
--- a/absl/time/time_benchmark.cc
+++ b/absl/time/time_benchmark.cc
@@ -3,7 +3,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -169,32 +169,32 @@
 BENCHMARK(BM_Time_ToUnixSeconds);
 
 //
-// FromDateTime
+// FromCivil
 //
-// In each "FromDateTime" benchmark we switch between two YMDhms
-// values separated by at least one transition in order to defeat any
-// internal caching of previous results (e.g., see time_local_hint_).
+// In each "FromCivil" benchmark we switch between two YMDhms values
+// separated by at least one transition in order to defeat any internal
+// caching of previous results (e.g., see time_local_hint_).
 //
 // The "UTC" variants use UTC instead of the Google/local time zone.
 // The "Day0" variants require normalization of the day of month.
 //
 
-void BM_Time_FromDateTime_Absl(benchmark::State& state) {
+void BM_Time_FromCivil_Absl(benchmark::State& state) {
   const absl::TimeZone tz =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
   int i = 0;
   while (state.KeepRunning()) {
     if ((i & 1) == 0) {
-      absl::FromDateTime(2014, 12, 18, 20, 16, 18, tz);
+      absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz);
     } else {
-      absl::FromDateTime(2013, 11, 15, 18, 30, 27, tz);
+      absl::FromCivil(absl::CivilSecond(2013, 11, 15, 18, 30, 27), tz);
     }
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTime_Absl);
+BENCHMARK(BM_Time_FromCivil_Absl);
 
-void BM_Time_FromDateTime_Libc(benchmark::State& state) {
+void BM_Time_FromCivil_Libc(benchmark::State& state) {
   // No timezone support, so just use localtime.
   int i = 0;
   while (state.KeepRunning()) {
@@ -219,32 +219,32 @@
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTime_Libc);
+BENCHMARK(BM_Time_FromCivil_Libc);
 
-void BM_Time_FromDateTimeUTC_Absl(benchmark::State& state) {
+void BM_Time_FromCivilUTC_Absl(benchmark::State& state) {
   const absl::TimeZone tz = absl::UTCTimeZone();
   while (state.KeepRunning()) {
-    FromDateTime(2014, 12, 18, 20, 16, 18, tz);
+    absl::FromCivil(absl::CivilSecond(2014, 12, 18, 20, 16, 18), tz);
   }
 }
-BENCHMARK(BM_Time_FromDateTimeUTC_Absl);
+BENCHMARK(BM_Time_FromCivilUTC_Absl);
 
-void BM_Time_FromDateTimeDay0_Absl(benchmark::State& state) {
+void BM_Time_FromCivilDay0_Absl(benchmark::State& state) {
   const absl::TimeZone tz =
       absl::time_internal::LoadTimeZone("America/Los_Angeles");
   int i = 0;
   while (state.KeepRunning()) {
     if ((i & 1) == 0) {
-      absl::FromDateTime(2014, 12, 0, 20, 16, 18, tz);
+      absl::FromCivil(absl::CivilSecond(2014, 12, 0, 20, 16, 18), tz);
     } else {
-      absl::FromDateTime(2013, 11, 0, 18, 30, 27, tz);
+      absl::FromCivil(absl::CivilSecond(2013, 11, 0, 18, 30, 27), tz);
     }
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTimeDay0_Absl);
+BENCHMARK(BM_Time_FromCivilDay0_Absl);
 
-void BM_Time_FromDateTimeDay0_Libc(benchmark::State& state) {
+void BM_Time_FromCivilDay0_Libc(benchmark::State& state) {
   // No timezone support, so just use localtime.
   int i = 0;
   while (state.KeepRunning()) {
@@ -269,7 +269,7 @@
     ++i;
   }
 }
-BENCHMARK(BM_Time_FromDateTimeDay0_Libc);
+BENCHMARK(BM_Time_FromCivilDay0_Libc);
 
 //
 // To/FromTimespec
diff --git a/absl/time/time_norm_test.cc b/absl/time/time_norm_test.cc
deleted file mode 100644
index 4436242..0000000
--- a/absl/time/time_norm_test.cc
+++ /dev/null
@@ -1,306 +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
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// This file contains tests for FromDateTime() normalization, which is
-// time-zone independent so we just use UTC throughout.
-
-#include <cstdint>
-#include <limits>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/time/internal/test_util.h"
-#include "absl/time/time.h"
-
-namespace {
-
-TEST(TimeNormCase, SimpleOverflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(2013, 11, 15, 16, 32, 59 + 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 33, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 59 + 1, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 17, 0, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 23 + 1, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 16, 0, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 30 + 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 1, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 12 + 1, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, SimpleUnderflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc = ConvertDateTime(2013, 11, 15, 16, 32, 0 - 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 16, 31, 59, 0, false);
-
-  tc = ConvertDateTime(2013, 11, 15, 16, 0 - 1, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 15, 15, 59, 14, 0, false);
-
-  tc = ConvertDateTime(2013, 11, 15, 0 - 1, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 14, 23, 32, 14, 0, false);
-
-  tc = ConvertDateTime(2013, 11, 1 - 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 10, 31, 16, 32, 14, 0, false);
-
-  tc = ConvertDateTime(2013, 1 - 1, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 12, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, MultipleOverflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::TimeConversion tc = ConvertDateTime(2013, 12, 31, 23, 59, 59 + 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2014, 1, 1, 0, 0, 0, 0, false);
-}
-
-TEST(TimeNormCase, MultipleUnderflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::TimeConversion tc = absl::ConvertDateTime(2014, 1, 1, 0, 0, 0 - 1, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 12, 31, 23, 59, 59, 0, false);
-}
-
-TEST(TimeNormCase, OverflowLimits) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::TimeConversion tc;
-  absl::Time::Breakdown bd;
-
-  const int kintmax = std::numeric_limits<int>::max();
-  tc = absl::ConvertDateTime(0, kintmax, kintmax, kintmax, kintmax, kintmax,
-                             utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 185085715, 11, 27, 12, 21, 7, 0, false);
-
-  const int kintmin = std::numeric_limits<int>::min();
-  tc = absl::ConvertDateTime(0, kintmin, kintmin, kintmin, kintmin, kintmin,
-                             utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, -185085717, 10, 31, 10, 37, 52, 0, false);
-
-  const int64_t max_year = std::numeric_limits<int64_t>::max();
-  tc = absl::ConvertDateTime(max_year, 12, 31, 23, 59, 59, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  EXPECT_EQ(absl::InfiniteFuture(), tc.pre);
-
-  const int64_t min_year = std::numeric_limits<int64_t>::min();
-  tc = absl::ConvertDateTime(min_year, 1, 1, 0, 0, 0, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  EXPECT_EQ(absl::InfinitePast(), tc.pre);
-}
-
-TEST(TimeNormCase, ComplexOverflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      ConvertDateTime(2013, 11, 15, 16, 32, 14 + 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 10, 14, 14, 5, 23, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 + 1234567, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2016, 3, 22, 0, 39, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16 + 123456, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2027, 12, 16, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15 + 1234, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2017, 4, 2, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11 + 123, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2024, 2, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, ComplexUnderflow) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(1999, 3, 0, 0, 0, 0, utc);  // year 400
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 2, 28, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 32, 14 - 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2009, 12, 17, 18, 59, 5, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16, 32 - 1234567, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2011, 7, 12, 8, 25, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15, 16 - 123456, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1999, 10, 16, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11, 15 - 1234, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2010, 6, 30, 16, 32, 14, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11 - 123, 15, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2003, 8, 15, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, Mishmash) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(2013, 11 - 123, 15 + 1234, 16 - 123456,
-                            32 + 1234567, 14 - 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1991, 5, 9, 3, 6, 5, 0, false);
-
-  tc = absl::ConvertDateTime(2013, 11 + 123, 15 - 1234, 16 + 123456,
-                             32 - 1234567, 14 + 123456789, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2036, 5, 24, 5, 58, 23, 0, false);
-
-  // Here is a normalization case we got wrong for a while.  Because the
-  // day is converted to "1" within a 400-year (146097-day) period, we
-  // didn't need to roll the month and so we didn't mark it as normalized.
-  tc = absl::ConvertDateTime(2013, 11, -146097 + 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1613, 11, 1, 16, 32, 14, 0, false);
-
-  // Even though the month overflow compensates for the day underflow,
-  // this should still be marked as normalized.
-  tc = absl::ConvertDateTime(2013, 11 + 400 * 12, -146097 + 1, 16, 32, 14, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 11, 1, 16, 32, 14, 0, false);
-}
-
-TEST(TimeNormCase, LeapYears) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-
-  absl::TimeConversion tc =
-      absl::ConvertDateTime(2013, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  absl::Time::Breakdown bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2013, 3, 1, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2012, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_FALSE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2012, 2, 29, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(2000, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_FALSE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 2000, 2, 29, 0, 0, 0, 0, false);
-
-  tc = absl::ConvertDateTime(1900, 2, 28 + 1, 0, 0, 0, utc);
-  EXPECT_TRUE(tc.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-  bd = tc.pre.In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1900, 3, 1, 0, 0, 0, 0, false);
-}
-
-// Convert all the days from 1970-1-1 to 1970-1-146097 (aka 2369-12-31)
-// and check that they normalize to the expected time.  146097 days span
-// the 400-year Gregorian cycle used during normalization.
-TEST(TimeNormCase, AllTheDays) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  absl::Time exp_time = absl::UnixEpoch();
-
-  for (int day = 1; day <= 146097; ++day) {
-    absl::TimeConversion tc = absl::ConvertDateTime(1970, 1, day, 0, 0, 0, utc);
-    EXPECT_EQ(day > 31, tc.normalized);
-    EXPECT_EQ(absl::TimeConversion::UNIQUE, tc.kind);
-    EXPECT_EQ(exp_time, tc.pre);
-    exp_time += absl::Hours(24);
-  }
-}
-
-}  // namespace
diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc
index 4f8f58a..74148d5 100644
--- a/absl/time/time_test.cc
+++ b/absl/time/time_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -28,6 +28,27 @@
 
 namespace {
 
+#if GTEST_USES_SIMPLE_RE
+const char kZoneAbbrRE[] = ".*";  // just punt
+#else
+const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
+#endif
+
+// This helper is a macro so that failed expectations show up with the
+// correct line numbers.
+#define EXPECT_CIVIL_INFO(ci, y, m, d, h, min, s, off, isdst)      \
+  do {                                                             \
+    EXPECT_EQ(y, ci.cs.year());                                    \
+    EXPECT_EQ(m, ci.cs.month());                                   \
+    EXPECT_EQ(d, ci.cs.day());                                     \
+    EXPECT_EQ(h, ci.cs.hour());                                    \
+    EXPECT_EQ(min, ci.cs.minute());                                \
+    EXPECT_EQ(s, ci.cs.second());                                  \
+    EXPECT_EQ(off, ci.offset);                                     \
+    EXPECT_EQ(isdst, ci.is_dst);                                   \
+    EXPECT_THAT(ci.zone_abbr, testing::MatchesRegex(kZoneAbbrRE)); \
+  } while (0)
+
 // A gMock matcher to match timespec values. Use this matcher like:
 // timespec ts1, ts2;
 // EXPECT_THAT(ts1, TimespecMatcher(ts2));
@@ -84,10 +105,10 @@
 }
 
 TEST(Time, UnixEpoch) {
-  absl::Time::Breakdown bd = absl::UnixEpoch().In(absl::UTCTimeZone());
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1970, 1, 1, 0, 0, 0, 0, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
-  EXPECT_EQ(4, bd.weekday);  // Thursday
+  const auto ci = absl::UTCTimeZone().At(absl::UnixEpoch());
+  EXPECT_EQ(absl::CivilSecond(1970, 1, 1, 0, 0, 0), ci.cs);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 }
 
 TEST(Time, Breakdown) {
@@ -95,26 +116,26 @@
   absl::Time t = absl::UnixEpoch();
 
   // The Unix epoch as seen in NYC.
-  absl::Time::Breakdown bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 19, 0, 0, -18000, false);
-  EXPECT_EQ(absl::ZeroDuration(), bd.subsecond);
-  EXPECT_EQ(3, bd.weekday);  // Wednesday
+  auto ci = tz.At(t);
+  EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 19, 0, 0, -18000, false);
+  EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 
   // Just before the epoch.
   t -= absl::Nanoseconds(1);
-  bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1969, 12, 31, 18, 59, 59, -18000, false);
-  EXPECT_EQ(absl::Nanoseconds(999999999), bd.subsecond);
-  EXPECT_EQ(3, bd.weekday);  // Wednesday
+  ci = tz.At(t);
+  EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 18, 59, 59, -18000, false);
+  EXPECT_EQ(absl::Nanoseconds(999999999), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 
   // Some time later.
   t += absl::Hours(24) * 2735;
   t += absl::Hours(18) + absl::Minutes(30) + absl::Seconds(15) +
        absl::Nanoseconds(9);
-  bd = t.In(tz);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 1977, 6, 28, 14, 30, 15, -14400, true);
-  EXPECT_EQ(8, bd.subsecond / absl::Nanoseconds(1));
-  EXPECT_EQ(2, bd.weekday);  // Tuesday
+  ci = tz.At(t);
+  EXPECT_CIVIL_INFO(ci, 1977, 6, 28, 14, 30, 15, -14400, true);
+  EXPECT_EQ(8, ci.subsecond / absl::Nanoseconds(1));
+  EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
 }
 
 TEST(Time, AdditiveOperators) {
@@ -550,67 +571,63 @@
             absl::ToChronoTime(absl::UnixEpoch() - tick));
 }
 
-TEST(Time, ConvertDateTime) {
-  const absl::TimeZone utc = absl::UTCTimeZone();
-  const absl::TimeZone goog =
-      absl::time_internal::LoadTimeZone("America/Los_Angeles");
+TEST(Time, TimeZoneAt) {
   const absl::TimeZone nyc =
       absl::time_internal::LoadTimeZone("America/New_York");
   const std::string fmt = "%a, %e %b %Y %H:%M:%S %z (%Z)";
 
-  // A simple case of normalization.
-  absl::TimeConversion oct32 = ConvertDateTime(2013, 10, 32, 8, 30, 0, goog);
-  EXPECT_TRUE(oct32.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, oct32.kind);
-  absl::TimeConversion nov01 = ConvertDateTime(2013, 11, 1, 8, 30, 0, goog);
-  EXPECT_FALSE(nov01.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, nov01.kind);
-  EXPECT_EQ(oct32.pre, nov01.pre);
-  EXPECT_EQ("Fri,  1 Nov 2013 08:30:00 -0700 (PDT)",
-            absl::FormatTime(fmt, nov01.pre, goog));
+  // A non-transition where the civil time is unique.
+  absl::CivilSecond nov01(2013, 11, 1, 8, 30, 0);
+  const auto nov01_ci = nyc.At(nov01);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, nov01_ci.kind);
+  EXPECT_EQ("Fri,  1 Nov 2013 08:30:00 -0400 (EDT)",
+            absl::FormatTime(fmt, nov01_ci.pre, nyc));
+  EXPECT_EQ(nov01_ci.pre, nov01_ci.trans);
+  EXPECT_EQ(nov01_ci.pre, nov01_ci.post);
+  EXPECT_EQ(nov01_ci.pre, absl::FromCivil(nov01, nyc));
 
   // A Spring DST transition, when there is a gap in civil time
   // and we prefer the later of the possible interpretations of a
   // non-existent time.
-  absl::TimeConversion mar13 = ConvertDateTime(2011, 3, 13, 2, 15, 0, nyc);
-  EXPECT_FALSE(mar13.normalized);
-  EXPECT_EQ(absl::TimeConversion::SKIPPED, mar13.kind);
+  absl::CivilSecond mar13(2011, 3, 13, 2, 15, 0);
+  const auto mar_ci = nyc.At(mar13);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::SKIPPED, mar_ci.kind);
   EXPECT_EQ("Sun, 13 Mar 2011 03:15:00 -0400 (EDT)",
-            absl::FormatTime(fmt, mar13.pre, nyc));
+            absl::FormatTime(fmt, mar_ci.pre, nyc));
   EXPECT_EQ("Sun, 13 Mar 2011 03:00:00 -0400 (EDT)",
-            absl::FormatTime(fmt, mar13.trans, nyc));
+            absl::FormatTime(fmt, mar_ci.trans, nyc));
   EXPECT_EQ("Sun, 13 Mar 2011 01:15:00 -0500 (EST)",
-            absl::FormatTime(fmt, mar13.post, nyc));
-  EXPECT_EQ(mar13.pre, absl::FromDateTime(2011, 3, 13, 2, 15, 0, nyc));
+            absl::FormatTime(fmt, mar_ci.post, nyc));
+  EXPECT_EQ(mar_ci.trans, absl::FromCivil(mar13, nyc));
 
   // A Fall DST transition, when civil times are repeated and
   // we prefer the earlier of the possible interpretations of an
   // ambiguous time.
-  absl::TimeConversion nov06 = ConvertDateTime(2011, 11, 6, 1, 15, 0, nyc);
-  EXPECT_FALSE(nov06.normalized);
-  EXPECT_EQ(absl::TimeConversion::REPEATED, nov06.kind);
+  absl::CivilSecond nov06(2011, 11, 6, 1, 15, 0);
+  const auto nov06_ci = nyc.At(nov06);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::REPEATED, nov06_ci.kind);
   EXPECT_EQ("Sun,  6 Nov 2011 01:15:00 -0400 (EDT)",
-            absl::FormatTime(fmt, nov06.pre, nyc));
+            absl::FormatTime(fmt, nov06_ci.pre, nyc));
   EXPECT_EQ("Sun,  6 Nov 2011 01:00:00 -0500 (EST)",
-            absl::FormatTime(fmt, nov06.trans, nyc));
+            absl::FormatTime(fmt, nov06_ci.trans, nyc));
   EXPECT_EQ("Sun,  6 Nov 2011 01:15:00 -0500 (EST)",
-            absl::FormatTime(fmt, nov06.post, nyc));
-  EXPECT_EQ(nov06.pre, absl::FromDateTime(2011, 11, 6, 1, 15, 0, nyc));
+            absl::FormatTime(fmt, nov06_ci.post, nyc));
+  EXPECT_EQ(nov06_ci.pre, absl::FromCivil(nov06, nyc));
 
   // Check that (time_t) -1 is handled correctly.
-  absl::TimeConversion minus1 = ConvertDateTime(1969, 12, 31, 18, 59, 59, nyc);
-  EXPECT_FALSE(minus1.normalized);
-  EXPECT_EQ(absl::TimeConversion::UNIQUE, minus1.kind);
-  EXPECT_EQ(-1, absl::ToTimeT(minus1.pre));
+  absl::CivilSecond minus1(1969, 12, 31, 18, 59, 59);
+  const auto minus1_cl = nyc.At(minus1);
+  EXPECT_EQ(absl::TimeZone::TimeInfo::UNIQUE, minus1_cl.kind);
+  EXPECT_EQ(-1, absl::ToTimeT(minus1_cl.pre));
   EXPECT_EQ("Wed, 31 Dec 1969 18:59:59 -0500 (EST)",
-            absl::FormatTime(fmt, minus1.pre, nyc));
+            absl::FormatTime(fmt, minus1_cl.pre, nyc));
   EXPECT_EQ("Wed, 31 Dec 1969 23:59:59 +0000 (UTC)",
-            absl::FormatTime(fmt, minus1.pre, utc));
+            absl::FormatTime(fmt, minus1_cl.pre, absl::UTCTimeZone()));
 }
 
-// FromDateTime(year, mon, day, hour, min, sec, UTCTimeZone()) has
-// a specialized fastpath implementation which we exercise here.
-TEST(Time, FromDateTimeUTC) {
+// FromCivil(CivilSecond(year, mon, day, hour, min, sec), UTCTimeZone())
+// has a specialized fastpath implementation, which we exercise here.
+TEST(Time, FromCivilUTC) {
   const absl::TimeZone utc = absl::UTCTimeZone();
   const std::string fmt = "%a, %e %b %Y %H:%M:%S %z (%Z)";
   const int kMax = std::numeric_limits<int>::max();
@@ -618,65 +635,36 @@
   absl::Time t;
 
   // 292091940881 is the last positive year to use the fastpath.
-  t = absl::FromDateTime(292091940881, kMax, kMax, kMax, kMax, kMax, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(292091940881, kMax, kMax, kMax, kMax, kMax), utc);
   EXPECT_EQ("Fri, 25 Nov 292277026596 12:21:07 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(292091940882, kMax, kMax, kMax, kMax, kMax, utc);
-  EXPECT_EQ("infinite-future", absl::FormatTime(fmt, t, utc));  // no overflow
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::max(), kMax, kMax, kMax, kMax, kMax, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(292091940882, kMax, kMax, kMax, kMax, kMax), utc);
   EXPECT_EQ("infinite-future", absl::FormatTime(fmt, t, utc));  // no overflow
 
   // -292091936940 is the last negative year to use the fastpath.
-  t = absl::FromDateTime(-292091936940, kMin, kMin, kMin, kMin, kMin, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(-292091936940, kMin, kMin, kMin, kMin, kMin), utc);
   EXPECT_EQ("Fri,  1 Nov -292277022657 10:37:52 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(-292091936941, kMin, kMin, kMin, kMin, kMin, utc);
+  t = absl::FromCivil(
+      absl::CivilSecond(-292091936941, kMin, kMin, kMin, kMin, kMin), utc);
   EXPECT_EQ("infinite-past", absl::FormatTime(fmt, t, utc));  // no underflow
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::min(), kMin, kMin, kMin, kMin, kMin, utc);
-  EXPECT_EQ("infinite-past", absl::FormatTime(fmt, t, utc));  // no overflow
 
   // Check that we're counting leap years correctly.
-  t = absl::FromDateTime(1900, 2, 28, 23, 59, 59, utc);
+  t = absl::FromCivil(absl::CivilSecond(1900, 2, 28, 23, 59, 59), utc);
   EXPECT_EQ("Wed, 28 Feb 1900 23:59:59 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(1900, 3, 1, 0, 0, 0, utc);
+  t = absl::FromCivil(absl::CivilSecond(1900, 3, 1, 0, 0, 0), utc);
   EXPECT_EQ("Thu,  1 Mar 1900 00:00:00 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(2000, 2, 29, 23, 59, 59, utc);
+  t = absl::FromCivil(absl::CivilSecond(2000, 2, 29, 23, 59, 59), utc);
   EXPECT_EQ("Tue, 29 Feb 2000 23:59:59 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-  t = absl::FromDateTime(2000, 3, 1, 0, 0, 0, utc);
+  t = absl::FromCivil(absl::CivilSecond(2000, 3, 1, 0, 0, 0), utc);
   EXPECT_EQ("Wed,  1 Mar 2000 00:00:00 +0000 (UTC)",
             absl::FormatTime(fmt, t, utc));
-
-  // Check normalization.
-  const std::string ymdhms = "%Y-%m-%d %H:%M:%S";
-  t = absl::FromDateTime(2015, 1, 1, 0, 0, 60, utc);
-  EXPECT_EQ("2015-01-01 00:01:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 0, 60, 0, utc);
-  EXPECT_EQ("2015-01-01 01:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 24, 0, 0, utc);
-  EXPECT_EQ("2015-01-02 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 32, 0, 0, 0, utc);
-  EXPECT_EQ("2015-02-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 13, 1, 0, 0, 0, utc);
-  EXPECT_EQ("2016-01-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 13, 32, 60, 60, 60, utc);
-  EXPECT_EQ("2016-02-03 13:01:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 0, 0, -1, utc);
-  EXPECT_EQ("2014-12-31 23:59:59", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, 0, -1, 0, utc);
-  EXPECT_EQ("2014-12-31 23:59:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, 1, -1, 0, 0, utc);
-  EXPECT_EQ("2014-12-31 23:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, 1, -1, 0, 0, 0, utc);
-  EXPECT_EQ("2014-12-30 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, -1, 1, 0, 0, 0, utc);
-  EXPECT_EQ("2014-11-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
-  t = absl::FromDateTime(2015, -1, -1, -1, -1, -1, utc);
-  EXPECT_EQ("2014-10-29 22:58:59", absl::FormatTime(ymdhms, t, utc));
 }
 
 TEST(Time, ToTM) {
@@ -684,8 +672,10 @@
 
   // Compares the results of ToTM() to gmtime_r() for lots of times over the
   // course of a few days.
-  const absl::Time start = absl::FromDateTime(2014, 1, 2, 3, 4, 5, utc);
-  const absl::Time end = absl::FromDateTime(2014, 1, 5, 3, 4, 5, utc);
+  const absl::Time start =
+      absl::FromCivil(absl::CivilSecond(2014, 1, 2, 3, 4, 5), utc);
+  const absl::Time end =
+      absl::FromCivil(absl::CivilSecond(2014, 1, 5, 3, 4, 5), utc);
   for (absl::Time t = start; t < end; t += absl::Seconds(30)) {
     const struct tm tm_bt = ToTM(t, utc);
     const time_t tt = absl::ToTimeT(t);
@@ -711,12 +701,12 @@
   // Checks that the tm_isdst field is correct when in standard time.
   const absl::TimeZone nyc =
       absl::time_internal::LoadTimeZone("America/New_York");
-  absl::Time t = absl::FromDateTime(2014, 3, 1, 0, 0, 0, nyc);
+  absl::Time t = absl::FromCivil(absl::CivilSecond(2014, 3, 1, 0, 0, 0), nyc);
   struct tm tm = ToTM(t, nyc);
   EXPECT_FALSE(tm.tm_isdst);
 
   // Checks that the tm_isdst field is correct when in daylight time.
-  t = absl::FromDateTime(2014, 4, 1, 0, 0, 0, nyc);
+  t = absl::FromCivil(absl::CivilSecond(2014, 4, 1, 0, 0, 0), nyc);
   tm = ToTM(t, nyc);
   EXPECT_TRUE(tm.tm_isdst);
 
@@ -808,8 +798,8 @@
       absl::time_internal::LoadTimeZone("America/New_York");
 
   // Test round-tripping across a skipped transition
-  absl::Time start = absl::FromDateTime(2014, 3, 9, 0, 0, 0, nyc);
-  absl::Time end = absl::FromDateTime(2014, 3, 9, 4, 0, 0, nyc);
+  absl::Time start = absl::FromCivil(absl::CivilHour(2014, 3, 9, 0), nyc);
+  absl::Time end = absl::FromCivil(absl::CivilHour(2014, 3, 9, 4), nyc);
   for (absl::Time t = start; t < end; t += absl::Minutes(1)) {
     struct tm tm = ToTM(t, nyc);
     absl::Time rt = FromTM(tm, nyc);
@@ -817,8 +807,8 @@
   }
 
   // Test round-tripping across an ambiguous transition
-  start = absl::FromDateTime(2014, 11, 2, 0, 0, 0, nyc);
-  end = absl::FromDateTime(2014, 11, 2, 4, 0, 0, nyc);
+  start = absl::FromCivil(absl::CivilHour(2014, 11, 2, 0), nyc);
+  end = absl::FromCivil(absl::CivilHour(2014, 11, 2, 4), nyc);
   for (absl::Time t = start; t < end; t += absl::Minutes(1)) {
     struct tm tm = ToTM(t, nyc);
     absl::Time rt = FromTM(tm, nyc);
@@ -826,8 +816,8 @@
   }
 
   // Test round-tripping of unique instants crossing a day boundary
-  start = absl::FromDateTime(2014, 6, 27, 22, 0, 0, nyc);
-  end = absl::FromDateTime(2014, 6, 28, 4, 0, 0, nyc);
+  start = absl::FromCivil(absl::CivilHour(2014, 6, 27, 22), nyc);
+  end = absl::FromCivil(absl::CivilHour(2014, 6, 28, 4), nyc);
   for (absl::Time t = start; t < end; t += absl::Minutes(1)) {
     struct tm tm = ToTM(t, nyc);
     absl::Time rt = FromTM(tm, nyc);
@@ -980,27 +970,27 @@
   EXPECT_EQ(min_timespec_sec, ts.tv_sec);
   EXPECT_EQ(0, ts.tv_nsec);
 
-  // Checks how Time::In() saturates on infinities.
-  absl::Time::Breakdown bd = absl::InfiniteFuture().In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::max(), 12, 31, 23,
+  // Checks how TimeZone::At() saturates on infinities.
+  auto ci = utc.At(absl::InfiniteFuture());
+  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23,
                             59, 59, 0, false);
-  EXPECT_EQ(absl::InfiniteDuration(), bd.subsecond);
-  EXPECT_EQ(4, bd.weekday);  // Thursday
-  EXPECT_EQ(365, bd.yearday);
-  EXPECT_STREQ("-00", bd.zone_abbr);  // artifact of absl::Time::In()
-  bd = absl::InfinitePast().In(utc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
+  EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+  EXPECT_EQ(365, absl::GetYearDay(absl::CivilDay(ci.cs)));
+  EXPECT_STREQ("-00", ci.zone_abbr);  // artifact of TimeZone::At()
+  ci = utc.At(absl::InfinitePast());
+  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
                             0, 0, false);
-  EXPECT_EQ(-absl::InfiniteDuration(), bd.subsecond);
-  EXPECT_EQ(7, bd.weekday);  // Sunday
-  EXPECT_EQ(1, bd.yearday);
-  EXPECT_STREQ("-00", bd.zone_abbr);  // artifact of absl::Time::In()
+  EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond);
+  EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+  EXPECT_EQ(1, absl::GetYearDay(absl::CivilDay(ci.cs)));
+  EXPECT_STREQ("-00", ci.zone_abbr);  // artifact of TimeZone::At()
 
   // Approach the maximal Time value from below.
-  t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 6, utc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 6), utc);
   EXPECT_EQ("292277026596-12-04T15:30:06+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
-  t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 7, utc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 7), utc);
   EXPECT_EQ("292277026596-12-04T15:30:07+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
@@ -1008,21 +998,21 @@
 
   // Checks that we can also get the maximal Time value for a far-east zone.
   const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60);
-  t = absl::FromDateTime(292277026596, 12, 5, 5, 30, 7, plus14);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 5, 30, 7), plus14);
   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);
 
   // One second later should push us to infinity.
-  t = absl::FromDateTime(292277026596, 12, 4, 15, 30, 8, utc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc);
   EXPECT_EQ("infinite-future", absl::FormatTime(absl::RFC3339_full, t, utc));
 
   // Approach the minimal Time value from above.
-  t = absl::FromDateTime(-292277022657, 1, 27, 8, 29, 53, utc);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 53), utc);
   EXPECT_EQ("-292277022657-01-27T08:29:53+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
-  t = absl::FromDateTime(-292277022657, 1, 27, 8, 29, 52, utc);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 52), utc);
   EXPECT_EQ("-292277022657-01-27T08:29:52+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
@@ -1030,14 +1020,15 @@
 
   // Checks that we can also get the minimal Time value for a far-west zone.
   const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60);
-  t = absl::FromDateTime(-292277022657, 1, 26, 20, 29, 52, minus12);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 26, 20, 29, 52),
+                      minus12);
   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);
 
   // One second before should push us to -infinity.
-  t = absl::FromDateTime(-292277022657, 1, 27, 8, 29, 51, utc);
+  t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc);
   EXPECT_EQ("infinite-past", absl::FormatTime(absl::RFC3339_full, t, utc));
 }
 
@@ -1051,38 +1042,160 @@
       absl::time_internal::LoadTimeZone("America/New_York");
   const absl::Time max =
       absl::FromUnixSeconds(std::numeric_limits<int64_t>::max());
-  absl::Time::Breakdown bd;
+  absl::TimeZone::CivilInfo ci;
   absl::Time t;
 
   // The maximal time converted in each zone.
-  bd = max.In(syd);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 5, 2, 30, 7, 39600, true);
-  t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 7, syd);
+  ci = syd.At(max);
+  EXPECT_CIVIL_INFO(ci, 292277026596, 12, 5, 2, 30, 7, 39600, true);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 7), syd);
   EXPECT_EQ(max, t);
-  bd = max.In(nyc);
-  ABSL_INTERNAL_EXPECT_TIME(bd, 292277026596, 12, 4, 10, 30, 7, -18000, false);
-  t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 7, nyc);
+  ci = nyc.At(max);
+  EXPECT_CIVIL_INFO(ci, 292277026596, 12, 4, 10, 30, 7, -18000, false);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 7), nyc);
   EXPECT_EQ(max, t);
 
   // One second later should push us to infinity.
-  t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 8, syd);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 8), syd);
   EXPECT_EQ(absl::InfiniteFuture(), t);
-  t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 8, nyc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 8), nyc);
   EXPECT_EQ(absl::InfiniteFuture(), t);
 
   // And we should stick there.
-  t = absl::FromDateTime(292277026596, 12, 5, 2, 30, 9, syd);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 5, 2, 30, 9), syd);
   EXPECT_EQ(absl::InfiniteFuture(), t);
-  t = absl::FromDateTime(292277026596, 12, 4, 10, 30, 9, nyc);
+  t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 10, 30, 9), nyc);
   EXPECT_EQ(absl::InfiniteFuture(), t);
 
   // All the way up to a saturated date/time, without overflow.
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59, syd);
+  t = absl::FromCivil(absl::CivilSecond::max(), syd);
   EXPECT_EQ(absl::InfiniteFuture(), t);
-  t = absl::FromDateTime(
-      std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59, nyc);
+  t = absl::FromCivil(absl::CivilSecond::max(), nyc);
   EXPECT_EQ(absl::InfiniteFuture(), t);
 }
 
+TEST(Time, FromCivilAlignment) {
+  const absl::TimeZone utc = absl::UTCTimeZone();
+  const absl::CivilSecond cs(2015, 2, 3, 4, 5, 6);
+  absl::Time t = absl::FromCivil(cs, utc);
+  EXPECT_EQ("2015-02-03T04:05:06+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilMinute(cs), utc);
+  EXPECT_EQ("2015-02-03T04:05:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilHour(cs), utc);
+  EXPECT_EQ("2015-02-03T04:00:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilDay(cs), utc);
+  EXPECT_EQ("2015-02-03T00:00:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilMonth(cs), utc);
+  EXPECT_EQ("2015-02-01T00:00:00+00:00", absl::FormatTime(t, utc));
+  t = absl::FromCivil(absl::CivilYear(cs), utc);
+  EXPECT_EQ("2015-01-01T00:00:00+00:00", absl::FormatTime(t, utc));
+}
+
+TEST(Time, LegacyDateTime) {
+  const absl::TimeZone utc = absl::UTCTimeZone();
+  const std::string ymdhms = "%Y-%m-%d %H:%M:%S";
+  const int kMax = std::numeric_limits<int>::max();
+  const int kMin = std::numeric_limits<int>::min();
+  absl::Time t;
+
+  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(),
+                         kMax, kMax, kMax, kMax, kMax, utc);
+  EXPECT_EQ("infinite-future",
+            absl::FormatTime(ymdhms, t, utc));  // no overflow
+  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(),
+                         kMin, kMin, kMin, kMin, kMin, utc);
+  EXPECT_EQ("infinite-past",
+            absl::FormatTime(ymdhms, t, utc));  // no overflow
+
+  // Check normalization.
+  EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized);
+  t = absl::FromDateTime(2015, 1, 1, 0, 0, 60, utc);
+  EXPECT_EQ("2015-01-01 00:01:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 0, 60, 0, utc);
+  EXPECT_EQ("2015-01-01 01:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 24, 0, 0, utc);
+  EXPECT_EQ("2015-01-02 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 32, 0, 0, 0, utc);
+  EXPECT_EQ("2015-02-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 13, 1, 0, 0, 0, utc);
+  EXPECT_EQ("2016-01-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 13, 32, 60, 60, 60, utc);
+  EXPECT_EQ("2016-02-03 13:01:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 0, 0, -1, utc);
+  EXPECT_EQ("2014-12-31 23:59:59", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, 0, -1, 0, utc);
+  EXPECT_EQ("2014-12-31 23:59:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, 1, -1, 0, 0, utc);
+  EXPECT_EQ("2014-12-31 23:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, 1, -1, 0, 0, 0, utc);
+  EXPECT_EQ("2014-12-30 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, -1, 1, 0, 0, 0, utc);
+  EXPECT_EQ("2014-11-01 00:00:00", absl::FormatTime(ymdhms, t, utc));
+  t = absl::FromDateTime(2015, -1, -1, -1, -1, -1, utc);
+  EXPECT_EQ("2014-10-29 22:58:59", absl::FormatTime(ymdhms, t, utc));
+}
+
+TEST(Time, NextTransitionUTC) {
+  const auto tz = absl::UTCTimeZone();
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::InfinitePast();
+  EXPECT_FALSE(tz.NextTransition(t, &trans));
+
+  t = absl::InfiniteFuture();
+  EXPECT_FALSE(tz.NextTransition(t, &trans));
+}
+
+TEST(Time, PrevTransitionUTC) {
+  const auto tz = absl::UTCTimeZone();
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::InfiniteFuture();
+  EXPECT_FALSE(tz.PrevTransition(t, &trans));
+
+  t = absl::InfinitePast();
+  EXPECT_FALSE(tz.PrevTransition(t, &trans));
+}
+
+TEST(Time, NextTransitionNYC) {
+  const auto tz = absl::time_internal::LoadTimeZone("America/New_York");
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz);
+  EXPECT_TRUE(tz.NextTransition(t, &trans));
+  EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 2, 0, 0), trans.from);
+  EXPECT_EQ(absl::CivilSecond(2018, 11, 4, 1, 0, 0), trans.to);
+
+  t = absl::InfiniteFuture();
+  EXPECT_FALSE(tz.NextTransition(t, &trans));
+
+  t = absl::InfinitePast();
+  EXPECT_TRUE(tz.NextTransition(t, &trans));
+  if (trans.from == absl::CivilSecond(1918, 03, 31, 2, 0, 0)) {
+    // It looks like the tzdata is only 32 bit (probably macOS),
+    // which bottoms out at 1901-12-13T20:45:52+00:00.
+    EXPECT_EQ(absl::CivilSecond(1918, 3, 31, 3, 0, 0), trans.to);
+  } else {
+    EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 3, 58), trans.from);
+    EXPECT_EQ(absl::CivilSecond(1883, 11, 18, 12, 0, 0), trans.to);
+  }
+}
+
+TEST(Time, PrevTransitionNYC) {
+  const auto tz = absl::time_internal::LoadTimeZone("America/New_York");
+  absl::TimeZone::CivilTransition trans;
+
+  auto t = absl::FromCivil(absl::CivilSecond(2018, 6, 30, 0, 0, 0), tz);
+  EXPECT_TRUE(tz.PrevTransition(t, &trans));
+  EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 2, 0, 0), trans.from);
+  EXPECT_EQ(absl::CivilSecond(2018, 3, 11, 3, 0, 0), trans.to);
+
+  t = absl::InfinitePast();
+  EXPECT_FALSE(tz.PrevTransition(t, &trans));
+
+  t = absl::InfiniteFuture();
+  EXPECT_TRUE(tz.PrevTransition(t, &trans));
+  // We have a transition but we don't know which one.
+}
+
 }  // namespace
diff --git a/absl/time/time_zone_test.cc b/absl/time/time_zone_test.cc
index 43d9190..8f1e74a 100644
--- a/absl/time/time_zone_test.cc
+++ b/absl/time/time_zone_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index 32f690c..7da0003 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -15,7 +15,7 @@
 #
 
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
     "ABSL_EXCEPTIONS_FLAG",
@@ -168,6 +168,7 @@
     deps = [
         ":bad_optional_access",
         "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/utility",
@@ -286,6 +287,7 @@
     linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
     deps = [
         ":variant",
+        "//absl/base:config",
         "//absl/base:exception_safety_testing",
         "//absl/memory",
         "@com_google_googletest//:gtest_main",
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 2f2e3a7..8afde46 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -13,216 +13,306 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
-list(APPEND TYPES_PUBLIC_HEADERS
-  "any.h"
-  "bad_any_cast.h"
-  "bad_optional_access.h"
-  "optional.h"
-  "span.h"
-  "variant.h"
-)
-
-
-# any library
-absl_header_library(
-  TARGET
-    absl_any
-  PUBLIC_LIBRARIES
-    absl::bad_any_cast
-    absl::base
-    absl::meta
-    absl::utility
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     any
-)
-
-# span library
-absl_header_library(
-  TARGET
-    absl_span
-  PUBLIC_LIBRARIES
+  HDRS
+    "any.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_any_cast
+    absl::config
+    absl::core_headers
+    absl::type_traits
     absl::utility
-  EXPORT_NAME
-    span
+  PUBLIC
 )
 
-
-# bad_any_cast library
-list(APPEND BAD_ANY_CAST_SRC
-  "bad_any_cast.cc"
-  ${TYPES_PUBLIC_HEADERS}
-)
-
-absl_library(
-  TARGET
-    absl_bad_any_cast
-  SOURCES
-    ${BAD_ANY_CAST_SRC}
-  PUBLIC_LIBRARIES
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     bad_any_cast
+  HDRS
+   "bad_any_cast.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_any_cast_impl
+    absl::config
+  PUBLIC
 )
 
-
-# optional library
-list(APPEND OPTIONAL_SRC
-  "optional.cc"
-)
-
-absl_library(
-  TARGET
-    absl_optional
-  SOURCES
-    ${OPTIONAL_SRC}
-  PUBLIC_LIBRARIES
-    absl::bad_optional_access
+absl_cc_library(
+  NAME
+    bad_any_cast_impl
+  SRCS
+   "bad_any_cast.h"
+   "bad_any_cast.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
     absl::base
-    absl::memory
-    absl::meta
-    absl::utility
-  EXPORT_NAME
-    optional
+    absl::config
 )
 
-
-set(BAD_OPTIONAL_ACCESS_SRC "bad_optional_access.cc")
-set(BAD_OPTIONAL_ACCESS_LIBRARIES absl::base)
-
-absl_library(
-  TARGET
-    absl_bad_optional_access
-  SOURCES
-    ${BAD_OPTIONAL_ACCESS_SRC}
-  PUBLIC_LIBRARIES
-    ${BAD_OPTIONAL_ACCESS_PUBLIC_LIBRARIES}
-  EXPORT_NAME
-    bad_optional_access
-)
-
-# variant library
-absl_library(
-  TARGET
-    absl_variant
-  SOURCES
-    "bad_variant_access.h" "bad_variant_access.cc" "variant.h" "internal/variant.h"
-  PUBLIC_LIBRARIES
-    absl::base absl::meta absl::utility
-  PRIVATE_COMPILE_FLAGS
-    ${ABSL_EXCEPTIONS_FLAG}
-  EXPORT_NAME
-    variant
-)
-
-#
-## TESTS
-#
-
-
-# test any_test
-set(ANY_TEST_SRC "any_test.cc")
-set(ANY_TEST_PUBLIC_LIBRARIES absl::base absl::throw_delegate absl::any absl::bad_any_cast test_instance_tracker_lib)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     any_test
-  SOURCES
-    ${ANY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ANY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "any_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::any
+    absl::base
+    absl::config
+    absl::exception_testing
+    absl::test_instance_tracker
+    gmock_main
 )
 
-
-# test any_test_noexceptions
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     any_test_noexceptions
-  SOURCES
-    ${ANY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ANY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "any_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::any
+    absl::base
+    absl::config
+    absl::exception_testing
+    absl::test_instance_tracker
+    gmock_main
 )
 
-# test any_exception_safety_test
-set(ANY_EXCEPTION_SAFETY_TEST_SRC "any_exception_safety_test.cc")
-set(ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::any
-  absl::base
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     any_exception_safety_test
-  SOURCES
-    ${ANY_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${ANY_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "any_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::any
+    absl::exception_safety_testing
+    gmock_main
 )
 
+absl_cc_library(
+  NAME
+    span
+  HDRS
+    "span.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::algorithm
+    absl::core_headers
+    absl::throw_delegate
+    absl::type_traits
+  PUBLIC
+)
 
-# test span_test
-set(SPAN_TEST_SRC "span_test.cc")
-set(SPAN_TEST_PUBLIC_LIBRARIES absl::base absl::strings absl::throw_delegate absl::span test_instance_tracker_lib)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     span_test
-  SOURCES
-    ${SPAN_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SPAN_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+  SRCS
+    "span_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::span
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::exception_testing
+    absl::fixed_array
+    absl::inlined_vector
+    absl::hash_testing
+    absl::strings
+    gmock_main
 )
 
-
-# test span_test_noexceptions
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     span_test_noexceptions
-  SOURCES
-    ${SPAN_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${SPAN_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "span_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::span
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::exception_testing
+    absl::fixed_array
+    absl::inlined_vector
+    absl::hash_testing
+    absl::strings
+    gmock_main
 )
 
-
-
-# test optional_test
-set(OPTIONAL_TEST_SRC "optional_test.cc")
-set(OPTIONAL_TEST_PUBLIC_LIBRARIES absl::base absl::throw_delegate absl::optional absl_bad_optional_access)
-
-absl_test(
-  TARGET
-    optional_test
-  SOURCES
-    ${OPTIONAL_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${OPTIONAL_TEST_PUBLIC_LIBRARIES}
+absl_cc_library(
+  NAME
+    optional
+  HDRS
+    "optional.h"
+  SRCS
+    "optional.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_optional_access
+    absl::config
+    absl::core_headers
+    absl::memory
+    absl::type_traits
+    absl::utility
+  PUBLIC
 )
 
-
-# test optional_exception_safety_test
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_SRC "optional_exception_safety_test.cc")
-set(OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES
-  absl::optional
-  absl_base_internal_exception_safety_testing
-)
-
-absl_test(
-  TARGET
-    optional_exception_safety_test
-  SOURCES
-    ${OPTIONAL_EXCEPTION_SAFETY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${OPTIONAL_EXCEPTION_SAFETY_TEST_PUBLIC_LIBRARIES}
-  PRIVATE_COMPILE_FLAGS
+absl_cc_library(
+  NAME
+    bad_optional_access
+  HDRS
+    "bad_optional_access.h"
+  SRCS
+    "bad_optional_access.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
     ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+  PUBLIC
 )
+
+absl_cc_library(
+  NAME
+    bad_variant_access
+  HDRS
+    "bad_variant_access.h"
+  SRCS
+    "bad_variant_access.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    optional_test
+  SRCS
+    "optional_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::optional
+    absl::base
+    absl::config
+    absl::type_traits
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    optional_exception_safety_test
+  SRCS
+    "optional_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::optional
+    absl::exception_safety_testing
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    variant
+  HDRS
+    "variant.h"
+  SRCS
+    "internal/variant.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bad_variant_access
+    absl::base_internal
+    absl::config
+    absl::core_headers
+    absl::type_traits
+    absl::utility
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    variant_test
+  SRCS
+    "variant_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::variant
+    absl::config
+    absl::core_headers
+    absl::memory
+    absl::type_traits
+    absl::strings
+    gmock_main
+)
+
+# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8
+if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9)
+absl_cc_test(
+  NAME
+    variant_exception_safety_test
+  SRCS
+    "variant_exception_safety_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::variant
+    absl::config
+    absl::exception_safety_testing
+    absl::memory
+    gmock_main
+)
+endif()
diff --git a/absl/types/any.h b/absl/types/any.h
index a973c6d..f3a3281 100644
--- a/absl/types/any.h
+++ b/absl/types/any.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -58,7 +58,7 @@
 
 #ifdef ABSL_HAVE_STD_ANY
 
-#include <any>
+#include <any>  // IWYU pragma: export
 
 namespace absl {
 using std::any;
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc
index f9dd8c4..5d7d8a5 100644
--- a/absl/types/any_exception_safety_test.cc
+++ b/absl/types/any_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -135,6 +135,7 @@
   EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
   EXPECT_TRUE(strong_empty_any_tester.Test(move));
 }
+
 // libstdc++ std::any fails this test
 #if !defined(ABSL_HAVE_STD_ANY)
 TEST(AnyExceptionSafety, Emplace) {
diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc
index 115e78d..a6351bf 100644
--- a/absl/types/any_test.cc
+++ b/absl/types/any_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc
index 2e2fd29..505919a 100644
--- a/absl/types/bad_any_cast.cc
+++ b/absl/types/bad_any_cast.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
index 6039013..8d020ed 100644
--- a/absl/types/bad_any_cast.h
+++ b/absl/types/bad_any_cast.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc
index 5587077..a791c7c 100644
--- a/absl/types/bad_optional_access.cc
+++ b/absl/types/bad_optional_access.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
index c6c2746..add5c45 100644
--- a/absl/types/bad_optional_access.h
+++ b/absl/types/bad_optional_access.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
index d27d775..a4325c8 100644
--- a/absl/types/bad_variant_access.cc
+++ b/absl/types/bad_variant_access.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
index e7355a5..637db43 100644
--- a/absl/types/bad_variant_access.h
+++ b/absl/types/bad_variant_access.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index eff4fef..5ca66e2 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -1234,23 +1234,29 @@
 // Base that is dependent on whether or not the move-assign can be trivial.
 template <class... T>
 using VariantMoveAssignBase = absl::conditional_t<
-    absl::disjunction<absl::conjunction<absl::is_move_assignable<Union<T...>>,
-                                        std::is_move_constructible<Union<T...>>,
-                                        std::is_destructible<Union<T...>>>,
-                      absl::negation<absl::conjunction<
-                          std::is_move_constructible<T>...,
-                          absl::is_move_assignable<T>...>>>::value,
+    absl::disjunction<
+        absl::conjunction<absl::is_move_assignable<Union<T...>>,
+                          std::is_move_constructible<Union<T...>>,
+                          std::is_destructible<Union<T...>>>,
+        absl::negation<absl::conjunction<std::is_move_constructible<T>...,
+                                         // Note: We're not qualifying this with
+                                         // absl:: because it doesn't compile
+                                         // under MSVC.
+                                         is_move_assignable<T>...>>>::value,
     VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
 
 // Base that is dependent on whether or not the copy-assign can be trivial.
 template <class... T>
 using VariantCopyAssignBase = absl::conditional_t<
-    absl::disjunction<absl::conjunction<absl::is_copy_assignable<Union<T...>>,
-                                        std::is_copy_constructible<Union<T...>>,
-                                        std::is_destructible<Union<T...>>>,
-                      absl::negation<absl::conjunction<
-                          std::is_copy_constructible<T>...,
-                          absl::is_copy_assignable<T>...>>>::value,
+    absl::disjunction<
+        absl::conjunction<absl::is_copy_assignable<Union<T...>>,
+                          std::is_copy_constructible<Union<T...>>,
+                          std::is_destructible<Union<T...>>>,
+        absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
+                                         // Note: We're not qualifying this with
+                                         // absl:: because it doesn't compile
+                                         // under MSVC.
+                                         is_copy_assignable<T>...>>>::value,
     VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
 
 template <class... T>
@@ -1542,8 +1548,8 @@
   variant<Types...>* w;
   template <std::size_t I>
   void operator()(SizeT<I>) const {
-    using std::swap;
-    swap(VariantCoreAccess::Access<I>(*v), VariantCoreAccess::Access<I>(*w));
+    type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
+                               VariantCoreAccess::Access<I>(*w));
   }
 
   void operator()(SizeT<variant_npos>) const {}
@@ -1598,11 +1604,12 @@
 template <typename Variant, typename... Ts>
 struct VariantHashBase<Variant,
                        absl::enable_if_t<absl::conjunction<
-                           type_traits_internal::IsHashEnabled<Ts>...>::value>,
+                           type_traits_internal::IsHashable<Ts>...>::value>,
                        Ts...> {
   using argument_type = Variant;
   using result_type = size_t;
   size_t operator()(const Variant& var) const {
+    type_traits_internal::AssertHashEnabled<Ts...>();
     if (var.valueless_by_exception()) {
       return 239799884;
     }
diff --git a/absl/types/optional.cc b/absl/types/optional.cc
index ef27290..44ff829 100644
--- a/absl/types/optional.cc
+++ b/absl/types/optional.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/optional.h b/absl/types/optional.h
index 1421001..f0ae9a1 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -36,11 +36,12 @@
 #define ABSL_TYPES_OPTIONAL_H_
 
 #include "absl/base/config.h"
+#include "absl/memory/memory.h"
 #include "absl/utility/utility.h"
 
 #ifdef ABSL_HAVE_STD_OPTIONAL
 
-#include <optional>
+#include <optional>  // IWYU pragma: export
 
 namespace absl {
 using std::bad_optional_access;
@@ -60,7 +61,6 @@
 #include <utility>
 
 #include "absl/base/attributes.h"
-#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 #include "absl/types/bad_optional_access.h"
 
@@ -114,10 +114,6 @@
 //      need the inline variable support in C++17 for external linkage.
 //    * Throws `absl::bad_optional_access` instead of
 //      `std::bad_optional_access`.
-//    * `optional::swap()` and `absl::swap()` relies on
-//      `std::is_(nothrow_)swappable()`, which has been introduced in C++17.
-//      As a workaround, we assume `is_swappable()` is always `true`
-//      and `is_nothrow_swappable()` is the same as `std::is_trivial()`.
 //    * `make_optional()` cannot be declared `constexpr` due to the absence of
 //      guaranteed copy elision.
 //    * The move constructor's `noexcept` specification is stronger, i.e. if the
@@ -163,7 +159,7 @@
 // This class stores the data in optional<T>.
 // It is specialized based on whether T is trivially destructible.
 // This is the specialization for non trivially destructible type.
-template <typename T, bool = std::is_trivially_destructible<T>::value>
+template <typename T, bool unused = std::is_trivially_destructible<T>::value>
 class optional_data_dtor_base {
   struct dummy_type {
     static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
@@ -261,10 +257,10 @@
 // have trivial move but nontrivial copy.
 // Also, we should be checking is_trivially_copyable here, which is not
 // supported now, so we use is_trivially_* traits instead.
-template <typename T, bool = absl::is_trivially_copy_constructible<T>::value&&
-                          absl::is_trivially_copy_assignable<
-                              typename std::remove_cv<T>::type>::value&&
-                              std::is_trivially_destructible<T>::value>
+template <typename T,
+          bool unused = absl::is_trivially_copy_constructible<T>::value&&
+              absl::is_trivially_copy_assignable<typename std::remove_cv<
+                  T>::type>::value&& std::is_trivially_destructible<T>::value>
 class optional_data;
 
 // Trivially copyable types
@@ -295,7 +291,7 @@
 
   optional_data() = default;
 
-  optional_data(const optional_data& rhs) {
+  optional_data(const optional_data& rhs) : optional_data_base<T>() {
     if (rhs.engaged_) {
       this->construct(rhs.data_);
     }
@@ -303,7 +299,8 @@
 
   optional_data(optional_data&& rhs) noexcept(
       absl::default_allocator_is_nothrow::value ||
-      std::is_nothrow_move_constructible<T>::value) {
+      std::is_nothrow_move_constructible<T>::value)
+      : optional_data_base<T>() {
     if (rhs.engaged_) {
       this->construct(std::move(rhs.data_));
     }
@@ -403,23 +400,24 @@
 };
 
 template <typename T>
-constexpr copy_traits get_ctor_copy_traits() {
-  return std::is_copy_constructible<T>::value
-             ? copy_traits::copyable
-             : std::is_move_constructible<T>::value ? copy_traits::movable
-                                                    : copy_traits::non_movable;
-}
+struct ctor_copy_traits {
+  static constexpr copy_traits traits =
+      std::is_copy_constructible<T>::value
+          ? copy_traits::copyable
+          : std::is_move_constructible<T>::value ? copy_traits::movable
+                                                 : copy_traits::non_movable;
+};
 
 template <typename T>
-constexpr copy_traits get_assign_copy_traits() {
-  return absl::is_copy_assignable<T>::value &&
-                 std::is_copy_constructible<T>::value
-             ? copy_traits::copyable
-             : absl::is_move_assignable<T>::value &&
-                       std::is_move_constructible<T>::value
-                   ? copy_traits::movable
-                   : copy_traits::non_movable;
-}
+struct assign_copy_traits {
+  static constexpr copy_traits traits =
+      absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
+          ? copy_traits::copyable
+          : absl::is_move_assignable<T>::value &&
+                    std::is_move_constructible<T>::value
+                ? copy_traits::movable
+                : copy_traits::non_movable;
+};
 
 // Whether T is constructible or convertible from optional<U>.
 template <typename T, typename U>
@@ -467,6 +465,7 @@
   using argument_type = absl::optional<T>;
   using result_type = size_t;
   size_t operator()(const absl::optional<T>& opt) const {
+    absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
     if (opt) {
       return std::hash<absl::remove_const_t<T> >()(*opt);
     } else {
@@ -484,9 +483,9 @@
 template <typename T>
 class optional : private optional_internal::optional_data<T>,
                  private optional_internal::optional_ctor_base<
-                     optional_internal::get_ctor_copy_traits<T>()>,
+                     optional_internal::ctor_copy_traits<T>::traits>,
                  private optional_internal::optional_assign_base<
-                     optional_internal::get_assign_copy_traits<T>()> {
+                     optional_internal::assign_copy_traits<T>::traits> {
   using data_base = optional_internal::optional_data<T>;
 
  public:
@@ -511,10 +510,11 @@
   // the arguments `std::forward<Args>(args)...`  within the `optional`.
   // (The `in_place_t` is a tag used to indicate that the contained object
   // should be constructed in-place.)
-  //
-  // TODO(absl-team): Add std::is_constructible<T, Args&&...> SFINAE.
-  template <typename... Args>
-  constexpr explicit optional(in_place_t, Args&&... args)
+  template <typename InPlaceT, typename... Args,
+            absl::enable_if_t<absl::conjunction<
+                std::is_same<InPlaceT, in_place_t>,
+                std::is_constructible<T, Args&&...> >::value>* = nullptr>
+  constexpr explicit optional(InPlaceT, Args&&... args)
       : data_base(in_place_t(), absl::forward<Args>(args)...) {}
 
   // Constructs a non-empty `optional` direct-initialized value of type `T` from
@@ -750,11 +750,10 @@
   // Swap, standard semantics
   void swap(optional& rhs) noexcept(
       std::is_nothrow_move_constructible<T>::value&&
-          std::is_trivial<T>::value) {
+          type_traits_internal::IsNothrowSwappable<T>::value) {
     if (*this) {
       if (rhs) {
-        using std::swap;
-        swap(**this, *rhs);
+        type_traits_internal::Swap(**this, *rhs);
       } else {
         rhs.construct(std::move(**this));
         this->destruct();
@@ -906,12 +905,10 @@
 //
 // Performs a swap between two `absl::optional` objects, using standard
 // semantics.
-//
-// NOTE: we assume `is_swappable()` is always `true`. A compile error will
-// result if this is not the case.
-template <typename T,
-          typename std::enable_if<std::is_move_constructible<T>::value,
-                                  bool>::type = false>
+template <typename T, typename std::enable_if<
+                          std::is_move_constructible<T>::value &&
+                              type_traits_internal::IsSwappable<T>::value,
+                          bool>::type = false>
 void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
   a.swap(b);
 }
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
index d117ee5..aaf8ebc 100644
--- a/absl/types/optional_exception_safety_test.cc
+++ b/absl/types/optional_exception_safety_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index d90db9f..0665488 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -157,6 +157,16 @@
   NonMovable& operator=(NonMovable&&) = delete;
 };
 
+struct NoDefault {
+  NoDefault() = delete;
+  NoDefault(const NoDefault&) {}
+  NoDefault& operator=(const NoDefault&) { return *this; }
+};
+
+struct ConvertsFromInPlaceT {
+  ConvertsFromInPlaceT(absl::in_place_t) {}  // NOLINT
+};
+
 TEST(optionalTest, DefaultConstructor) {
   absl::optional<int> empty;
   EXPECT_FALSE(empty);
@@ -337,16 +347,18 @@
   static_assert((*opt2).x == ConstexprType::kCtorInitializerList, "");
 #endif
 
-  // TODO(absl-team): uncomment these when std::is_constructible<T, Args&&...>
-  // SFINAE is added to optional::optional(absl::in_place_t, Args&&...).
-  // struct I {
-  //   I(absl::in_place_t);
-  // };
+  EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+                                      absl::in_place_t>::value));
+  EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+                                      const absl::in_place_t&>::value));
+  EXPECT_TRUE(
+      (std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+                             absl::in_place_t, absl::in_place_t>::value));
 
-  // EXPECT_FALSE((std::is_constructible<absl::optional<I>,
-  // absl::in_place_t>::value));
-  // EXPECT_FALSE((std::is_constructible<absl::optional<I>, const
-  // absl::in_place_t&>::value));
+  EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+                                      absl::in_place_t>::value));
+  EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+                                      absl::in_place_t&&>::value));
 }
 
 // template<U=T> optional(U&&);
@@ -1042,9 +1054,9 @@
   // test exception throw on value()
   absl::optional<int> empty;
 #ifdef ABSL_HAVE_EXCEPTIONS
-  EXPECT_THROW(empty.value(), absl::bad_optional_access);
+  EXPECT_THROW((void)empty.value(), absl::bad_optional_access);
 #else
-  EXPECT_DEATH(empty.value(), "Bad optional access");
+  EXPECT_DEATH((void)empty.value(), "Bad optional access");
 #endif
 
   // test constexpr value()
@@ -1476,8 +1488,8 @@
 
 TEST(optionalTest, ValueType) {
   EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value));
-  EXPECT_TRUE(
-      (std::is_same<absl::optional<std::string>::value_type, std::string>::value));
+  EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type,
+                            std::string>::value));
   EXPECT_FALSE(
       (std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value));
 }
@@ -1504,18 +1516,19 @@
 
   static_assert(is_hash_enabled_for<absl::optional<int>>::value, "");
   static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, "");
+  static_assert(
+      absl::type_traits_internal::IsHashable<absl::optional<int>>::value, "");
+  static_assert(
+      absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value,
+      "");
+  absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>();
+  absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>();
 
-#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
-                          _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
-  // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
-  // static_assert to catch any user-defined type that doesn't provide a hash
-  // specialization. So instantiating std::hash<absl::optional<T>> will result
-  // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
   static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, "");
+  static_assert(!absl::type_traits_internal::IsHashable<
+                    absl::optional<NonHashable>>::value,
+                "");
 #endif
 
   // libstdc++ std::optional is missing remove_const_t, i.e. it's using
@@ -1623,4 +1636,29 @@
   EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
 }
 
+#if !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION)
+struct NestedClassBug {
+  struct Inner {
+    bool dummy = false;
+  };
+  absl::optional<Inner> value;
+};
+
+TEST(optionalTest, InPlaceTSFINAEBug) {
+  NestedClassBug b;
+  ((void)b);
+  using Inner = NestedClassBug::Inner;
+
+  EXPECT_TRUE((std::is_default_constructible<Inner>::value));
+  EXPECT_TRUE((std::is_constructible<Inner>::value));
+  EXPECT_TRUE(
+      (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value));
+
+  absl::optional<Inner> o(absl::in_place);
+  EXPECT_TRUE(o.has_value());
+  o.emplace();
+  EXPECT_TRUE(o.has_value());
+}
+#endif  // !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION)
+
 }  // namespace
diff --git a/absl/types/span.h b/absl/types/span.h
index 911af0c..d7f48d9 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -5,7 +5,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -87,7 +87,7 @@
   return c.data();
 }
 
-// Before C++17, string::data returns a const char* in all cases.
+// Before C++17, std::string::data returns a const char* in all cases.
 inline char* GetDataImpl(std::string& s,  // NOLINT(runtime/references)
                          int) noexcept {
   return &s[0];
@@ -485,6 +485,40 @@
                : (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
   }
 
+  // Span::first()
+  //
+  // Returns a `Span` containing first `len` elements. Parameter `len` is of
+  // type `size_type` and thus non-negative. `len` value must be <= size().
+  //
+  // Examples:
+  //
+  //   std::vector<int> vec = {10, 11, 12, 13};
+  //   absl::MakeSpan(vec).first(1);  // {10}
+  //   absl::MakeSpan(vec).first(3);  // {10, 11, 12}
+  //   absl::MakeSpan(vec).first(5);  // throws std::out_of_range
+  constexpr Span first(size_type len) const {
+    return (len <= size())
+               ? Span(data(), len)
+               : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+  }
+
+  // Span::last()
+  //
+  // Returns a `Span` containing last `len` elements. Parameter `len` is of
+  // type `size_type` and thus non-negative. `len` value must be <= size().
+  //
+  // Examples:
+  //
+  //   std::vector<int> vec = {10, 11, 12, 13};
+  //   absl::MakeSpan(vec).last(1);  // {13}
+  //   absl::MakeSpan(vec).last(3);  // {11, 12, 13}
+  //   absl::MakeSpan(vec).last(5);  // throws std::out_of_range
+  constexpr Span last(size_type len) const {
+    return (len <= size())
+               ? Span(size() - len + data(), len)
+               : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+  }
+
   // Support for absl::Hash.
   template <typename H>
   friend H AbslHashValue(H h, Span v) {
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index bd739ff..9269f91 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -139,8 +139,10 @@
   EXPECT_THAT(s_const_abc, SpanIs(abc));
 
   EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value));
-  EXPECT_FALSE((std::is_constructible<absl::Span<const int>, std::string>::value));
-  EXPECT_TRUE((std::is_convertible<std::string, absl::Span<const char>>::value));
+  EXPECT_FALSE(
+      (std::is_constructible<absl::Span<const int>, std::string>::value));
+  EXPECT_TRUE(
+      (std::is_convertible<std::string, absl::Span<const char>>::value));
 }
 
 TEST(IntSpan, FromConstPointer) {
@@ -293,6 +295,38 @@
 #endif
 }
 
+TEST(IntSpan, First) {
+  std::vector<int> empty;
+  EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty));
+
+  auto ramp = MakeRamp(10);
+  EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0));
+  EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp));
+  EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+  EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range);
+#else
+  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), "");
+#endif
+}
+
+TEST(IntSpan, Last) {
+  std::vector<int> empty;
+  EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty));
+
+  auto ramp = MakeRamp(10);
+  EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0));
+  EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp));
+  EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+  EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range);
+#else
+  EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), "");
+#endif
+}
+
 TEST(IntSpan, MakeSpanPtrLength) {
   std::vector<int> empty;
   auto s_empty = absl::MakeSpan(empty.data(), empty.size());
@@ -767,6 +801,8 @@
   ABSL_TEST_CONSTEXPR(span.begin());
   ABSL_TEST_CONSTEXPR(span.cbegin());
   ABSL_TEST_CONSTEXPR(span.subspan(0, 0));
+  ABSL_TEST_CONSTEXPR(span.first(1));
+  ABSL_TEST_CONSTEXPR(span.last(1));
   ABSL_TEST_CONSTEXPR(span[0]);
 }
 
@@ -779,4 +815,19 @@
   EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*));
 }
 
+TEST(Span, Hash) {
+  int array[] = {1, 2, 3, 4};
+  int array2[] = {1, 2, 3};
+  using T = absl::Span<const int>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      {// Empties
+       T(), T(nullptr, 0), T(array, 0), T(array2, 0),
+       // Different array with same value
+       T(array, 3), T(array2), T({1, 2, 3}),
+       // Same array, but different length
+       T(array, 1), T(array, 2),
+       // Same length, but different array
+       T(array + 1, 2), T(array + 2, 2)}));
+}
+
 }  // namespace
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 2f78722..ebd52d2 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -47,7 +47,7 @@
 
 #ifdef ABSL_HAVE_STD_VARIANT
 
-#include <variant>
+#include <variant>  // IWYU pragma: export
 
 namespace absl {
 using std::bad_variant_access;
@@ -82,7 +82,7 @@
 // absl::variant
 // -----------------------------------------------------------------------------
 //
-// An 'absl::variant` type is a form of type-safe union. An `absl::variant` --
+// An `absl::variant` type is a form of type-safe union. An `absl::variant` --
 // except in exceptional cases -- always holds a value of one of its alternative
 // types.
 //
@@ -129,14 +129,19 @@
 // type (in which case, they will be swapped) or to two different types (in
 // which case the values will need to be moved).
 //
-template <typename... Ts>
+template <
+    typename... Ts,
+    absl::enable_if_t<
+        absl::conjunction<std::is_move_constructible<Ts>...,
+                          type_traits_internal::IsSwappable<Ts>...>::value,
+        int> = 0>
 void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
   v.swap(w);
 }
 
 // variant_size
 //
-// Returns the number of alterative types available for a given `absl::variant`
+// Returns the number of alternative types available for a given `absl::variant`
 // type as a compile-time constant expression. As this is a class template, it
 // is not generally useful for accessing the number of alternative types of
 // any given `absl::variant` instance.
@@ -399,9 +404,9 @@
 // Calls a provided functor on a given set of variants. `absl::visit()` is
 // commonly used to conditionally inspect the state of a given variant (or set
 // of variants).
-// Requires: The expression in the Effects: element shall be a valid expression
-// of the same type and value category, for all combinations of alternative
-// types of all variants. Otherwise, the program is ill-formed.
+//
+// The functor must return the same type when called with any of the variants'
+// alternatives.
 //
 // Example:
 //
@@ -414,6 +419,7 @@
 //   };
 //
 //   // Declare our variant, and call `absl::visit()` on it.
+//   // Note that `GetVariant()` returns void in either case.
 //   absl::variant<int, std::string> foo = std::string("foo");
 //   GetVariant visitor;
 //   absl::visit(visitor, foo);  // Prints `The variant's value is: foo'
@@ -453,7 +459,7 @@
                                   std::is_object<Tn>...>::value,
                 "Attempted to instantiate a variant containing a non-object "
                 "type.");
-  // Intentionally not qualifing `negation` with `absl::` to work around a bug
+  // Intentionally not qualifying `negation` with `absl::` to work around a bug
   // in MSVC 2015 with inline namespace and variadic template.
   static_assert(absl::conjunction<negation<std::is_array<T0> >,
                                   negation<std::is_array<Tn> >...>::value,
@@ -561,7 +567,7 @@
 
   // Assignment Operators
 
-  // Copy assignement operator
+  // Copy assignment operator
   variant& operator=(const variant& other) = default;
 
   // Move assignment operator
@@ -687,12 +693,12 @@
   //
   // Swaps the values of two variant objects.
   //
-  // TODO(calabrese)
-  //   `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
-  //   which is introduced in C++17. So we assume `is_swappable()` is always
-  //   true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
   void swap(variant& rhs) noexcept(
-      absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
+      absl::conjunction<
+          std::is_nothrow_move_constructible<T0>,
+          std::is_nothrow_move_constructible<Tn>...,
+          type_traits_internal::IsNothrowSwappable<T0>,
+          type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
     return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
         variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
   }
diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc
index 99658ac..a5f5216 100644
--- a/absl/types/variant_benchmark.cc
+++ b/absl/types/variant_benchmark.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc
index 58436f0..76beb59 100644
--- a/absl/types/variant_exception_safety_test.cc
+++ b/absl/types/variant_exception_safety_test.cc
@@ -4,13 +4,14 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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/types/variant.h"
 
 #include <iostream>
@@ -20,9 +21,13 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/exception_safety_testing.h"
 #include "absl/memory/memory.h"
 
+// See comment in absl/base/config.h
+#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
+
 namespace absl {
 namespace {
 
@@ -311,6 +316,12 @@
     EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
   }
   {
+    // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06.
+    // The fix is targeted for gcc-9.
+    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
+    // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
+#if !(defined(ABSL_HAVE_STD_VARIANT) && \
+      defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
     // - otherwise (index() != j), equivalent to
     // emplace<j>(get<j>(std::move(rhs)))
     // - If an exception is thrown during the call to Tj's move construction
@@ -326,6 +337,8 @@
                       auto copy = rhs;
                       *lhs = std::move(copy);
                     }));
+#endif  // !(defined(ABSL_HAVE_STD_VARIANT) &&
+        //   defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
   }
 }
 
@@ -506,3 +519,5 @@
 
 }  // namespace
 }  // namespace absl
+
+#endif  // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index bfb8bd7..ab40ed2 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -52,7 +52,7 @@
 #endif  // ABSL_HAVE_EXCEPTIONS
 
 #define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...)                 \
-  ABSL_VARIANT_TEST_EXPECT_FAIL((__VA_ARGS__), absl::bad_variant_access, \
+  ABSL_VARIANT_TEST_EXPECT_FAIL((void)(__VA_ARGS__), absl::bad_variant_access, \
                                 "Bad variant access")
 
 struct Hashable {};
@@ -257,7 +257,7 @@
 // each type.
 template <typename T>
 class VariantTypesTest : public ::testing::Test {};
-TYPED_TEST_CASE(VariantTypesTest, VariantTypes);
+TYPED_TEST_SUITE(VariantTypesTest, VariantTypes);
 
 ////////////////////
 // [variant.ctor] //
@@ -484,7 +484,8 @@
 }
 
 TEST(VariantTest, InPlaceTypeInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6);
   ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -519,7 +520,8 @@
 }
 
 TEST(VariantTest, InPlaceIndexInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6);
   ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -560,8 +562,14 @@
 
 #ifdef ABSL_HAVE_EXCEPTIONS
 
+// See comment in absl/base/config.h
+#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
+TEST(VariantTest, DISABLED_TestDtorValuelessByException)
+#else
 // Test destruction when in the valueless_by_exception state.
-TEST(VariantTest, TestDtorValuelessByException) {
+TEST(VariantTest, TestDtorValuelessByException)
+#endif
+{
   int counter = 0;
   IncrementInDtor counter_adjuster(&counter);
 
@@ -826,7 +834,8 @@
 }
 
 TEST(VariantTest, TestEmplaceInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(absl::in_place_index_t<0>{}, 555);
   MoveOnlyWithListConstructor& emplace_result =
@@ -863,7 +872,8 @@
 }
 
 TEST(VariantTest, TestEmplaceIndexInitializerList) {
-  using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+  using Var =
+      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
 
   Var v1(absl::in_place_index_t<0>{}, 555);
   MoveOnlyWithListConstructor& emplace_result =
@@ -1301,7 +1311,8 @@
         absl::get<std::string>(std::move(v)));
 
     const Var& const_v = v;
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(const_v));
+    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+        absl::get<std::string>(const_v));
     ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
         absl::get<std::string>(std::move(const_v)));  // NOLINT
   }
@@ -1358,7 +1369,8 @@
       EXPECT_EQ(*elem, 0);
       {
         auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_TRUE(
+            (std::is_same<decltype(bad_elem), const std::string*>::value));
         EXPECT_EQ(bad_elem, nullptr);
       }
       {
@@ -1467,7 +1479,8 @@
       }
       {
         auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_TRUE(
+            (std::is_same<decltype(bad_elem), const std::string*>::value));
         EXPECT_EQ(bad_elem, nullptr);
       }
       {
@@ -1520,7 +1533,8 @@
       }
       {
         auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+        EXPECT_TRUE(
+            (std::is_same<decltype(bad_elem), const std::string*>::value));
         EXPECT_EQ(bad_elem, nullptr);
       }
       {
@@ -1723,9 +1737,13 @@
     bool operator()(std::string&&) const { return true; }  // NOLINT
 
     int operator()(const std::string&, const std::string&) const { return 0; }
-    int operator()(const std::string&, std::string&&) const { return 1; }  // NOLINT
-    int operator()(std::string&&, const std::string&) const { return 2; }  // NOLINT
-    int operator()(std::string&&, std::string&&) const { return 3; }       // NOLINT
+    int operator()(const std::string&, std::string&&) const {
+      return 1;
+    }  // NOLINT
+    int operator()(std::string&&, const std::string&) const {
+      return 2;
+    }                                                                 // NOLINT
+    int operator()(std::string&&, std::string&&) const { return 3; }  // NOLINT
   };
   EXPECT_FALSE(absl::visit(Visitor{}, v));
   EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v)));
@@ -1801,9 +1819,9 @@
   EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
                           B(std::unique_ptr<int>(new int(7)))),
               ::testing::Pair(5, 7));
-  EXPECT_THAT(
-      absl::visit(Visitor(), A(std::string("BBBBB")), B(absl::string_view("ABC"))),
-      ::testing::Pair(5, 3));
+  EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
+                          B(absl::string_view("ABC"))),
+              ::testing::Pair(5, 3));
 }
 
 TEST(VariantTest, VisitNoArgs) {
@@ -1972,29 +1990,17 @@
 }
 
 TEST(VariantTest, Hash) {
-  static_assert(type_traits_internal::IsHashEnabled<variant<int>>::value, "");
-  static_assert(type_traits_internal::IsHashEnabled<variant<Hashable>>::value,
+  static_assert(type_traits_internal::IsHashable<variant<int>>::value, "");
+  static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, "");
+  static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value,
+                "");
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+  static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value,
                 "");
   static_assert(
-      type_traits_internal::IsHashEnabled<variant<int, Hashable>>::value, "");
-
-#if defined(_MSC_VER) ||                                   \
-    (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 4000 && \
-     _LIBCPP_STD_VER > 11) ||                              \
-    defined(__APPLE__)
-  // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
-  // static_assert to catch any user-defined type T that doesn't provide a hash
-  // specialization. So instantiating std::hash<variant<T>> will result
-  // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
-  static_assert(
-      !type_traits_internal::IsHashEnabled<variant<NonHashable>>::value, "");
-  static_assert(!type_traits_internal::IsHashEnabled<
-                    variant<Hashable, NonHashable>>::value,
-                "");
+      !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value,
+      "");
 #endif
 
 // MSVC std::hash<std::variant> does not use the index, thus produce the same
@@ -2018,11 +2024,10 @@
     EXPECT_GT(hashcodes.size(), 90);
 
     // test const-qualified
+    static_assert(type_traits_internal::IsHashable<variant<const int>>::value,
+                  "");
     static_assert(
-        type_traits_internal::IsHashEnabled<variant<const int>>::value, "");
-    static_assert(
-        type_traits_internal::IsHashEnabled<variant<const Hashable>>::value,
-        "");
+        type_traits_internal::IsHashable<variant<const Hashable>>::value, "");
     std::hash<absl::variant<const int>> c_hash;
     for (int i = 0; i < 100; ++i) {
       EXPECT_EQ(hash(i), c_hash(i));
@@ -2171,7 +2176,8 @@
 
   // We still need the explicit cast for std::string, because C++ won't apply
   // two user-defined implicit conversions in a row.
-  EXPECT_TRUE(absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
+  EXPECT_TRUE(
+      absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
 }
 
 struct Convertible2;
@@ -2195,7 +2201,8 @@
 
 TEST(VariantTest, TestRvalueConversion) {
   variant<double, std::string> var(
-      ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(0)));
+      ConvertVariantTo<variant<double, std::string>>(
+          variant<std::string, int>(0)));
   ASSERT_TRUE(absl::holds_alternative<double>(var));
   EXPECT_EQ(0.0, absl::get<double>(var));
 
@@ -2287,7 +2294,8 @@
 TEST(VariantTest, TestMoveConversion) {
   using Variant =
       variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
-  using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+  using OtherVariant =
+      variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
 
   Variant var(
       ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)}));
@@ -2295,8 +2303,8 @@
   ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);
   EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));
 
-  var =
-      ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+  var = ConvertVariantTo<Variant>(
+      OtherVariant(absl::make_unique<std::string>("foo")));
   ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));
   EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var));
 }
@@ -2307,7 +2315,8 @@
   // whether moving or copying has occurred.
   using Variant =
       variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>;
-  using OtherVariant = variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
+  using OtherVariant =
+      variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
 
   Variant v1(std::make_shared<const int>(0));
 
@@ -2336,7 +2345,8 @@
 
 TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
   variant<double, std::string> var(
-      ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(3)));
+      ConvertVariantTo<variant<double, std::string>>(
+          variant<std::string, int>(3)));
   EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0));
 
   var = ConvertVariantTo<variant<double, std::string>>(
@@ -2378,7 +2388,8 @@
 
   variant<const char*, float> source2 = "foo";
   destination = ConvertVariantTo<variant<double, std::string>>(source2);
-  EXPECT_THAT(absl::get_if<std::string>(&destination), Pointee(std::string("foo")));
+  EXPECT_THAT(absl::get_if<std::string>(&destination),
+              Pointee(std::string("foo")));
 
   variant<int, float> source3(42);
   variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
@@ -2415,15 +2426,16 @@
 TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
   using Variant =
       variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
-  using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+  using OtherVariant =
+      variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
 
   Variant var(
       ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)}));
   EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),
               Pointee(Pointee(3)));
 
-  var =
-      ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+  var = ConvertVariantTo<Variant>(
+      OtherVariant(absl::make_unique<std::string>("foo")));
   EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),
               Pointee(Pointee(std::string("foo"))));
 }
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index c01b49b..5185ccd 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -1,5 +1,5 @@
 load(
-    "//absl:copts.bzl",
+    "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_TEST_COPTS",
 )
diff --git a/absl/utility/CMakeLists.txt b/absl/utility/CMakeLists.txt
index dc3a631..e1edd19 100644
--- a/absl/utility/CMakeLists.txt
+++ b/absl/utility/CMakeLists.txt
@@ -5,7 +5,7 @@
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
-#      http://www.apache.org/licenses/LICENSE-2.0
+#      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,
@@ -14,39 +14,31 @@
 # limitations under the License.
 #
 
-
-list(APPEND UTILITY_PUBLIC_HEADERS
-  "utility.h"
-)
-
-absl_header_library(
-  TARGET
-    absl_utility
-  PUBLIC_LIBRARIES
-    absl::base
-  EXPORT_NAME
+absl_cc_library(
+  NAME
     utility
+  HDRS
+    "utility.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base_internal
+    absl::config
+    absl::type_traits
+  PUBLIC
 )
 
-
-#
-## TESTS
-#
-
-# test utility_test
-set(UTILITY_TEST_SRC "utility_test.cc")
-set(UTILITY_TEST_PUBLIC_LIBRARIES
-  absl::base
-  absl::memory
-  absl::strings
-  absl::utility
-)
-
-absl_test(
-  TARGET
+absl_cc_test(
+  NAME
     utility_test
-  SOURCES
-    ${UTILITY_TEST_SRC}
-  PUBLIC_LIBRARIES
-    ${UTILITY_TEST_PUBLIC_LIBRARIES}
+  SRCS
+    "utility_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::utility
+    absl::core_headers
+    absl::memory
+    absl::strings
+    gmock_main
 )
diff --git a/absl/utility/utility.h b/absl/utility/utility.h
index aef4baa..853c1fb 100644
--- a/absl/utility/utility.h
+++ b/absl/utility/utility.h
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -32,10 +32,9 @@
 //
 // References:
 //
-//  http://en.cppreference.com/w/cpp/utility/integer_sequence
-//  http://en.cppreference.com/w/cpp/utility/apply
+//  https://en.cppreference.com/w/cpp/utility/integer_sequence
+//  https://en.cppreference.com/w/cpp/utility/apply
 //  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
-//
 
 #ifndef ABSL_UTILITY_UTILITY_H_
 #define ABSL_UTILITY_UTILITY_H_
@@ -234,25 +233,33 @@
 //
 // Example:
 //
-//   class Foo{void Bar(int);};
-//   void user_function(int, string);
-//   void user_function(std::unique_ptr<Foo>);
+//   class Foo {
+//    public:
+//     void Bar(int);
+//   };
+//   void user_function1(int, std::string);
+//   void user_function2(std::unique_ptr<Foo>);
+//   auto user_lambda = [](int, int) {};
 //
 //   int main()
 //   {
-//       std::tuple<int, string> tuple1(42, "bar");
-//       // Invokes the user function overload on int, string.
-//       absl::apply(&user_function, tuple1);
+//       std::tuple<int, std::string> tuple1(42, "bar");
+//       // Invokes the first user function on int, std::string.
+//       absl::apply(&user_function1, tuple1);
 //
-//       auto foo = absl::make_unique<Foo>();
-//       std::tuple<Foo*, int> tuple2(foo.get(), 42);
-//       // Invokes the method Bar on foo with one argument 42.
-//       absl::apply(&Foo::Bar, foo.get(), 42);
-//
-//       std::tuple<std::unique_ptr<Foo>> tuple3(absl::make_unique<Foo>());
+//       std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
 //       // Invokes the user function that takes ownership of the unique
 //       // pointer.
-//       absl::apply(&user_function, std::move(tuple));
+//       absl::apply(&user_function2, std::move(tuple2));
+//
+//       auto foo = absl::make_unique<Foo>();
+//       std::tuple<Foo*, int> tuple3(foo.get(), 42);
+//       // Invokes the method Bar on foo with one argument, 42.
+//       absl::apply(&Foo::Bar, tuple3);
+//
+//       std::tuple<int, int> tuple4(8, 9);
+//       // Invokes a lambda.
+//       absl::apply(user_lambda, tuple4);
 //   }
 template <typename Functor, typename Tuple>
 auto apply(Functor&& functor, Tuple&& t)
diff --git a/absl/utility/utility_test.cc b/absl/utility/utility_test.cc
index 3c447b2..5a4972b 100644
--- a/absl/utility/utility_test.cc
+++ b/absl/utility/utility_test.cc
@@ -4,7 +4,7 @@
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//      http://www.apache.org/licenses/LICENSE-2.0
+//      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,
@@ -135,7 +135,7 @@
 
 template <typename Tup, size_t... Is>
 std::vector<std::string> TupStringVecImpl(const Tup& tup,
-                                     absl::index_sequence<Is...>) {
+                                          absl::index_sequence<Is...>) {
   return {Fmt(std::get<Is>(tup))...};
 }
 
diff --git a/api/array_view.h b/api/array_view.h
index efc642d..bf91484 100644
--- a/api/array_view.h
+++ b/api/array_view.h
@@ -231,6 +231,12 @@
                               HasDataAndSize<U, T>::value>::type* = nullptr>
   ArrayView(U& u)  // NOLINT
       : ArrayView(u.data(), u.size()) {}
+  template <
+      typename U,
+      typename std::enable_if<Size == impl::kArrayViewVarSize &&
+                              HasDataAndSize<U, T>::value>::type* = nullptr>
+  ArrayView(const U& u)  // NOLINT(runtime/explicit)
+      : ArrayView(u.data(), u.size()) {}
 
   // Indexing and iteration. These allow mutation even if the ArrayView is
   // const, because the ArrayView doesn't own the array. (To prevent mutation,
diff --git a/api/array_view_unittest.cc b/api/array_view_unittest.cc
index 694ed0b..62b51c0 100644
--- a/api/array_view_unittest.cc
+++ b/api/array_view_unittest.cc
@@ -28,16 +28,21 @@
 using ::testing::IsEmpty;
 
 template <typename T>
-void Call(ArrayView<T>) {}
+size_t Call(ArrayView<T> av) {
+  return av.size();
+}
+
+template <typename T, size_t N>
+void CallFixed(ArrayView<T, N> av) {}
 
 }  // namespace
 
 TEST(ArrayViewTest, TestConstructFromPtrAndArray) {
   char arr[] = "Arrr!";
   const char carr[] = "Carrr!";
-  Call<const char>(arr);
-  Call<const char>(carr);
-  Call<char>(arr);
+  EXPECT_EQ(6u, Call<const char>(arr));
+  EXPECT_EQ(7u, Call<const char>(carr));
+  EXPECT_EQ(6u, Call<char>(arr));
   // Call<char>(carr);  // Compile error, because can't drop const.
   // Call<int>(arr);  // Compile error, because incompatible types.
   ArrayView<int*> x;
@@ -182,6 +187,8 @@
 }
 
 TEST(ArrayViewTest, TestStdArray) {
+  EXPECT_EQ(4u, Call<const int>(std::array<int, 4>{1, 2, 3, 4}));
+  CallFixed<const int, 3>(std::array<int, 3>{2, 3, 4});
   constexpr size_t size = 5;
   std::array<float, size> arr{};
   // Fixed size view.
@@ -214,11 +221,12 @@
 }
 
 TEST(ArrayViewTest, TestStdVector) {
+  EXPECT_EQ(3u, Call<const int>(std::vector<int>{4, 5, 6}));
   std::vector<int> v;
   v.push_back(3);
   v.push_back(11);
-  Call<const int>(v);
-  Call<int>(v);
+  EXPECT_EQ(2u, Call<const int>(v));
+  EXPECT_EQ(2u, Call<int>(v));
   // Call<unsigned int>(v);  // Compile error, because incompatible types.
   ArrayView<int> x = v;
   EXPECT_EQ(2u, x.size());
@@ -229,7 +237,7 @@
   EXPECT_EQ(v.data(), y.data());
   // ArrayView<double> d = v;  // Compile error, because incompatible types.
   const std::vector<int> cv;
-  Call<const int>(cv);
+  EXPECT_EQ(0u, Call<const int>(cv));
   // Call<int>(cv);  // Compile error, because can't drop const.
   ArrayView<const int> z = cv;
   EXPECT_EQ(0u, z.size());
@@ -239,8 +247,8 @@
 
 TEST(ArrayViewTest, TestRtcBuffer) {
   rtc::Buffer b = "so buffer";
-  Call<const uint8_t>(b);
-  Call<uint8_t>(b);
+  EXPECT_EQ(10u, Call<const uint8_t>(b));
+  EXPECT_EQ(10u, Call<uint8_t>(b));
   // Call<int8_t>(b);  // Compile error, because incompatible types.
   ArrayView<uint8_t> x = b;
   EXPECT_EQ(10u, x.size());
@@ -251,7 +259,7 @@
   EXPECT_EQ(b.data(), y.data());
   // ArrayView<char> d = b;  // Compile error, because incompatible types.
   const rtc::Buffer cb = "very const";
-  Call<const uint8_t>(cb);
+  EXPECT_EQ(11u, Call<const uint8_t>(cb));
   // Call<uint8_t>(cb);  // Compile error, because can't drop const.
   ArrayView<const uint8_t> z = cb;
   EXPECT_EQ(11u, z.size());
diff --git a/api/async_resolver_factory.h b/api/async_resolver_factory.h
new file mode 100644
index 0000000..93d3f79
--- /dev/null
+++ b/api/async_resolver_factory.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 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_ASYNC_RESOLVER_FACTORY_H_
+#define API_ASYNC_RESOLVER_FACTORY_H_
+
+#include "rtc_base/async_resolver_interface.h"
+
+namespace webrtc {
+
+// An abstract factory for creating AsyncResolverInterfaces. This allows
+// client applications to provide WebRTC with their own mechanism for
+// performing DNS resolution.
+class AsyncResolverFactory {
+ public:
+  AsyncResolverFactory() = default;
+  virtual ~AsyncResolverFactory() = default;
+
+  // The caller should call Destroy on the returned object to delete it.
+  virtual rtc::AsyncResolverInterface* Create() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_ASYNC_RESOLVER_FACTORY_H_
diff --git a/api/audio/audio_frame.cc b/api/audio/audio_frame.cc
index 75d30b0..1e706b9 100644
--- a/api/audio/audio_frame.cc
+++ b/api/audio/audio_frame.cc
@@ -13,7 +13,7 @@
 #include <string.h>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
diff --git a/api/audio/audio_frame.h b/api/audio/audio_frame.h
index dd6ac02..8f1dc62 100644
--- a/api/audio/audio_frame.h
+++ b/api/audio/audio_frame.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/api/audio/audio_mixer.h b/api/audio/audio_mixer.h
index 14eefc1..b290cfa 100644
--- a/api/audio/audio_mixer.h
+++ b/api/audio/audio_mixer.h
@@ -14,7 +14,7 @@
 #include <memory>
 
 #include "api/audio/audio_frame.h"
-#include "rtc_base/refcount.h"
+#include "rtc_base/ref_count.h"
 
 namespace webrtc {
 
diff --git a/api/audio/echo_canceller3_config.cc b/api/audio/echo_canceller3_config.cc
index 3eb2a8d..a560c9e 100644
--- a/api/audio/echo_canceller3_config.cc
+++ b/api/audio/echo_canceller3_config.cc
@@ -87,19 +87,11 @@
     c->delay.down_sampling_factor = 4;
     res = false;
   }
-  if (c->delay.delay_headroom_blocks <= 1 &&
-      c->delay.hysteresis_limit_1_blocks == 1) {
-    c->delay.hysteresis_limit_1_blocks = 0;
-    res = false;
-  }
+
   res = res & Limit(&c->delay.default_delay, 0, 5000);
   res = res & Limit(&c->delay.num_filters, 0, 5000);
-  res = res & Limit(&c->delay.api_call_jitter_blocks, 1, 5000);
-  res = res & Limit(&c->delay.min_echo_path_delay_blocks, 0, 5000);
-  res = res & Limit(&c->delay.delay_headroom_blocks, 0, 5000);
-  res = res & Limit(&c->delay.hysteresis_limit_1_blocks, 0, 5000);
-  res = res & Limit(&c->delay.hysteresis_limit_2_blocks, 0, 5000);
-  res = res & Limit(&c->delay.skew_hysteresis_blocks, 0, 5000);
+  res = res & Limit(&c->delay.delay_headroom_samples, 0, 5000);
+  res = res & Limit(&c->delay.hysteresis_limit_blocks, 0, 5000);
   res = res & Limit(&c->delay.fixed_capture_delay_samples, 0, 5000);
   res = res & Limit(&c->delay.delay_estimate_smoothing, 0.f, 1.f);
   res = res & Limit(&c->delay.delay_candidate_detection_threshold, 0.f, 1.f);
@@ -150,9 +142,7 @@
   }
   res = res & Limit(&c->erle.num_sections, 1, c->filter.main.length_blocks);
 
-  res = res & Limit(&c->ep_strength.lf, 0.f, 1000000.f);
-  res = res & Limit(&c->ep_strength.mf, 0.f, 1000000.f);
-  res = res & Limit(&c->ep_strength.hf, 0.f, 1000000.f);
+  res = res & Limit(&c->ep_strength.default_gain, 0.f, 1000000.f);
   res = res & Limit(&c->ep_strength.default_len, -1.f, 1.f);
 
   res =
@@ -174,15 +164,6 @@
   res = res & Limit(&c->render_levels.poor_excitation_render_limit_ds8, 0.f,
                     32768.f * 32768.f);
 
-  res =
-      res & Limit(&c->echo_removal_control.gain_rampup.initial_gain, 0.f, 1.f);
-  res = res & Limit(&c->echo_removal_control.gain_rampup.first_non_zero_gain,
-                    0.f, 1.f);
-  res = res & Limit(&c->echo_removal_control.gain_rampup.non_zero_gain_blocks,
-                    0, 100000);
-  res = res &
-        Limit(&c->echo_removal_control.gain_rampup.full_gain_blocks, 0, 100000);
-
   res = res & Limit(&c->echo_model.noise_floor_hold, 0, 1000);
   res = res & Limit(&c->echo_model.min_noise_floor_power, 0, 2000000.f);
   res = res & Limit(&c->echo_model.stationary_gate_slope, 0, 1000000.f);
@@ -244,12 +225,6 @@
 
   res = res & Limit(&c->suppressor.floor_first_increase, 0.f, 1000000.f);
 
-  if (c->delay.delay_headroom_blocks >
-      c->filter.main_initial.length_blocks - 1) {
-    c->delay.delay_headroom_blocks = c->filter.main_initial.length_blocks - 1;
-    res = false;
-  }
-
   return res;
 }
 }  // namespace webrtc
diff --git a/api/audio/echo_canceller3_config.h b/api/audio/echo_canceller3_config.h
index ffe17f2..7dcc7dd 100644
--- a/api/audio/echo_canceller3_config.h
+++ b/api/audio/echo_canceller3_config.h
@@ -27,7 +27,6 @@
   EchoCanceller3Config(const EchoCanceller3Config& e);
 
   struct Buffering {
-    bool use_new_render_buffering = true;
     size_t excess_render_detection_interval_blocks = 250;
     size_t max_allowed_excess_render_blocks = 8;
   } buffering;
@@ -38,12 +37,8 @@
     size_t default_delay = 5;
     size_t down_sampling_factor = 4;
     size_t num_filters = 5;
-    size_t api_call_jitter_blocks = 26;
-    size_t min_echo_path_delay_blocks = 0;
-    size_t delay_headroom_blocks = 2;
-    size_t hysteresis_limit_1_blocks = 1;
-    size_t hysteresis_limit_2_blocks = 1;
-    size_t skew_hysteresis_blocks = 3;
+    size_t delay_headroom_samples = 32;
+    size_t hysteresis_limit_blocks = 1;
     size_t fixed_capture_delay_samples = 0;
     float delay_estimate_smoothing = 0.7f;
     float delay_candidate_detection_threshold = 0.2f;
@@ -91,9 +86,7 @@
   } erle;
 
   struct EpStrength {
-    float lf = 1.f;
-    float mf = 1.f;
-    float hf = 1.f;
+    float default_gain = 1.f;
     float default_len = 0.83f;
     bool reverb_based_on_render = true;
     bool echo_can_saturate = true;
@@ -118,12 +111,6 @@
   } render_levels;
 
   struct EchoRemovalControl {
-    struct GainRampup {
-      float initial_gain = 0.0f;
-      float first_non_zero_gain = 0.001f;
-      int non_zero_gain_blocks = 187;
-      int full_gain_blocks = 312;
-    } gain_rampup;
     bool has_clock_drift = false;
     bool linear_and_stable_echo_path = false;
   } echo_removal_control;
diff --git a/api/audio/echo_canceller3_config_json.cc b/api/audio/echo_canceller3_config_json.cc
index 01a831c..4c8c8ab 100644
--- a/api/audio/echo_canceller3_config_json.cc
+++ b/api/audio/echo_canceller3_config_json.cc
@@ -9,9 +9,11 @@
  */
 #include "api/audio/echo_canceller3_config_json.h"
 
+#include <stddef.h>
 #include <string>
 #include <vector>
 
+#include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/json.h"
 #include "rtc_base/strings/string_builder.h"
@@ -136,8 +138,6 @@
 
   Json::Value section;
   if (rtc::GetValueFromJsonObject(root, "buffering", &section)) {
-    ReadParam(section, "use_new_render_buffering",
-              &cfg.buffering.use_new_render_buffering);
     ReadParam(section, "excess_render_detection_interval_blocks",
               &cfg.buffering.excess_render_detection_interval_blocks);
     ReadParam(section, "max_allowed_excess_render_blocks",
@@ -148,18 +148,10 @@
     ReadParam(section, "default_delay", &cfg.delay.default_delay);
     ReadParam(section, "down_sampling_factor", &cfg.delay.down_sampling_factor);
     ReadParam(section, "num_filters", &cfg.delay.num_filters);
-    ReadParam(section, "api_call_jitter_blocks",
-              &cfg.delay.api_call_jitter_blocks);
-    ReadParam(section, "min_echo_path_delay_blocks",
-              &cfg.delay.min_echo_path_delay_blocks);
-    ReadParam(section, "delay_headroom_blocks",
-              &cfg.delay.delay_headroom_blocks);
-    ReadParam(section, "hysteresis_limit_1_blocks",
-              &cfg.delay.hysteresis_limit_1_blocks);
-    ReadParam(section, "hysteresis_limit_2_blocks",
-              &cfg.delay.hysteresis_limit_2_blocks);
-    ReadParam(section, "skew_hysteresis_blocks",
-              &cfg.delay.skew_hysteresis_blocks);
+    ReadParam(section, "delay_headroom_samples",
+              &cfg.delay.delay_headroom_samples);
+    ReadParam(section, "hysteresis_limit_blocks",
+              &cfg.delay.hysteresis_limit_blocks);
     ReadParam(section, "fixed_capture_delay_samples",
               &cfg.delay.fixed_capture_delay_samples);
     ReadParam(section, "delay_estimate_smoothing",
@@ -201,9 +193,7 @@
   }
 
   if (rtc::GetValueFromJsonObject(aec3_root, "ep_strength", &section)) {
-    ReadParam(section, "lf", &cfg.ep_strength.lf);
-    ReadParam(section, "mf", &cfg.ep_strength.mf);
-    ReadParam(section, "hf", &cfg.ep_strength.hf);
+    ReadParam(section, "default_gain", &cfg.ep_strength.default_gain);
     ReadParam(section, "default_len", &cfg.ep_strength.default_len);
     ReadParam(section, "reverb_based_on_render",
               &cfg.ep_strength.reverb_based_on_render);
@@ -241,17 +231,6 @@
 
   if (rtc::GetValueFromJsonObject(aec3_root, "echo_removal_control",
                                   &section)) {
-    Json::Value subsection;
-    if (rtc::GetValueFromJsonObject(section, "gain_rampup", &subsection)) {
-      ReadParam(subsection, "initial_gain",
-                &cfg.echo_removal_control.gain_rampup.initial_gain);
-      ReadParam(subsection, "first_non_zero_gain",
-                &cfg.echo_removal_control.gain_rampup.first_non_zero_gain);
-      ReadParam(subsection, "non_zero_gain_blocks",
-                &cfg.echo_removal_control.gain_rampup.non_zero_gain_blocks);
-      ReadParam(subsection, "full_gain_blocks",
-                &cfg.echo_removal_control.gain_rampup.full_gain_blocks);
-    }
     ReadParam(section, "has_clock_drift",
               &cfg.echo_removal_control.has_clock_drift);
     ReadParam(section, "linear_and_stable_echo_path",
@@ -352,17 +331,9 @@
   ost << "\"down_sampling_factor\": " << config.delay.down_sampling_factor
       << ",";
   ost << "\"num_filters\": " << config.delay.num_filters << ",";
-  ost << "\"api_call_jitter_blocks\": " << config.delay.api_call_jitter_blocks
+  ost << "\"delay_headroom_samples\": " << config.delay.delay_headroom_samples
       << ",";
-  ost << "\"min_echo_path_delay_blocks\": "
-      << config.delay.min_echo_path_delay_blocks << ",";
-  ost << "\"delay_headroom_blocks\": " << config.delay.delay_headroom_blocks
-      << ",";
-  ost << "\"hysteresis_limit_1_blocks\": "
-      << config.delay.hysteresis_limit_1_blocks << ",";
-  ost << "\"hysteresis_limit_2_blocks\": "
-      << config.delay.hysteresis_limit_2_blocks << ",";
-  ost << "\"skew_hysteresis_blocks\": " << config.delay.skew_hysteresis_blocks
+  ost << "\"hysteresis_limit_blocks\": " << config.delay.hysteresis_limit_blocks
       << ",";
   ost << "\"fixed_capture_delay_samples\": "
       << config.delay.fixed_capture_delay_samples << ",";
@@ -431,9 +402,7 @@
   ost << "},";
 
   ost << "\"ep_strength\": {";
-  ost << "\"lf\": " << config.ep_strength.lf << ",";
-  ost << "\"mf\": " << config.ep_strength.mf << ",";
-  ost << "\"hf\": " << config.ep_strength.hf << ",";
+  ost << "\"default_gain\": " << config.ep_strength.default_gain << ",";
   ost << "\"default_len\": " << config.ep_strength.default_len << ",";
   ost << "\"reverb_based_on_render\": "
       << (config.ep_strength.reverb_based_on_render ? "true" : "false") << ",";
@@ -474,16 +443,6 @@
   ost << "},";
 
   ost << "\"echo_removal_control\": {";
-  ost << "\"gain_rampup\": {";
-  ost << "\"initial_gain\": "
-      << config.echo_removal_control.gain_rampup.initial_gain << ",";
-  ost << "\"first_non_zero_gain\": "
-      << config.echo_removal_control.gain_rampup.first_non_zero_gain << ",";
-  ost << "\"non_zero_gain_blocks\": "
-      << config.echo_removal_control.gain_rampup.non_zero_gain_blocks << ",";
-  ost << "\"full_gain_blocks\": "
-      << config.echo_removal_control.gain_rampup.full_gain_blocks;
-  ost << "},";
   ost << "\"has_clock_drift\": "
       << (config.echo_removal_control.has_clock_drift ? "true" : "false")
       << ",";
diff --git a/api/audio_options.cc b/api/audio_options.cc
index e33214b..16c0430 100644
--- a/api/audio_options.cc
+++ b/api/audio_options.cc
@@ -10,6 +10,7 @@
 
 #include "api/audio_options.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace cricket {
@@ -51,6 +52,8 @@
           change.audio_jitter_buffer_fast_accelerate);
   SetFrom(&audio_jitter_buffer_min_delay_ms,
           change.audio_jitter_buffer_min_delay_ms);
+  SetFrom(&audio_jitter_buffer_enable_rtx_handling,
+          change.audio_jitter_buffer_enable_rtx_handling);
   SetFrom(&typing_detection, change.typing_detection);
   SetFrom(&experimental_agc, change.experimental_agc);
   SetFrom(&extended_filter_aec, change.extended_filter_aec);
@@ -80,6 +83,8 @@
              o.audio_jitter_buffer_fast_accelerate &&
          audio_jitter_buffer_min_delay_ms ==
              o.audio_jitter_buffer_min_delay_ms &&
+         audio_jitter_buffer_enable_rtx_handling ==
+             o.audio_jitter_buffer_enable_rtx_handling &&
          typing_detection == o.typing_detection &&
          experimental_agc == o.experimental_agc &&
          extended_filter_aec == o.extended_filter_aec &&
@@ -113,6 +118,8 @@
                 audio_jitter_buffer_fast_accelerate);
   ToStringIfSet(&result, "audio_jitter_buffer_min_delay_ms",
                 audio_jitter_buffer_min_delay_ms);
+  ToStringIfSet(&result, "audio_jitter_buffer_enable_rtx_handling",
+                audio_jitter_buffer_enable_rtx_handling);
   ToStringIfSet(&result, "typing", typing_detection);
   ToStringIfSet(&result, "experimental_agc", experimental_agc);
   ToStringIfSet(&result, "extended_filter_aec", extended_filter_aec);
diff --git a/api/audio_options.h b/api/audio_options.h
index c2d1f44..478bff6 100644
--- a/api/audio_options.h
+++ b/api/audio_options.h
@@ -56,6 +56,8 @@
   absl::optional<bool> audio_jitter_buffer_fast_accelerate;
   // Audio receiver jitter buffer (NetEq) minimum target delay in milliseconds.
   absl::optional<int> audio_jitter_buffer_min_delay_ms;
+  // Audio receiver jitter buffer (NetEq) should handle retransmitted packets.
+  absl::optional<bool> audio_jitter_buffer_enable_rtx_handling;
   // Audio processing to detect typing.
   absl::optional<bool> typing_detection;
   absl::optional<bool> experimental_agc;
diff --git a/api/candidate.cc b/api/candidate.cc
index 275b173..c857f89 100644
--- a/api/candidate.cc
+++ b/api/candidate.cc
@@ -11,7 +11,7 @@
 #include "api/candidate.h"
 
 #include "rtc_base/helpers.h"
-#include "rtc_base/ipaddress.h"
+#include "rtc_base/ip_address.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace cricket {
@@ -125,4 +125,19 @@
   return !(*this == o);
 }
 
+Candidate Candidate::ToSanitizedCopy(bool use_hostname_address,
+                                     bool filter_related_address) const {
+  Candidate copy(*this);
+  if (use_hostname_address) {
+    rtc::SocketAddress hostname_only_addr(address().hostname(),
+                                          address().port());
+    copy.set_address(hostname_only_addr);
+  }
+  if (filter_related_address) {
+    copy.set_related_address(
+        rtc::EmptySocketAddressWithFamily(copy.address().family()));
+  }
+  return copy;
+}
+
 }  // namespace cricket
diff --git a/api/candidate.h b/api/candidate.h
index 4c650d9..7452055 100644
--- a/api/candidate.h
+++ b/api/candidate.h
@@ -19,7 +19,7 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/network_constants.h"
-#include "rtc_base/socketaddress.h"
+#include "rtc_base/socket_address.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace cricket {
@@ -166,6 +166,16 @@
   bool operator==(const Candidate& o) const;
   bool operator!=(const Candidate& o) const;
 
+  // Returns a sanitized copy configured by the given booleans. If
+  // |use_host_address| is true, the returned copy has its IP removed from
+  // |address()|, which leads |address()| to be a hostname address. If
+  // |filter_related_address|, the returned copy has its related address reset
+  // to the wildcard address (i.e. 0.0.0.0 for IPv4 and :: for IPv6). Note that
+  // setting both booleans to false returns an identical copy to the original
+  // candidate.
+  Candidate ToSanitizedCopy(bool use_hostname_address,
+                            bool filter_related_address) const;
+
  private:
   std::string ToStringInternal(bool sensitive) const;
 
diff --git a/api/create_peerconnection_factory.cc b/api/create_peerconnection_factory.cc
index 1a6d086..0d15e8c 100644
--- a/api/create_peerconnection_factory.cc
+++ b/api/create_peerconnection_factory.cc
@@ -13,104 +13,26 @@
 #include <memory>
 #include <utility>
 
-#include "api/call/callfactoryinterface.h"
-#include "api/peerconnectioninterface.h"
+#include "api/audio/audio_mixer.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
+#include "api/audio_codecs/audio_encoder_factory.h"
+#include "api/call/call_factory_interface.h"
+#include "api/fec_controller.h"
+#include "api/peer_connection_interface.h"
+#include "api/scoped_refptr.h"
+#include "api/transport/network_control.h"
 #include "api/video_codecs/video_decoder_factory.h"
 #include "api/video_codecs/video_encoder_factory.h"
 #include "logging/rtc_event_log/rtc_event_log_factory.h"
 #include "logging/rtc_event_log/rtc_event_log_factory_interface.h"
-#include "media/engine/webrtcmediaengine.h"
+#include "media/base/media_engine.h"
+#include "media/engine/webrtc_media_engine.h"
 #include "modules/audio_device/include/audio_device.h"
 #include "modules/audio_processing/include/audio_processing.h"
-#include "rtc_base/bind.h"
-#include "rtc_base/scoped_ref_ptr.h"
 #include "rtc_base/thread.h"
 
 namespace webrtc {
 
-#if defined(USE_BUILTIN_SW_CODECS)
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory) {
-  return CreatePeerConnectionFactoryWithAudioMixer(
-      nullptr /*network_thread*/, nullptr /*worker_thread*/,
-      nullptr /*signaling_thread*/, nullptr /*default_adm*/,
-      audio_encoder_factory, audio_decoder_factory,
-      nullptr /*video_encoder_factory*/, nullptr /*video_decoder_factory*/,
-      nullptr /*audio_mixer*/);
-}
-
-// Note: all the other CreatePeerConnectionFactory variants just end up calling
-// this, ultimately.
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing) {
-  rtc::scoped_refptr<AudioProcessing> audio_processing_use = audio_processing;
-  if (!audio_processing_use) {
-    audio_processing_use = AudioProcessingBuilder().Create();
-  }
-
-  std::unique_ptr<cricket::MediaEngineInterface> media_engine(
-      cricket::WebRtcMediaEngineFactory::Create(
-          default_adm, audio_encoder_factory, audio_decoder_factory,
-          video_encoder_factory, video_decoder_factory, audio_mixer,
-          audio_processing_use));
-
-  std::unique_ptr<CallFactoryInterface> call_factory = CreateCallFactory();
-
-  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory =
-      CreateRtcEventLogFactory();
-
-  return CreateModularPeerConnectionFactory(
-      network_thread, worker_thread, signaling_thread, std::move(media_engine),
-      std::move(call_factory), std::move(event_log_factory));
-}
-
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing,
-    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
-    std::unique_ptr<NetworkControllerFactoryInterface>
-        network_controller_factory) {
-  rtc::scoped_refptr<AudioProcessing> audio_processing_use = audio_processing;
-  if (!audio_processing_use) {
-    audio_processing_use = AudioProcessingBuilder().Create();
-  }
-
-  std::unique_ptr<cricket::MediaEngineInterface> media_engine(
-      cricket::WebRtcMediaEngineFactory::Create(
-          default_adm, audio_encoder_factory, audio_decoder_factory,
-          video_encoder_factory, video_decoder_factory, audio_mixer,
-          audio_processing_use));
-
-  std::unique_ptr<CallFactoryInterface> call_factory = CreateCallFactory();
-
-  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory =
-      CreateRtcEventLogFactory();
-
-  return CreateModularPeerConnectionFactory(
-      network_thread, worker_thread, signaling_thread, std::move(media_engine),
-      std::move(call_factory), std::move(event_log_factory),
-      std::move(fec_controller_factory), std::move(network_controller_factory));
-}
-#endif
-
 rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
     rtc::Thread* network_thread,
     rtc::Thread* worker_thread,
@@ -145,38 +67,4 @@
   return CreateModularPeerConnectionFactory(std::move(dependencies));
 }
 
-#if defined(USE_BUILTIN_SW_CODECS)
-rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactoryWithAudioMixer(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer) {
-  return CreatePeerConnectionFactory(
-      network_thread, worker_thread, signaling_thread, default_adm,
-      audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
-      video_decoder_factory, audio_mixer, nullptr);
-}
-
-rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory) {
-  return CreatePeerConnectionFactoryWithAudioMixer(
-      network_thread, worker_thread, signaling_thread, default_adm,
-      audio_encoder_factory, audio_decoder_factory, video_encoder_factory,
-      video_decoder_factory, nullptr);
-}
-#endif
-
 }  // namespace webrtc
diff --git a/api/create_peerconnection_factory.h b/api/create_peerconnection_factory.h
index baa50c7..40f1276 100644
--- a/api/create_peerconnection_factory.h
+++ b/api/create_peerconnection_factory.h
@@ -17,9 +17,10 @@
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_encoder_factory.h"
 #include "api/fec_controller.h"
-#include "api/peerconnectioninterface.h"
+#include "api/peer_connection_interface.h"
+#include "api/scoped_refptr.h"
 #include "api/transport/network_control.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/deprecation.h"
 
 namespace rtc {
 // TODO(bugs.webrtc.org/9987): Move rtc::Thread to api/ or expose a better
@@ -28,104 +29,14 @@
 class Thread;
 }  // namespace rtc
 
-namespace cricket {
-class WebRtcVideoDecoderFactory;
-class WebRtcVideoEncoderFactory;
-}  // namespace cricket
-
 namespace webrtc {
 
 class AudioDeviceModule;
 class AudioProcessing;
 
-#if defined(USE_BUILTIN_SW_CODECS)
-// Create a new instance of PeerConnectionFactoryInterface.
-//
-// This method relies on the thread it's called on as the "signaling thread"
-// for the PeerConnectionFactory it creates.
-//
-// As such, if the current thread is not already running an rtc::Thread message
-// loop, an application using this method must eventually either call
-// rtc::Thread::Current()->Run(), or call
-// rtc::Thread::Current()->ProcessMessages() within the application's own
-// message loop.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory);
-
-// Create a new instance of PeerConnectionFactoryInterface.
-//
-// |network_thread|, |worker_thread| and |signaling_thread| are
-// the only mandatory parameters.
-//
-// If non-null, a reference is added to |default_adm|, and ownership of
-// |video_encoder_factory| and |video_decoder_factory| is transferred to the
-// returned factory.
-// TODO(deadbeef): Use rtc::scoped_refptr<> and std::unique_ptr<> to make this
-// ownership transfer and ref counting more obvious.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory);
-
-// Create a new instance of PeerConnectionFactoryInterface with optional
-// external audio mixed and audio processing modules.
-//
-// If |audio_mixer| is null, an internal audio mixer will be created and used.
-// If |audio_processing| is null, an internal audio processing module will be
-// created and used.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing);
-
-// Create a new instance of PeerConnectionFactoryInterface with optional
-// external audio mixer, audio processing, and fec controller modules.
-//
-// If |audio_mixer| is null, an internal audio mixer will be created and used.
-// If |audio_processing| is null, an internal audio processing module will be
-// created and used.
-// If |fec_controller_factory| is null, an internal fec controller module will
-// be created and used.
-// If |network_controller_factory| is provided, it will be used if enabled via
-// field trial.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer,
-    rtc::scoped_refptr<AudioProcessing> audio_processing,
-    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
-    std::unique_ptr<NetworkControllerFactoryInterface>
-        network_controller_factory = nullptr);
-#endif  // defined(USE_BUILTIN_SW_CODECS)
-
 // Create a new instance of PeerConnectionFactoryInterface with optional video
 // codec factories. These video factories represents all video codecs, i.e. no
 // extra internal video codecs will be added.
-// When building WebRTC with rtc_use_builtin_sw_codecs = false, this is the
-// only available CreatePeerConnectionFactory overload.
 RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
 CreatePeerConnectionFactory(
     rtc::Thread* network_thread,
@@ -139,41 +50,6 @@
     rtc::scoped_refptr<AudioMixer> audio_mixer,
     rtc::scoped_refptr<AudioProcessing> audio_processing);
 
-#if defined(USE_BUILTIN_SW_CODECS)
-// Create a new instance of PeerConnectionFactoryInterface with external audio
-// mixer.
-//
-// If |audio_mixer| is null, an internal audio mixer will be created and used.
-RTC_EXPORT rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactoryWithAudioMixer(
-    rtc::Thread* network_thread,
-    rtc::Thread* worker_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory,
-    rtc::scoped_refptr<AudioMixer> audio_mixer);
-
-// Create a new instance of PeerConnectionFactoryInterface.
-// Same thread is used as worker and network thread.
-RTC_EXPORT inline rtc::scoped_refptr<PeerConnectionFactoryInterface>
-CreatePeerConnectionFactory(
-    rtc::Thread* worker_and_network_thread,
-    rtc::Thread* signaling_thread,
-    AudioDeviceModule* default_adm,
-    rtc::scoped_refptr<AudioEncoderFactory> audio_encoder_factory,
-    rtc::scoped_refptr<AudioDecoderFactory> audio_decoder_factory,
-    cricket::WebRtcVideoEncoderFactory* video_encoder_factory,
-    cricket::WebRtcVideoDecoderFactory* video_decoder_factory) {
-  return CreatePeerConnectionFactory(
-      worker_and_network_thread, worker_and_network_thread, signaling_thread,
-      default_adm, audio_encoder_factory, audio_decoder_factory,
-      video_encoder_factory, video_decoder_factory);
-}
-#endif  // defined(USE_BUILTIN_SW_CODECS)
-
 }  // namespace webrtc
 
 #endif  // API_CREATE_PEERCONNECTION_FACTORY_H_
diff --git a/api/crypto_params.h b/api/crypto_params.h
new file mode 100644
index 0000000..5da352c
--- /dev/null
+++ b/api/crypto_params.h
@@ -0,0 +1,41 @@
+/*
+ *  Copyright (c) 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.
+ */
+
+#ifndef API_CRYPTO_PARAMS_H_
+#define API_CRYPTO_PARAMS_H_
+
+#include <string>
+
+namespace cricket {
+
+// Parameters for SRTP negotiation, as described in RFC 4568.
+// TODO(benwright) - Rename to SrtpCryptoParams as these only apply to SRTP and
+// not generic crypto parameters for WebRTC.
+struct CryptoParams {
+  CryptoParams() : tag(0) {}
+  CryptoParams(int t,
+               const std::string& cs,
+               const std::string& kp,
+               const std::string& sp)
+      : tag(t), cipher_suite(cs), key_params(kp), session_params(sp) {}
+
+  bool Matches(const CryptoParams& params) const {
+    return (tag == params.tag && cipher_suite == params.cipher_suite);
+  }
+
+  int tag;
+  std::string cipher_suite;
+  std::string key_params;
+  std::string session_params;
+};
+
+}  // namespace cricket
+
+#endif  // API_CRYPTO_PARAMS_H_
diff --git a/api/data_channel_interface.cc b/api/data_channel_interface.cc
new file mode 100644
index 0000000..240ccbe
--- /dev/null
+++ b/api/data_channel_interface.cc
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 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/data_channel_interface.h"
+
+namespace webrtc {
+
+bool DataChannelInterface::ordered() const {
+  return false;
+}
+
+uint16_t DataChannelInterface::maxRetransmitTime() const {
+  return 0;
+}
+
+uint16_t DataChannelInterface::maxRetransmits() const {
+  return 0;
+}
+
+std::string DataChannelInterface::protocol() const {
+  return std::string();
+}
+
+bool DataChannelInterface::negotiated() const {
+  return false;
+}
+
+}  // namespace webrtc
diff --git a/api/data_channel_interface.h b/api/data_channel_interface.h
new file mode 100644
index 0000000..91a9804
--- /dev/null
+++ b/api/data_channel_interface.h
@@ -0,0 +1,180 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// This file contains interfaces for DataChannels
+// http://dev.w3.org/2011/webrtc/editor/webrtc.html#rtcdatachannel
+
+#ifndef API_DATA_CHANNEL_INTERFACE_H_
+#define API_DATA_CHANNEL_INTERFACE_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelinit
+// TODO(deadbeef): Use absl::optional for the "-1 if unset" things.
+struct DataChannelInit {
+  // Deprecated. Reliability is assumed, and channel will be unreliable if
+  // maxRetransmitTime or MaxRetransmits is set.
+  bool reliable = false;
+
+  // True if ordered delivery is required.
+  bool ordered = true;
+
+  // The max period of time in milliseconds in which retransmissions will be
+  // sent. After this time, no more retransmissions will be sent. -1 if unset.
+  //
+  // Cannot be set along with |maxRetransmits|.
+  int maxRetransmitTime = -1;
+
+  // The max number of retransmissions. -1 if unset.
+  //
+  // Cannot be set along with |maxRetransmitTime|.
+  int maxRetransmits = -1;
+
+  // This is set by the application and opaque to the WebRTC implementation.
+  std::string protocol;
+
+  // True if the channel has been externally negotiated and we do not send an
+  // in-band signalling in the form of an "open" message. If this is true, |id|
+  // below must be set; otherwise it should be unset and will be negotiated
+  // in-band.
+  bool negotiated = false;
+
+  // The stream id, or SID, for SCTP data channels. -1 if unset (see above).
+  int id = -1;
+};
+
+// At the JavaScript level, data can be passed in as a string or a blob, so
+// this structure's |binary| flag tells whether the data should be interpreted
+// as binary or text.
+struct DataBuffer {
+  DataBuffer(const rtc::CopyOnWriteBuffer& data, bool binary)
+      : data(data), binary(binary) {}
+  // For convenience for unit tests.
+  explicit DataBuffer(const std::string& text)
+      : data(text.data(), text.length()), binary(false) {}
+  size_t size() const { return data.size(); }
+
+  rtc::CopyOnWriteBuffer data;
+  // Indicates if the received data contains UTF-8 or binary data.
+  // Note that the upper layers are left to verify the UTF-8 encoding.
+  // TODO(jiayl): prefer to use an enum instead of a bool.
+  bool binary;
+};
+
+// Used to implement RTCDataChannel events.
+//
+// The code responding to these callbacks should unwind the stack before
+// using any other webrtc APIs; re-entrancy is not supported.
+class DataChannelObserver {
+ public:
+  // The data channel state have changed.
+  virtual void OnStateChange() = 0;
+  //  A data buffer was successfully received.
+  virtual void OnMessage(const DataBuffer& buffer) = 0;
+  // The data channel's buffered_amount has changed.
+  virtual void OnBufferedAmountChange(uint64_t previous_amount) {}
+
+ protected:
+  virtual ~DataChannelObserver() = default;
+};
+
+class DataChannelInterface : public rtc::RefCountInterface {
+ public:
+  // C++ version of: https://www.w3.org/TR/webrtc/#idl-def-rtcdatachannelstate
+  // Unlikely to change, but keep in sync with DataChannel.java:State and
+  // RTCDataChannel.h:RTCDataChannelState.
+  enum DataState {
+    kConnecting,
+    kOpen,  // The DataChannel is ready to send data.
+    kClosing,
+    kClosed
+  };
+
+  static const char* DataStateString(DataState state) {
+    switch (state) {
+      case kConnecting:
+        return "connecting";
+      case kOpen:
+        return "open";
+      case kClosing:
+        return "closing";
+      case kClosed:
+        return "closed";
+    }
+    RTC_CHECK(false) << "Unknown DataChannel state: " << state;
+    return "";
+  }
+
+  // Used to receive events from the data channel. Only one observer can be
+  // registered at a time. UnregisterObserver should be called before the
+  // observer object is destroyed.
+  virtual void RegisterObserver(DataChannelObserver* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+
+  // The label attribute represents a label that can be used to distinguish this
+  // DataChannel object from other DataChannel objects.
+  virtual std::string label() const = 0;
+
+  // The accessors below simply return the properties from the DataChannelInit
+  // the data channel was constructed with.
+  virtual bool reliable() const = 0;
+  // TODO(deadbeef): Remove these dummy implementations when all classes have
+  // implemented these APIs. They should all just return the values the
+  // DataChannel was created with.
+  virtual bool ordered() const;
+  virtual uint16_t maxRetransmitTime() const;
+  virtual uint16_t maxRetransmits() const;
+  virtual std::string protocol() const;
+  virtual bool negotiated() const;
+
+  // Returns the ID from the DataChannelInit, if it was negotiated out-of-band.
+  // If negotiated in-band, this ID will be populated once the DTLS role is
+  // determined, and until then this will return -1.
+  virtual int id() const = 0;
+  virtual DataState state() const = 0;
+  virtual uint32_t messages_sent() const = 0;
+  virtual uint64_t bytes_sent() const = 0;
+  virtual uint32_t messages_received() const = 0;
+  virtual uint64_t bytes_received() const = 0;
+
+  // Returns the number of bytes of application data (UTF-8 text and binary
+  // data) that have been queued using Send but have not yet been processed at
+  // the SCTP level. See comment above Send below.
+  virtual uint64_t buffered_amount() const = 0;
+
+  // Begins the graceful data channel closing procedure. See:
+  // https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.7
+  virtual void Close() = 0;
+
+  // Sends |data| to the remote peer. If the data can't be sent at the SCTP
+  // level (due to congestion control), it's buffered at the data channel level,
+  // up to a maximum of 16MB. If Send is called while this buffer is full, the
+  // data channel will be closed abruptly.
+  //
+  // So, it's important to use buffered_amount() and OnBufferedAmountChange to
+  // ensure the data channel is used efficiently but without filling this
+  // buffer.
+  virtual bool Send(const DataBuffer& buffer) = 0;
+
+ protected:
+  ~DataChannelInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_DATA_CHANNEL_INTERFACE_H_
diff --git a/api/dtls_transport_interface.h b/api/dtls_transport_interface.h
new file mode 100644
index 0000000..7f35a23
--- /dev/null
+++ b/api/dtls_transport_interface.h
@@ -0,0 +1,76 @@
+/*
+ *  Copyright 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_DTLS_TRANSPORT_INTERFACE_H_
+#define API_DTLS_TRANSPORT_INTERFACE_H_
+
+#include "api/ice_transport_interface.h"
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// States of a DTLS transport, corresponding to the JS API specification.
+// http://w3c.github.io/webrtc-pc/#dom-rtcdtlstransportstate
+enum class DtlsTransportState {
+  kNew,         // Has not started negotiating yet.
+  kConnecting,  // In the process of negotiating a secure connection.
+  kConnected,   // Completed negotiation and verified fingerprints.
+  kClosed,      // Intentionally closed.
+  kFailed,      // Failure due to an error or failing to verify a remote
+                // fingerprint.
+  kNumValues
+};
+
+// This object gives snapshot information about the changeable state of a
+// DTLSTransport.
+class DtlsTransportInformation {
+ public:
+  explicit DtlsTransportInformation(DtlsTransportState state) : state_(state) {}
+  DtlsTransportState state() const { return state_; }
+  // TODO(hta): Add remote certificate access
+ private:
+  DtlsTransportState state_;
+};
+
+class DtlsTransportObserverInterface {
+ public:
+  // This callback carries information about the state of the transport.
+  // The argument is a pass-by-value snapshot of the state.
+  virtual void OnStateChange(DtlsTransportInformation info) = 0;
+  // This callback is called when an error occurs, causing the transport
+  // to go to the kFailed state.
+  virtual void OnError(RTCError error) = 0;
+
+ protected:
+  virtual ~DtlsTransportObserverInterface() = default;
+};
+
+// A DTLS transport, as represented to the outside world.
+// This object is created on the network thread, and can only be
+// accessed on that thread, except for functions explicitly marked otherwise.
+// References can be held by other threads, and destruction can therefore
+// be initiated by other threads.
+class DtlsTransportInterface : public rtc::RefCountInterface {
+ public:
+  // Returns a pointer to the ICE transport that is owned by the DTLS transport.
+  virtual rtc::scoped_refptr<IceTransportInterface> ice_transport() = 0;
+  // Returns information on the state of the DtlsTransport.
+  // This function can be called from other threads.
+  virtual DtlsTransportInformation Information() = 0;
+  // Observer management.
+  virtual void RegisterObserver(DtlsTransportObserverInterface* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_DTLS_TRANSPORT_INTERFACE_H_
diff --git a/api/dtmf_sender_interface.h b/api/dtmf_sender_interface.h
new file mode 100644
index 0000000..9cdfba1
--- /dev/null
+++ b/api/dtmf_sender_interface.h
@@ -0,0 +1,100 @@
+/*
+ *  Copyright 2012 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_DTMF_SENDER_INTERFACE_H_
+#define API_DTMF_SENDER_INTERFACE_H_
+
+#include <string>
+
+#include "api/media_stream_interface.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// DtmfSender callback interface, used to implement RTCDtmfSender events.
+// Applications should implement this interface to get notifications from the
+// DtmfSender.
+class DtmfSenderObserverInterface {
+ public:
+  // Triggered when DTMF |tone| is sent.
+  // If |tone| is empty that means the DtmfSender has sent out all the given
+  // tones.
+  // The callback includes the state of the tone buffer at the time when
+  // the tone finished playing.
+  virtual void OnToneChange(const std::string& tone,
+                            const std::string& tone_buffer) {}
+  // DEPRECATED: Older API without tone buffer.
+  // TODO(bugs.webrtc.org/9725): Remove old API and default implementation
+  // when old callers are gone.
+  virtual void OnToneChange(const std::string& tone) {}
+
+ protected:
+  virtual ~DtmfSenderObserverInterface() = default;
+};
+
+// The interface of native implementation of the RTCDTMFSender defined by the
+// WebRTC W3C Editor's Draft.
+// See: https://www.w3.org/TR/webrtc/#peer-to-peer-dtmf
+class DtmfSenderInterface : public rtc::RefCountInterface {
+ public:
+  // Used to receive events from the DTMF sender. Only one observer can be
+  // registered at a time. UnregisterObserver should be called before the
+  // observer object is destroyed.
+  virtual void RegisterObserver(DtmfSenderObserverInterface* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+
+  // Returns true if this DtmfSender is capable of sending DTMF. Otherwise
+  // returns false. To be able to send DTMF, the associated RtpSender must be
+  // able to send packets, and a "telephone-event" codec must be negotiated.
+  virtual bool CanInsertDtmf() = 0;
+
+  // Queues a task that sends the DTMF |tones|. The |tones| parameter is treated
+  // as a series of characters. The characters 0 through 9, A through D, #, and
+  // * generate the associated DTMF tones. The characters a to d are equivalent
+  // to A to D. The character ',' indicates a delay of 2 seconds before
+  // processing the next character in the tones parameter.
+  //
+  // Unrecognized characters are ignored.
+  //
+  // The |duration| parameter indicates the duration in ms to use for each
+  // character passed in the |tones| parameter. The duration cannot be more
+  // than 6000 or less than 70.
+  //
+  // The |inter_tone_gap| parameter indicates the gap between tones in ms. The
+  // |inter_tone_gap| must be at least 50 ms but should be as short as
+  // possible.
+  //
+  // If InsertDtmf is called on the same object while an existing task for this
+  // object to generate DTMF is still running, the previous task is canceled.
+  // Returns true on success and false on failure.
+  virtual bool InsertDtmf(const std::string& tones,
+                          int duration,
+                          int inter_tone_gap) = 0;
+
+  // Returns the tones remaining to be played out.
+  virtual std::string tones() const = 0;
+
+  // Returns the current tone duration value in ms.
+  // This value will be the value last set via the InsertDtmf() method, or the
+  // default value of 100 ms if InsertDtmf() was never called.
+  virtual int duration() const = 0;
+
+  // Returns the current value of the between-tone gap in ms.
+  // This value will be the value last set via the InsertDtmf() method, or the
+  // default value of 50 ms if InsertDtmf() was never called.
+  virtual int inter_tone_gap() const = 0;
+
+ protected:
+  ~DtmfSenderInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_DTMF_SENDER_INTERFACE_H_
diff --git a/api/ice_transport_factory.cc b/api/ice_transport_factory.cc
new file mode 100644
index 0000000..6cc399a
--- /dev/null
+++ b/api/ice_transport_factory.cc
@@ -0,0 +1,58 @@
+/*
+ *  Copyright 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 "api/ice_transport_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "absl/memory/memory.h"
+#include "p2p/base/ice_transport_internal.h"
+#include "p2p/base/p2p_transport_channel.h"
+#include "p2p/base/port_allocator.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+namespace {
+
+// This implementation of IceTransportInterface is used in cases where
+// the only reference to the P2PTransport will be through this class.
+// It must be constructed, accessed and destroyed on the signaling thread.
+class IceTransportWithTransportChannel : public IceTransportInterface {
+ public:
+  IceTransportWithTransportChannel(
+      std::unique_ptr<cricket::IceTransportInternal> internal)
+      : internal_(std::move(internal)) {}
+
+  ~IceTransportWithTransportChannel() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+  }
+
+  cricket::IceTransportInternal* internal() override {
+    RTC_DCHECK_RUN_ON(&thread_checker_);
+    return internal_.get();
+  }
+
+ private:
+  const rtc::ThreadChecker thread_checker_{};
+  const std::unique_ptr<cricket::IceTransportInternal> internal_
+      RTC_GUARDED_BY(thread_checker_);
+};
+
+}  // namespace
+
+rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+    cricket::PortAllocator* port_allocator) {
+  return new rtc::RefCountedObject<IceTransportWithTransportChannel>(
+      absl::make_unique<cricket::P2PTransportChannel>("", 0, port_allocator));
+}
+
+}  // namespace webrtc
diff --git a/api/ice_transport_factory.h b/api/ice_transport_factory.h
new file mode 100644
index 0000000..a8330df
--- /dev/null
+++ b/api/ice_transport_factory.h
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef API_ICE_TRANSPORT_FACTORY_H_
+#define API_ICE_TRANSPORT_FACTORY_H_
+
+#include "api/ice_transport_interface.h"
+#include "api/scoped_refptr.h"
+
+namespace cricket {
+class PortAllocator;
+}
+
+namespace webrtc {
+
+// Static factory for an IceTransport object that can be created
+// without using a webrtc::PeerConnection.
+// The returned object must be accessed and destroyed on the thread that
+// created it.
+// The PortAllocator must outlive the created IceTransportInterface object.
+rtc::scoped_refptr<IceTransportInterface> CreateIceTransport(
+    cricket::PortAllocator* port_allocator);
+
+}  // namespace webrtc
+
+#endif  // API_ICE_TRANSPORT_FACTORY_H_
diff --git a/api/ice_transport_interface.h b/api/ice_transport_interface.h
new file mode 100644
index 0000000..6e63045
--- /dev/null
+++ b/api/ice_transport_interface.h
@@ -0,0 +1,38 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef API_ICE_TRANSPORT_INTERFACE_H_
+#define API_ICE_TRANSPORT_INTERFACE_H_
+
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace cricket {
+class IceTransportInternal;
+}  // namespace cricket
+
+namespace webrtc {
+
+// An ICE transport, as represented to the outside world.
+// This object is refcounted, and is therefore alive until the
+// last holder has released it.
+class IceTransportInterface : public rtc::RefCountInterface {
+ public:
+  // Accessor for the internal representation of an ICE transport.
+  // The returned object can only be safely used on the signalling thread.
+  // TODO(crbug.com/907849): Add API calls for the functions that have to
+  // be exposed to clients, and stop allowing access to the
+  // cricket::IceTransportInternal API.
+  virtual cricket::IceTransportInternal* internal() = 0;
+};
+
+}  // namespace webrtc
+#endif  // API_ICE_TRANSPORT_INTERFACE_H_
diff --git a/api/jsep.h b/api/jsep.h
index 1c50455..6da7827 100644
--- a/api/jsep.h
+++ b/api/jsep.h
@@ -27,8 +27,8 @@
 #include <vector>
 
 #include "absl/types/optional.h"
-#include "api/rtcerror.h"
-#include "rtc_base/refcount.h"
+#include "api/rtc_error.h"
+#include "rtc_base/ref_count.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace cricket {
diff --git a/api/jsep_ice_candidate.cc b/api/jsep_ice_candidate.cc
new file mode 100644
index 0000000..59da4e4
--- /dev/null
+++ b/api/jsep_ice_candidate.cc
@@ -0,0 +1,86 @@
+/*
+ *  Copyright 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/jsep_ice_candidate.h"
+
+#include <algorithm>
+#include <utility>
+
+namespace webrtc {
+
+std::string JsepIceCandidate::sdp_mid() const {
+  return sdp_mid_;
+}
+
+int JsepIceCandidate::sdp_mline_index() const {
+  return sdp_mline_index_;
+}
+
+const cricket::Candidate& JsepIceCandidate::candidate() const {
+  return candidate_;
+}
+
+std::string JsepIceCandidate::server_url() const {
+  return candidate_.url();
+}
+
+JsepCandidateCollection::JsepCandidateCollection() = default;
+
+JsepCandidateCollection::JsepCandidateCollection(JsepCandidateCollection&& o)
+    : candidates_(std::move(o.candidates_)) {}
+
+size_t JsepCandidateCollection::count() const {
+  return candidates_.size();
+}
+
+void JsepCandidateCollection::add(JsepIceCandidate* candidate) {
+  candidates_.push_back(candidate);
+}
+
+const IceCandidateInterface* JsepCandidateCollection::at(size_t index) const {
+  return candidates_[index];
+}
+
+JsepCandidateCollection::~JsepCandidateCollection() {
+  for (std::vector<JsepIceCandidate*>::iterator it = candidates_.begin();
+       it != candidates_.end(); ++it) {
+    delete *it;
+  }
+}
+
+bool JsepCandidateCollection::HasCandidate(
+    const IceCandidateInterface* candidate) const {
+  bool ret = false;
+  for (std::vector<JsepIceCandidate*>::const_iterator it = candidates_.begin();
+       it != candidates_.end(); ++it) {
+    if ((*it)->sdp_mid() == candidate->sdp_mid() &&
+        (*it)->sdp_mline_index() == candidate->sdp_mline_index() &&
+        (*it)->candidate().IsEquivalent(candidate->candidate())) {
+      ret = true;
+      break;
+    }
+  }
+  return ret;
+}
+
+size_t JsepCandidateCollection::remove(const cricket::Candidate& candidate) {
+  auto iter = std::find_if(candidates_.begin(), candidates_.end(),
+                           [candidate](JsepIceCandidate* c) {
+                             return candidate.MatchesForRemoval(c->candidate());
+                           });
+  if (iter != candidates_.end()) {
+    delete *iter;
+    candidates_.erase(iter);
+    return 1;
+  }
+  return 0;
+}
+
+}  // namespace webrtc
diff --git a/api/jsep_ice_candidate.h b/api/jsep_ice_candidate.h
new file mode 100644
index 0000000..5b22454
--- /dev/null
+++ b/api/jsep_ice_candidate.h
@@ -0,0 +1,85 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// TODO(deadbeef): Move this out of api/; it's an implementation detail and
+// shouldn't be used externally.
+
+#ifndef API_JSEP_ICE_CANDIDATE_H_
+#define API_JSEP_ICE_CANDIDATE_H_
+
+#include <stddef.h>
+#include <string>
+#include <vector>
+
+#include "api/candidate.h"
+#include "api/jsep.h"
+#include "rtc_base/constructor_magic.h"
+
+namespace webrtc {
+
+// Implementation of IceCandidateInterface.
+class JsepIceCandidate : public IceCandidateInterface {
+ public:
+  JsepIceCandidate(const std::string& sdp_mid, int sdp_mline_index);
+  JsepIceCandidate(const std::string& sdp_mid,
+                   int sdp_mline_index,
+                   const cricket::Candidate& candidate);
+  ~JsepIceCandidate() override;
+  // |err| may be null.
+  bool Initialize(const std::string& sdp, SdpParseError* err);
+  void SetCandidate(const cricket::Candidate& candidate) {
+    candidate_ = candidate;
+  }
+
+  std::string sdp_mid() const override;
+  int sdp_mline_index() const override;
+  const cricket::Candidate& candidate() const override;
+
+  std::string server_url() const override;
+
+  bool ToString(std::string* out) const override;
+
+ private:
+  std::string sdp_mid_;
+  int sdp_mline_index_;
+  cricket::Candidate candidate_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(JsepIceCandidate);
+};
+
+// Implementation of IceCandidateCollection which stores JsepIceCandidates.
+class JsepCandidateCollection : public IceCandidateCollection {
+ public:
+  JsepCandidateCollection();
+  // Move constructor is defined so that a vector of JsepCandidateCollections
+  // can be resized.
+  JsepCandidateCollection(JsepCandidateCollection&& o);
+  ~JsepCandidateCollection() override;
+  size_t count() const override;
+  bool HasCandidate(const IceCandidateInterface* candidate) const override;
+  // Adds and takes ownership of the JsepIceCandidate.
+  // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is
+  // more clear.
+  virtual void add(JsepIceCandidate* candidate);
+  const IceCandidateInterface* at(size_t index) const override;
+  // Removes the candidate that has a matching address and protocol.
+  //
+  // Returns the number of candidates that were removed.
+  size_t remove(const cricket::Candidate& candidate);
+
+ private:
+  std::vector<JsepIceCandidate*> candidates_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(JsepCandidateCollection);
+};
+
+}  // namespace webrtc
+
+#endif  // API_JSEP_ICE_CANDIDATE_H_
diff --git a/api/jsep_session_description.h b/api/jsep_session_description.h
new file mode 100644
index 0000000..75ae0cd
--- /dev/null
+++ b/api/jsep_session_description.h
@@ -0,0 +1,91 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// TODO(deadbeef): Move this out of api/; it's an implementation detail and
+// shouldn't be used externally.
+
+#ifndef API_JSEP_SESSION_DESCRIPTION_H_
+#define API_JSEP_SESSION_DESCRIPTION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/candidate.h"
+#include "api/jsep.h"
+#include "api/jsep_ice_candidate.h"
+#include "rtc_base/constructor_magic.h"
+
+namespace cricket {
+class SessionDescription;
+}
+
+namespace webrtc {
+
+// Implementation of SessionDescriptionInterface.
+class JsepSessionDescription : public SessionDescriptionInterface {
+ public:
+  explicit JsepSessionDescription(SdpType type);
+  // TODO(steveanton): Remove this once callers have switched to SdpType.
+  explicit JsepSessionDescription(const std::string& type);
+  JsepSessionDescription(
+      SdpType type,
+      std::unique_ptr<cricket::SessionDescription> description,
+      absl::string_view session_id,
+      absl::string_view session_version);
+  virtual ~JsepSessionDescription();
+
+  // Takes ownership of |description|.
+  // TODO(deadbeef): Make this use an std::unique_ptr<>, so ownership logic is
+  // more clear.
+  bool Initialize(cricket::SessionDescription* description,
+                  const std::string& session_id,
+                  const std::string& session_version);
+
+  virtual cricket::SessionDescription* description() {
+    return description_.get();
+  }
+  virtual const cricket::SessionDescription* description() const {
+    return description_.get();
+  }
+  virtual std::string session_id() const { return session_id_; }
+  virtual std::string session_version() const { return session_version_; }
+  virtual SdpType GetType() const { return type_; }
+  virtual std::string type() const { return SdpTypeToString(type_); }
+  // Allows changing the type. Used for testing.
+  virtual bool AddCandidate(const IceCandidateInterface* candidate);
+  virtual size_t RemoveCandidates(
+      const std::vector<cricket::Candidate>& candidates);
+  virtual size_t number_of_mediasections() const;
+  virtual const IceCandidateCollection* candidates(
+      size_t mediasection_index) const;
+  virtual bool ToString(std::string* out) const;
+
+  static const int kDefaultVideoCodecId;
+  static const char kDefaultVideoCodecName[];
+
+ private:
+  std::unique_ptr<cricket::SessionDescription> description_;
+  std::string session_id_;
+  std::string session_version_;
+  SdpType type_;
+  std::vector<JsepCandidateCollection> candidate_collection_;
+
+  bool GetMediasectionIndex(const IceCandidateInterface* candidate,
+                            size_t* index);
+  int GetMediasectionIndex(const cricket::Candidate& candidate);
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(JsepSessionDescription);
+};
+
+}  // namespace webrtc
+
+#endif  // API_JSEP_SESSION_DESCRIPTION_H_
diff --git a/api/media_stream_interface.cc b/api/media_stream_interface.cc
new file mode 100644
index 0000000..cf994cb
--- /dev/null
+++ b/api/media_stream_interface.cc
@@ -0,0 +1,39 @@
+/*
+ *  Copyright 2017 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/media_stream_interface.h"
+
+namespace webrtc {
+
+const char MediaStreamTrackInterface::kVideoKind[] = "video";
+const char MediaStreamTrackInterface::kAudioKind[] = "audio";
+
+VideoTrackInterface::ContentHint VideoTrackInterface::content_hint() const {
+  return ContentHint::kNone;
+}
+
+bool AudioTrackInterface::GetSignalLevel(int* level) {
+  return false;
+}
+
+rtc::scoped_refptr<AudioProcessorInterface>
+AudioTrackInterface::GetAudioProcessor() {
+  return nullptr;
+}
+
+const cricket::AudioOptions AudioSourceInterface::options() const {
+  return {};
+}
+
+double MediaSourceInterface::GetLatency() const {
+  return 0.0;
+}
+
+}  // namespace webrtc
diff --git a/api/media_stream_interface.h b/api/media_stream_interface.h
new file mode 100644
index 0000000..1249b85
--- /dev/null
+++ b/api/media_stream_interface.h
@@ -0,0 +1,304 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// This file contains interfaces for MediaStream, MediaTrack and MediaSource.
+// These interfaces are used for implementing MediaStream and MediaTrack as
+// defined in http://dev.w3.org/2011/webrtc/editor/webrtc.html#stream-api. These
+// interfaces must be used only with PeerConnection. PeerConnectionManager
+// interface provides the factory methods to create MediaStream and MediaTracks.
+
+#ifndef API_MEDIA_STREAM_INTERFACE_H_
+#define API_MEDIA_STREAM_INTERFACE_H_
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/audio_options.h"
+#include "api/scoped_refptr.h"
+#include "api/video/video_frame.h"
+#include "api/video/video_sink_interface.h"
+#include "api/video/video_source_interface.h"
+#include "modules/audio_processing/include/audio_processing_statistics.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// Generic observer interface.
+class ObserverInterface {
+ public:
+  virtual void OnChanged() = 0;
+
+ protected:
+  virtual ~ObserverInterface() {}
+};
+
+class NotifierInterface {
+ public:
+  virtual void RegisterObserver(ObserverInterface* observer) = 0;
+  virtual void UnregisterObserver(ObserverInterface* observer) = 0;
+
+  virtual ~NotifierInterface() {}
+};
+
+// Base class for sources. A MediaStreamTrack has an underlying source that
+// provides media. A source can be shared by multiple tracks.
+class MediaSourceInterface : public rtc::RefCountInterface,
+                             public NotifierInterface {
+ public:
+  enum SourceState { kInitializing, kLive, kEnded, kMuted };
+
+  virtual SourceState state() const = 0;
+
+  virtual bool remote() const = 0;
+
+  // Sets the minimum latency of the remote source until audio playout. Actual
+  // observered latency may differ depending on the source. |latency| is in the
+  // range of [0.0, 10.0] seconds.
+  // TODO(kuddai) make pure virtual once not only remote tracks support latency.
+  virtual void SetLatency(double latency) {}
+  virtual double GetLatency() const;
+
+ protected:
+  ~MediaSourceInterface() override = default;
+};
+
+// C++ version of MediaStreamTrack.
+// See: https://www.w3.org/TR/mediacapture-streams/#mediastreamtrack
+class MediaStreamTrackInterface : public rtc::RefCountInterface,
+                                  public NotifierInterface {
+ public:
+  enum TrackState {
+    kLive,
+    kEnded,
+  };
+
+  static const char kAudioKind[];
+  static const char kVideoKind[];
+
+  // The kind() method must return kAudioKind only if the object is a
+  // subclass of AudioTrackInterface, and kVideoKind only if the
+  // object is a subclass of VideoTrackInterface. It is typically used
+  // to protect a static_cast<> to the corresponding subclass.
+  virtual std::string kind() const = 0;
+
+  // Track identifier.
+  virtual std::string id() const = 0;
+
+  // A disabled track will produce silence (if audio) or black frames (if
+  // video). Can be disabled and re-enabled.
+  virtual bool enabled() const = 0;
+  virtual bool set_enabled(bool enable) = 0;
+
+  // Live or ended. A track will never be live again after becoming ended.
+  virtual TrackState state() const = 0;
+
+ protected:
+  ~MediaStreamTrackInterface() override = default;
+};
+
+// VideoTrackSourceInterface is a reference counted source used for
+// VideoTracks. The same source can be used by multiple VideoTracks.
+// VideoTrackSourceInterface is designed to be invoked on the signaling thread
+// except for rtc::VideoSourceInterface<VideoFrame> methods that will be invoked
+// on the worker thread via a VideoTrack. A custom implementation of a source
+// can inherit AdaptedVideoTrackSource instead of directly implementing this
+// interface.
+class VideoTrackSourceInterface : public MediaSourceInterface,
+                                  public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+  struct Stats {
+    // Original size of captured frame, before video adaptation.
+    int input_width;
+    int input_height;
+  };
+
+  // Indicates that parameters suitable for screencasts should be automatically
+  // applied to RtpSenders.
+  // TODO(perkj): Remove these once all known applications have moved to
+  // explicitly setting suitable parameters for screencasts and don't need this
+  // implicit behavior.
+  virtual bool is_screencast() const = 0;
+
+  // Indicates that the encoder should denoise video before encoding it.
+  // If it is not set, the default configuration is used which is different
+  // depending on video codec.
+  // TODO(perkj): Remove this once denoising is done by the source, and not by
+  // the encoder.
+  virtual absl::optional<bool> needs_denoising() const = 0;
+
+  // Returns false if no stats are available, e.g, for a remote source, or a
+  // source which has not seen its first frame yet.
+  //
+  // Implementation should avoid blocking.
+  virtual bool GetStats(Stats* stats) = 0;
+
+ protected:
+  ~VideoTrackSourceInterface() override = default;
+};
+
+// VideoTrackInterface is designed to be invoked on the signaling thread except
+// for rtc::VideoSourceInterface<VideoFrame> methods that must be invoked
+// on the worker thread.
+// PeerConnectionFactory::CreateVideoTrack can be used for creating a VideoTrack
+// that ensures thread safety and that all methods are called on the right
+// thread.
+class VideoTrackInterface : public MediaStreamTrackInterface,
+                            public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+  // Video track content hint, used to override the source is_screencast
+  // property.
+  // See https://crbug.com/653531 and https://w3c.github.io/mst-content-hint.
+  enum class ContentHint { kNone, kFluid, kDetailed, kText };
+
+  // Register a video sink for this track. Used to connect the track to the
+  // underlying video engine.
+  void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+                       const rtc::VideoSinkWants& wants) override {}
+  void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override {}
+
+  virtual VideoTrackSourceInterface* GetSource() const = 0;
+
+  virtual ContentHint content_hint() const;
+  virtual void set_content_hint(ContentHint hint) {}
+
+ protected:
+  ~VideoTrackInterface() override = default;
+};
+
+// Interface for receiving audio data from a AudioTrack.
+class AudioTrackSinkInterface {
+ public:
+  virtual void OnData(const void* audio_data,
+                      int bits_per_sample,
+                      int sample_rate,
+                      size_t number_of_channels,
+                      size_t number_of_frames) = 0;
+
+ protected:
+  virtual ~AudioTrackSinkInterface() {}
+};
+
+// AudioSourceInterface is a reference counted source used for AudioTracks.
+// The same source can be used by multiple AudioTracks.
+class AudioSourceInterface : public MediaSourceInterface {
+ public:
+  class AudioObserver {
+   public:
+    virtual void OnSetVolume(double volume) = 0;
+
+   protected:
+    virtual ~AudioObserver() {}
+  };
+
+  // TODO(deadbeef): Makes all the interfaces pure virtual after they're
+  // implemented in chromium.
+
+  // Sets the volume of the source. |volume| is in  the range of [0, 10].
+  // TODO(tommi): This method should be on the track and ideally volume should
+  // be applied in the track in a way that does not affect clones of the track.
+  virtual void SetVolume(double volume) {}
+
+  // Registers/unregisters observers to the audio source.
+  virtual void RegisterAudioObserver(AudioObserver* observer) {}
+  virtual void UnregisterAudioObserver(AudioObserver* observer) {}
+
+  // TODO(tommi): Make pure virtual.
+  virtual void AddSink(AudioTrackSinkInterface* sink) {}
+  virtual void RemoveSink(AudioTrackSinkInterface* sink) {}
+
+  // Returns options for the AudioSource.
+  // (for some of the settings this approach is broken, e.g. setting
+  // audio network adaptation on the source is the wrong layer of abstraction).
+  virtual const cricket::AudioOptions options() const;
+};
+
+// Interface of the audio processor used by the audio track to collect
+// statistics.
+class AudioProcessorInterface : public rtc::RefCountInterface {
+ public:
+  struct AudioProcessorStatistics {
+    bool typing_noise_detected = false;
+    AudioProcessingStats apm_statistics;
+  };
+
+  // Get audio processor statistics. The |has_remote_tracks| argument should be
+  // set if there are active remote tracks (this would usually be true during
+  // a call). If there are no remote tracks some of the stats will not be set by
+  // the AudioProcessor, because they only make sense if there is at least one
+  // remote track.
+  virtual AudioProcessorStatistics GetStats(bool has_remote_tracks) = 0;
+
+ protected:
+  ~AudioProcessorInterface() override = default;
+};
+
+class AudioTrackInterface : public MediaStreamTrackInterface {
+ public:
+  // TODO(deadbeef): Figure out if the following interface should be const or
+  // not.
+  virtual AudioSourceInterface* GetSource() const = 0;
+
+  // Add/Remove a sink that will receive the audio data from the track.
+  virtual void AddSink(AudioTrackSinkInterface* sink) = 0;
+  virtual void RemoveSink(AudioTrackSinkInterface* sink) = 0;
+
+  // Get the signal level from the audio track.
+  // Return true on success, otherwise false.
+  // TODO(deadbeef): Change the interface to int GetSignalLevel() and pure
+  // virtual after it's implemented in chromium.
+  virtual bool GetSignalLevel(int* level);
+
+  // Get the audio processor used by the audio track. Return null if the track
+  // does not have any processor.
+  // TODO(deadbeef): Make the interface pure virtual.
+  virtual rtc::scoped_refptr<AudioProcessorInterface> GetAudioProcessor();
+
+ protected:
+  ~AudioTrackInterface() override = default;
+};
+
+typedef std::vector<rtc::scoped_refptr<AudioTrackInterface> > AudioTrackVector;
+typedef std::vector<rtc::scoped_refptr<VideoTrackInterface> > VideoTrackVector;
+
+// C++ version of https://www.w3.org/TR/mediacapture-streams/#mediastream.
+//
+// A major difference is that remote audio/video tracks (received by a
+// PeerConnection/RtpReceiver) are not synchronized simply by adding them to
+// the same stream; a session description with the correct "a=msid" attributes
+// must be pushed down.
+//
+// Thus, this interface acts as simply a container for tracks.
+class MediaStreamInterface : public rtc::RefCountInterface,
+                             public NotifierInterface {
+ public:
+  virtual std::string id() const = 0;
+
+  virtual AudioTrackVector GetAudioTracks() = 0;
+  virtual VideoTrackVector GetVideoTracks() = 0;
+  virtual rtc::scoped_refptr<AudioTrackInterface> FindAudioTrack(
+      const std::string& track_id) = 0;
+  virtual rtc::scoped_refptr<VideoTrackInterface> FindVideoTrack(
+      const std::string& track_id) = 0;
+
+  virtual bool AddTrack(AudioTrackInterface* track) = 0;
+  virtual bool AddTrack(VideoTrackInterface* track) = 0;
+  virtual bool RemoveTrack(AudioTrackInterface* track) = 0;
+  virtual bool RemoveTrack(VideoTrackInterface* track) = 0;
+
+ protected:
+  ~MediaStreamInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_STREAM_INTERFACE_H_
diff --git a/api/media_stream_proxy.h b/api/media_stream_proxy.h
new file mode 100644
index 0000000..5169679
--- /dev/null
+++ b/api/media_stream_proxy.h
@@ -0,0 +1,44 @@
+/*
+ *  Copyright 2011 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_MEDIA_STREAM_PROXY_H_
+#define API_MEDIA_STREAM_PROXY_H_
+
+#include <string>
+
+#include "api/media_stream_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(MediaStream)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_METHOD0(AudioTrackVector, GetAudioTracks)
+PROXY_METHOD0(VideoTrackVector, GetVideoTracks)
+PROXY_METHOD1(rtc::scoped_refptr<AudioTrackInterface>,
+              FindAudioTrack,
+              const std::string&)
+PROXY_METHOD1(rtc::scoped_refptr<VideoTrackInterface>,
+              FindVideoTrack,
+              const std::string&)
+PROXY_METHOD1(bool, AddTrack, AudioTrackInterface*)
+PROXY_METHOD1(bool, AddTrack, VideoTrackInterface*)
+PROXY_METHOD1(bool, RemoveTrack, AudioTrackInterface*)
+PROXY_METHOD1(bool, RemoveTrack, VideoTrackInterface*)
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_STREAM_PROXY_H_
diff --git a/api/media_stream_track_proxy.h b/api/media_stream_track_proxy.h
new file mode 100644
index 0000000..d3dc255
--- /dev/null
+++ b/api/media_stream_track_proxy.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 2011 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.
+ */
+
+// This file includes proxy classes for tracks. The purpose is
+// to make sure tracks are only accessed from the signaling thread.
+
+#ifndef API_MEDIA_STREAM_TRACK_PROXY_H_
+#define API_MEDIA_STREAM_TRACK_PROXY_H_
+
+#include <string>
+
+#include "api/media_stream_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+
+BEGIN_SIGNALING_PROXY_MAP(AudioTrack)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(std::string, kind)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(TrackState, state)
+PROXY_CONSTMETHOD0(bool, enabled)
+PROXY_CONSTMETHOD0(AudioSourceInterface*, GetSource)
+PROXY_METHOD1(void, AddSink, AudioTrackSinkInterface*)
+PROXY_METHOD1(void, RemoveSink, AudioTrackSinkInterface*)
+PROXY_METHOD1(bool, GetSignalLevel, int*)
+PROXY_METHOD0(rtc::scoped_refptr<AudioProcessorInterface>, GetAudioProcessor)
+PROXY_METHOD1(bool, set_enabled, bool)
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+BEGIN_PROXY_MAP(VideoTrack)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(std::string, kind)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(TrackState, state)
+PROXY_CONSTMETHOD0(bool, enabled)
+PROXY_METHOD1(bool, set_enabled, bool)
+PROXY_CONSTMETHOD0(ContentHint, content_hint)
+PROXY_METHOD1(void, set_content_hint, ContentHint)
+PROXY_WORKER_METHOD2(void,
+                     AddOrUpdateSink,
+                     rtc::VideoSinkInterface<VideoFrame>*,
+                     const rtc::VideoSinkWants&)
+PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
+PROXY_CONSTMETHOD0(VideoTrackSourceInterface*, GetSource)
+
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_STREAM_TRACK_PROXY_H_
diff --git a/api/media_transport_interface.cc b/api/media_transport_interface.cc
index ef223aa..20bbe26 100644
--- a/api/media_transport_interface.cc
+++ b/api/media_transport_interface.cc
@@ -29,71 +29,9 @@
     const MediaTransportSettings&) = default;
 MediaTransportSettings::~MediaTransportSettings() = default;
 
-MediaTransportEncodedAudioFrame::~MediaTransportEncodedAudioFrame() {}
-
-MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
-    int sampling_rate_hz,
-    int starting_sample_index,
-    int samples_per_channel,
-    int sequence_number,
-    FrameType frame_type,
-    uint8_t payload_type,
-    std::vector<uint8_t> encoded_data)
-    : sampling_rate_hz_(sampling_rate_hz),
-      starting_sample_index_(starting_sample_index),
-      samples_per_channel_(samples_per_channel),
-      sequence_number_(sequence_number),
-      frame_type_(frame_type),
-      payload_type_(payload_type),
-      encoded_data_(std::move(encoded_data)) {}
-
-MediaTransportEncodedAudioFrame& MediaTransportEncodedAudioFrame::operator=(
-    const MediaTransportEncodedAudioFrame&) = default;
-
-MediaTransportEncodedAudioFrame& MediaTransportEncodedAudioFrame::operator=(
-    MediaTransportEncodedAudioFrame&&) = default;
-
-MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
-    const MediaTransportEncodedAudioFrame&) = default;
-
-MediaTransportEncodedAudioFrame::MediaTransportEncodedAudioFrame(
-    MediaTransportEncodedAudioFrame&&) = default;
-
-MediaTransportEncodedVideoFrame::~MediaTransportEncodedVideoFrame() {}
-
-MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
-    int64_t frame_id,
-    std::vector<int64_t> referenced_frame_ids,
-    VideoCodecType codec_type,
-    const webrtc::EncodedImage& encoded_image)
-    : codec_type_(codec_type),
-      encoded_image_(encoded_image),
-      frame_id_(frame_id),
-      referenced_frame_ids_(std::move(referenced_frame_ids)) {}
-
-MediaTransportEncodedVideoFrame& MediaTransportEncodedVideoFrame::operator=(
-    const MediaTransportEncodedVideoFrame&) = default;
-
-MediaTransportEncodedVideoFrame& MediaTransportEncodedVideoFrame::operator=(
-    MediaTransportEncodedVideoFrame&&) = default;
-
-MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
-    const MediaTransportEncodedVideoFrame&) = default;
-
-MediaTransportEncodedVideoFrame::MediaTransportEncodedVideoFrame(
-    MediaTransportEncodedVideoFrame&&) = default;
 
 SendDataParams::SendDataParams() = default;
-
-RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
-MediaTransportFactory::CreateMediaTransport(
-    rtc::PacketTransportInternal* packet_transport,
-    rtc::Thread* network_thread,
-    bool is_caller) {
-  MediaTransportSettings settings;
-  settings.is_caller = is_caller;
-  return CreateMediaTransport(packet_transport, network_thread, settings);
-}
+SendDataParams::SendDataParams(const SendDataParams&) = default;
 
 RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
 MediaTransportFactory::CreateMediaTransport(
@@ -103,22 +41,60 @@
   return std::unique_ptr<MediaTransportInterface>(nullptr);
 }
 
+RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
+MediaTransportFactory::CreateMediaTransport(
+    rtc::Thread* network_thread,
+    const MediaTransportSettings& settings) {
+  return std::unique_ptr<MediaTransportInterface>(nullptr);
+}
+
+std::string MediaTransportFactory::GetTransportName() const {
+  return "";
+}
+
+MediaTransportInterface::MediaTransportInterface() = default;
+MediaTransportInterface::~MediaTransportInterface() = default;
+
+absl::optional<std::string>
+MediaTransportInterface::GetTransportParametersOffer() const {
+  return absl::nullopt;
+}
+
+void MediaTransportInterface::Connect(
+    rtc::PacketTransportInternal* packet_transport) {}
+
+void MediaTransportInterface::SetKeyFrameRequestCallback(
+    MediaTransportKeyFrameRequestCallback* callback) {}
+
 absl::optional<TargetTransferRate>
 MediaTransportInterface::GetLatestTargetTransferRate() {
   return absl::nullopt;
 }
 
-void MediaTransportInterface::SetNetworkChangeCallback(
+void MediaTransportInterface::AddNetworkChangeCallback(
     MediaTransportNetworkChangeCallback* callback) {}
 
-void MediaTransportInterface::RemoveTargetTransferRateObserver(
-    webrtc::TargetTransferRateObserver* observer) {}
+void MediaTransportInterface::RemoveNetworkChangeCallback(
+    MediaTransportNetworkChangeCallback* callback) {}
+
+void MediaTransportInterface::SetFirstAudioPacketReceivedObserver(
+    AudioPacketReceivedObserver* observer) {}
 
 void MediaTransportInterface::AddTargetTransferRateObserver(
-    webrtc::TargetTransferRateObserver* observer) {}
+    TargetTransferRateObserver* observer) {}
+void MediaTransportInterface::RemoveTargetTransferRateObserver(
+    TargetTransferRateObserver* observer) {}
+
+void MediaTransportInterface::AddRttObserver(
+    MediaTransportRttObserver* observer) {}
+void MediaTransportInterface::RemoveRttObserver(
+    MediaTransportRttObserver* observer) {}
 
 size_t MediaTransportInterface::GetAudioPacketOverhead() const {
   return 0;
 }
 
+void MediaTransportInterface::SetAllocatedBitrateLimits(
+    const MediaTransportAllocatedBitrateLimits& limits) {}
+
 }  // namespace webrtc
diff --git a/api/media_transport_interface.h b/api/media_transport_interface.h
index b10dd63..d333bec 100644
--- a/api/media_transport_interface.h
+++ b/api/media_transport_interface.h
@@ -21,14 +21,15 @@
 #include <memory>
 #include <string>
 #include <utility>
-#include <vector>
 
 #include "absl/types/optional.h"
 #include "api/array_view.h"
-#include "api/rtcerror.h"
-#include "api/video/encoded_image.h"
-#include "rtc_base/copyonwritebuffer.h"
-#include "rtc_base/networkroute.h"
+#include "api/rtc_error.h"
+#include "api/transport/media/audio_transport.h"
+#include "api/transport/media/video_transport.h"
+#include "api/units/data_rate.h"
+#include "rtc_base/copy_on_write_buffer.h"
+#include "rtc_base/network_route.h"
 
 namespace rtc {
 class PacketTransportInternal;
@@ -37,6 +38,23 @@
 
 namespace webrtc {
 
+class RtcEventLog;
+
+class AudioPacketReceivedObserver {
+ public:
+  virtual ~AudioPacketReceivedObserver() = default;
+
+  // Invoked for the first received audio packet on a given channel id.
+  // It will be invoked once for each channel id.
+  virtual void OnFirstAudioPacketReceived(int64_t channel_id) = 0;
+};
+
+struct MediaTransportAllocatedBitrateLimits {
+  DataRate min_pacing_rate = DataRate::Zero();
+  DataRate max_padding_bitrate = DataRate::Zero();
+  DataRate max_total_allocated_bitrate = DataRate::Zero();
+};
+
 // A collection of settings for creation of media transport.
 struct MediaTransportSettings final {
   MediaTransportSettings();
@@ -52,91 +70,15 @@
   // TODO(bugs.webrtc.org/9944): This should become zero buffer in the distant
   // future.
   absl::optional<std::string> pre_shared_key;
-};
 
-// Represents encoded audio frame in any encoding (type of encoding is opaque).
-// To avoid copying of encoded data use move semantics when passing by value.
-class MediaTransportEncodedAudioFrame final {
- public:
-  enum class FrameType {
-    // Normal audio frame (equivalent to webrtc::kAudioFrameSpeech).
-    kSpeech,
+  // If present, this is a config passed from the caller to the answerer in the
+  // offer. Each media transport knows how to understand its own parameters.
+  absl::optional<std::string> remote_transport_parameters;
 
-    // DTX frame (equivalent to webrtc::kAudioFrameCN).
-    // DTX frame (equivalent to webrtc::kAudioFrameCN).
-    kDiscontinuousTransmission,
-    // TODO(nisse): Mis-spelled version, update users, then delete.
-    kDiscountinuousTransmission = kDiscontinuousTransmission,
-  };
-
-  MediaTransportEncodedAudioFrame(
-      // Audio sampling rate, for example 48000.
-      int sampling_rate_hz,
-
-      // Starting sample index of the frame, i.e. how many audio samples were
-      // before this frame since the beginning of the call or beginning of time
-      // in one channel (the starting point should not matter for NetEq). In
-      // WebRTC it is used as a timestamp of the frame.
-      // TODO(sukhanov): Starting_sample_index is currently adjusted on the
-      // receiver side in RTP path. Non-RTP implementations should preserve it.
-      // For NetEq initial offset should not matter so we should consider fixing
-      // RTP path.
-      int starting_sample_index,
-
-      // Number of audio samples in audio frame in 1 channel.
-      int samples_per_channel,
-
-      // Sequence number of the frame in the order sent, it is currently
-      // required by NetEq, but we can fix NetEq, because starting_sample_index
-      // should be enough.
-      int sequence_number,
-
-      // If audio frame is a speech or discontinued transmission.
-      FrameType frame_type,
-
-      // Opaque payload type. In RTP codepath payload type is stored in RTP
-      // header. In other implementations it should be simply passed through the
-      // wire -- it's needed for decoder.
-      uint8_t payload_type,
-
-      // Vector with opaque encoded data.
-      std::vector<uint8_t> encoded_data);
-
-  ~MediaTransportEncodedAudioFrame();
-  MediaTransportEncodedAudioFrame(const MediaTransportEncodedAudioFrame&);
-  MediaTransportEncodedAudioFrame& operator=(
-      const MediaTransportEncodedAudioFrame& other);
-  MediaTransportEncodedAudioFrame& operator=(
-      MediaTransportEncodedAudioFrame&& other);
-  MediaTransportEncodedAudioFrame(MediaTransportEncodedAudioFrame&&);
-
-  // Getters.
-  int sampling_rate_hz() const { return sampling_rate_hz_; }
-  int starting_sample_index() const { return starting_sample_index_; }
-  int samples_per_channel() const { return samples_per_channel_; }
-  int sequence_number() const { return sequence_number_; }
-
-  uint8_t payload_type() const { return payload_type_; }
-  FrameType frame_type() const { return frame_type_; }
-
-  rtc::ArrayView<const uint8_t> encoded_data() const { return encoded_data_; }
-
- private:
-  int sampling_rate_hz_;
-  int starting_sample_index_;
-  int samples_per_channel_;
-
-  // TODO(sukhanov): Refactor NetEq so we don't need sequence number.
-  // Having sample_index and samples_per_channel should be enough.
-  int sequence_number_;
-
-  FrameType frame_type_;
-
-  // TODO(sukhanov): Consider enumerating allowed encodings and store enum
-  // instead of uint payload_type.
-  uint8_t payload_type_;
-
-  std::vector<uint8_t> encoded_data_;
+  // If present, provides the event log that media transport should use.
+  // Media transport does not own it. The lifetime of |event_log| will exceed
+  // the lifetime of the instance of MediaTransportInterface instance.
+  RtcEventLog* event_log = nullptr;
 };
 
 // Callback to notify about network route changes.
@@ -149,79 +91,6 @@
       const rtc::NetworkRoute& new_network_route) = 0;
 };
 
-// Interface for receiving encoded audio frames from MediaTransportInterface
-// implementations.
-class MediaTransportAudioSinkInterface {
- public:
-  virtual ~MediaTransportAudioSinkInterface() = default;
-
-  // Called when new encoded audio frame is received.
-  virtual void OnData(uint64_t channel_id,
-                      MediaTransportEncodedAudioFrame frame) = 0;
-};
-
-// Represents encoded video frame, along with the codec information.
-class MediaTransportEncodedVideoFrame final {
- public:
-  MediaTransportEncodedVideoFrame(int64_t frame_id,
-                                  std::vector<int64_t> referenced_frame_ids,
-                                  VideoCodecType codec_type,
-                                  const webrtc::EncodedImage& encoded_image);
-  ~MediaTransportEncodedVideoFrame();
-  MediaTransportEncodedVideoFrame(const MediaTransportEncodedVideoFrame&);
-  MediaTransportEncodedVideoFrame& operator=(
-      const MediaTransportEncodedVideoFrame& other);
-  MediaTransportEncodedVideoFrame& operator=(
-      MediaTransportEncodedVideoFrame&& other);
-  MediaTransportEncodedVideoFrame(MediaTransportEncodedVideoFrame&&);
-
-  VideoCodecType codec_type() const { return codec_type_; }
-  const webrtc::EncodedImage& encoded_image() const { return encoded_image_; }
-
-  int64_t frame_id() const { return frame_id_; }
-  const std::vector<int64_t>& referenced_frame_ids() const {
-    return referenced_frame_ids_;
-  }
-
- private:
-  VideoCodecType codec_type_;
-
-  // The buffer is not owned by the encoded image by default. On the sender it
-  // means that it will need to make a copy of it if it wants to deliver it
-  // asynchronously.
-  webrtc::EncodedImage encoded_image_;
-
-  // Frame id uniquely identifies a frame in a stream. It needs to be unique in
-  // a given time window (i.e. technically unique identifier for the lifetime of
-  // the connection is not needed, but you need to guarantee that remote side
-  // got rid of the previous frame_id if you plan to reuse it).
-  //
-  // It is required by a remote jitter buffer, and is the same as
-  // EncodedFrame::id::picture_id.
-  //
-  // This data must be opaque to the media transport, and media transport should
-  // itself not make any assumptions about what it is and its uniqueness.
-  int64_t frame_id_;
-
-  // A single frame might depend on other frames. This is set of identifiers on
-  // which the current frame depends.
-  std::vector<int64_t> referenced_frame_ids_;
-};
-
-// Interface for receiving encoded video frames from MediaTransportInterface
-// implementations.
-class MediaTransportVideoSinkInterface {
- public:
-  virtual ~MediaTransportVideoSinkInterface() = default;
-
-  // Called when new encoded video frame is received.
-  virtual void OnData(uint64_t channel_id,
-                      MediaTransportEncodedVideoFrame frame) = 0;
-
-  // Called when the request for keyframe is received.
-  virtual void OnKeyFrameRequested(uint64_t channel_id) = 0;
-};
-
 // State of the media transport.  Media transport begins in the pending state.
 // It transitions to writable when it is ready to send media.  It may transition
 // back to pending if the connection is blocked.  It may transition to closed at
@@ -241,6 +110,19 @@
   virtual void OnStateChanged(MediaTransportState state) = 0;
 };
 
+// Callback for RTT measurements on the receive side.
+// TODO(nisse): Related interfaces: CallStatsObserver and RtcpRttStats. It's
+// somewhat unclear what type of measurement is needed. It's used to configure
+// NACK generation and playout buffer. Either raw measurement values or recent
+// maximum would make sense for this use. Need consolidation of RTT signalling.
+class MediaTransportRttObserver {
+ public:
+  virtual ~MediaTransportRttObserver() = default;
+
+  // Invoked when a new RTT measurement is available, typically once per ACK.
+  virtual void OnRttUpdated(int64_t rtt_ms) = 0;
+};
+
 // Supported types of application data messages.
 enum class DataMessageType {
   // Application data buffer with the binary bit unset.
@@ -259,6 +141,7 @@
 // unreliable delivery.
 struct SendDataParams {
   SendDataParams();
+  SendDataParams(const SendDataParams&);
 
   DataMessageType type = DataMessageType::kText;
 
@@ -305,7 +188,29 @@
 // and receiving bandwidth estimate update from congestion control.
 class MediaTransportInterface {
  public:
-  virtual ~MediaTransportInterface() = default;
+  MediaTransportInterface();
+  virtual ~MediaTransportInterface();
+
+  // Retrieves callers config (i.e. media transport offer) that should be passed
+  // to the callee, before the call is connected. Such config is opaque to SDP
+  // (sdp just passes it through). The config is a binary blob, so SDP may
+  // choose to use base64 to serialize it (or any other approach that guarantees
+  // that the binary blob goes through). This should only be called for the
+  // caller's perspective.
+  //
+  // This may return an unset optional, which means that the given media
+  // transport is not supported / disabled and shouldn't be reported in SDP.
+  //
+  // It may also return an empty string, in which case the media transport is
+  // supported, but without any extra settings.
+  // TODO(psla): Make abstract.
+  virtual absl::optional<std::string> GetTransportParametersOffer() const;
+
+  // Connect the media transport to the ICE transport.
+  // The implementation must be able to ignore incoming packets that don't
+  // belong to it.
+  // TODO(psla): Make abstract.
+  virtual void Connect(rtc::PacketTransportInternal* packet_transport);
 
   // Start asynchronous send of audio frame. The status returned by this method
   // only pertains to the synchronous operations (e.g.
@@ -321,6 +226,10 @@
       uint64_t channel_id,
       const MediaTransportEncodedVideoFrame& frame) = 0;
 
+  // Used by video sender to be notified on key frame requests.
+  virtual void SetKeyFrameRequestCallback(
+      MediaTransportKeyFrameRequestCallback* callback);
+
   // Requests a keyframe for the particular channel (stream). The caller should
   // check that the keyframe is not present in a jitter buffer already (i.e.
   // don't request a keyframe if there is one that you will get from the jitter
@@ -341,12 +250,27 @@
   // A newly registered observer will be called back with the latest recorded
   // target rate, if available.
   virtual void AddTargetTransferRateObserver(
-      webrtc::TargetTransferRateObserver* observer);
+      TargetTransferRateObserver* observer);
 
   // Removes an existing |observer| from observers. If observer was never
   // registered, an error is logged and method does nothing.
   virtual void RemoveTargetTransferRateObserver(
-      webrtc::TargetTransferRateObserver* observer);
+      TargetTransferRateObserver* observer);
+
+  // Sets audio packets observer, which gets informed about incoming audio
+  // packets. Before destruction, the observer must be unregistered by setting
+  // nullptr.
+  //
+  // This method may be temporary, when the multiplexer is implemented (or
+  // multiplexer may use it to demultiplex channel ids).
+  virtual void SetFirstAudioPacketReceivedObserver(
+      AudioPacketReceivedObserver* observer);
+
+  // Intended for receive side. AddRttObserver registers an observer to be
+  // called for each RTT measurement, typically once per ACK. Before media
+  // transport is destructed the observer must be unregistered.
+  virtual void AddRttObserver(MediaTransportRttObserver* observer);
+  virtual void RemoveRttObserver(MediaTransportRttObserver* observer);
 
   // Returns the last known target transfer rate as reported to the above
   // observers.
@@ -358,12 +282,13 @@
   // might not be a very accurate number.
   virtual size_t GetAudioPacketOverhead() const;
 
-  // Sets an observer for network change events. If the network route is already
-  // established when the callback is set, |callback| will be called immediately
-  // with the current network route.
-  // Before media transport is destroyed, the callback must be unregistered by
-  // setting it to nullptr.
-  virtual void SetNetworkChangeCallback(
+  // Registers an observer for network change events. If the network route is
+  // already established when the callback is added, |callback| will be called
+  // immediately with the current network route. Before media transport is
+  // destroyed, the callback must be removed.
+  virtual void AddNetworkChangeCallback(
+      MediaTransportNetworkChangeCallback* callback);
+  virtual void RemoveNetworkChangeCallback(
       MediaTransportNetworkChangeCallback* callback);
 
   // Sets a state observer callback. Before media transport is destroyed, the
@@ -373,6 +298,15 @@
   virtual void SetMediaTransportStateCallback(
       MediaTransportStateCallback* callback) = 0;
 
+  // Updates allocation limits.
+  // TODO(psla): Make abstract when downstream implementation implement it.
+  virtual void SetAllocatedBitrateLimits(
+      const MediaTransportAllocatedBitrateLimits& limits);
+
+  // Opens a data |channel_id| for sending.  May return an error if the
+  // specified |channel_id| is unusable.  Must be called before |SendData|.
+  virtual RTCError OpenChannel(int channel_id) = 0;
+
   // Sends a data buffer to the remote endpoint using the given send parameters.
   // |buffer| may not be larger than 256 KiB. Returns an error if the send
   // fails.
@@ -408,21 +342,28 @@
   // - Does not take ownership of packet_transport or network_thread.
   // - Does not support group calls, in 1:1 call one side must set
   //   is_caller = true and another is_caller = false.
-  // TODO(bugs.webrtc.org/9938) This constructor will be removed and replaced
-  // with the one below.
-  virtual RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
-  CreateMediaTransport(rtc::PacketTransportInternal* packet_transport,
-                       rtc::Thread* network_thread,
-                       bool is_caller);
-
-  // Creates media transport.
-  // - Does not take ownership of packet_transport or network_thread.
-  // TODO(bugs.webrtc.org/9938): remove default implementation once all children
-  // override it.
   virtual RTCErrorOr<std::unique_ptr<MediaTransportInterface>>
   CreateMediaTransport(rtc::PacketTransportInternal* packet_transport,
                        rtc::Thread* network_thread,
                        const MediaTransportSettings& settings);
+
+  // Creates a new Media Transport in a disconnected state. If the media
+  // transport for the caller is created, one can then call
+  // MediaTransportInterface::GetTransportParametersOffer on that new instance.
+  // TODO(psla): Make abstract.
+  virtual RTCErrorOr<std::unique_ptr<webrtc::MediaTransportInterface>>
+  CreateMediaTransport(rtc::Thread* network_thread,
+                       const MediaTransportSettings& settings);
+
+  // Gets a transport name which is supported by the implementation.
+  // Different factories should return different transport names, and at runtime
+  // it will be checked that different names were used.
+  // For example, "rtp" or "generic" may be returned by two different
+  // implementations.
+  // The value returned by this method must never change in the lifetime of the
+  // factory.
+  // TODO(psla): Make abstract.
+  virtual std::string GetTransportName() const;
 };
 
 }  // namespace webrtc
diff --git a/api/media_types.cc b/api/media_types.cc
new file mode 100644
index 0000000..3359f1d
--- /dev/null
+++ b/api/media_types.cc
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2016 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/media_types.h"
+
+#include "api/media_stream_interface.h"
+#include "rtc_base/checks.h"
+
+namespace {
+static const char* kMediaTypeData = "data";
+}  // namespace
+
+namespace cricket {
+
+std::string MediaTypeToString(MediaType type) {
+  switch (type) {
+    case MEDIA_TYPE_AUDIO:
+      return webrtc::MediaStreamTrackInterface::kAudioKind;
+    case MEDIA_TYPE_VIDEO:
+      return webrtc::MediaStreamTrackInterface::kVideoKind;
+    case MEDIA_TYPE_DATA:
+      return kMediaTypeData;
+  }
+  FATAL();
+  // Not reachable; avoids compile warning.
+  return "";
+}
+
+MediaType MediaTypeFromString(const std::string& type_str) {
+  if (type_str == webrtc::MediaStreamTrackInterface::kAudioKind) {
+    return MEDIA_TYPE_AUDIO;
+  } else if (type_str == webrtc::MediaStreamTrackInterface::kVideoKind) {
+    return MEDIA_TYPE_VIDEO;
+  } else if (type_str == kMediaTypeData) {
+    return MEDIA_TYPE_DATA;
+  }
+  FATAL();
+  // Not reachable; avoids compile warning.
+  return static_cast<MediaType>(-1);
+}
+
+}  // namespace cricket
diff --git a/api/media_types.h b/api/media_types.h
new file mode 100644
index 0000000..64e2ebc
--- /dev/null
+++ b/api/media_types.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright 2016 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_MEDIA_TYPES_H_
+#define API_MEDIA_TYPES_H_
+
+#include <string>
+
+// The cricket and webrtc have separate definitions for what a media type is.
+// They're not compatible. Watch out for this.
+
+namespace cricket {
+
+enum MediaType { MEDIA_TYPE_AUDIO, MEDIA_TYPE_VIDEO, MEDIA_TYPE_DATA };
+
+std::string MediaTypeToString(MediaType type);
+// Aborts on invalid string. Only expected to be used on strings that are
+// guaranteed to be valid, such as MediaStreamTrackInterface::kind().
+MediaType MediaTypeFromString(const std::string& type_str);
+
+}  // namespace cricket
+
+namespace webrtc {
+
+enum class MediaType { ANY, AUDIO, VIDEO, DATA };
+
+}  // namespace webrtc
+
+#endif  // API_MEDIA_TYPES_H_
diff --git a/api/notifier.h b/api/notifier.h
index e5c61c9..c03b104 100644
--- a/api/notifier.h
+++ b/api/notifier.h
@@ -13,7 +13,7 @@
 
 #include <list>
 
-#include "api/mediastreaminterface.h"
+#include "api/media_stream_interface.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
diff --git a/api/peer_connection_factory_proxy.h b/api/peer_connection_factory_proxy.h
new file mode 100644
index 0000000..620f1ca
--- /dev/null
+++ b/api/peer_connection_factory_proxy.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright 2014 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_PEER_CONNECTION_FACTORY_PROXY_H_
+#define API_PEER_CONNECTION_FACTORY_PROXY_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "api/peer_connection_interface.h"
+#include "api/proxy.h"
+#include "rtc_base/bind.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_METHOD1(void, SetOptions, const Options&)
+PROXY_METHOD4(rtc::scoped_refptr<PeerConnectionInterface>,
+              CreatePeerConnection,
+              const PeerConnectionInterface::RTCConfiguration&,
+              std::unique_ptr<cricket::PortAllocator>,
+              std::unique_ptr<rtc::RTCCertificateGeneratorInterface>,
+              PeerConnectionObserver*)
+PROXY_METHOD2(rtc::scoped_refptr<PeerConnectionInterface>,
+              CreatePeerConnection,
+              const PeerConnectionInterface::RTCConfiguration&,
+              PeerConnectionDependencies)
+PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
+                   GetRtpSenderCapabilities,
+                   cricket::MediaType)
+PROXY_CONSTMETHOD1(webrtc::RtpCapabilities,
+                   GetRtpReceiverCapabilities,
+                   cricket::MediaType)
+PROXY_METHOD1(rtc::scoped_refptr<MediaStreamInterface>,
+              CreateLocalMediaStream,
+              const std::string&)
+PROXY_METHOD1(rtc::scoped_refptr<AudioSourceInterface>,
+              CreateAudioSource,
+              const cricket::AudioOptions&)
+PROXY_METHOD2(rtc::scoped_refptr<VideoTrackInterface>,
+              CreateVideoTrack,
+              const std::string&,
+              VideoTrackSourceInterface*)
+PROXY_METHOD2(rtc::scoped_refptr<AudioTrackInterface>,
+              CreateAudioTrack,
+              const std::string&,
+              AudioSourceInterface*)
+PROXY_METHOD2(bool, StartAecDump, rtc::PlatformFile, int64_t)
+PROXY_METHOD0(void, StopAecDump)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_PEER_CONNECTION_FACTORY_PROXY_H_
diff --git a/api/peer_connection_interface.cc b/api/peer_connection_interface.cc
new file mode 100644
index 0000000..244ee73
--- /dev/null
+++ b/api/peer_connection_interface.cc
@@ -0,0 +1,245 @@
+/*
+ *  Copyright 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/peer_connection_interface.h"
+#include "api/dtls_transport_interface.h"
+#include "api/sctp_transport_interface.h"
+
+namespace webrtc {
+
+PeerConnectionInterface::IceServer::IceServer() = default;
+PeerConnectionInterface::IceServer::IceServer(const IceServer& rhs) = default;
+PeerConnectionInterface::IceServer::~IceServer() = default;
+
+PeerConnectionInterface::RTCConfiguration::RTCConfiguration() = default;
+
+PeerConnectionInterface::RTCConfiguration::RTCConfiguration(
+    const RTCConfiguration& rhs) = default;
+
+PeerConnectionInterface::RTCConfiguration::RTCConfiguration(
+    RTCConfigurationType type) {
+  if (type == RTCConfigurationType::kAggressive) {
+    // These parameters are also defined in Java and IOS configurations,
+    // so their values may be overwritten by the Java or IOS configuration.
+    bundle_policy = kBundlePolicyMaxBundle;
+    rtcp_mux_policy = kRtcpMuxPolicyRequire;
+    ice_connection_receiving_timeout = kAggressiveIceConnectionReceivingTimeout;
+
+    // These parameters are not defined in Java or IOS configuration,
+    // so their values will not be overwritten.
+    enable_ice_renomination = true;
+    redetermine_role_on_ice_restart = false;
+  }
+}
+
+PeerConnectionInterface::RTCConfiguration::~RTCConfiguration() = default;
+
+RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>
+PeerConnectionInterface::AddTrack(
+    rtc::scoped_refptr<MediaStreamTrackInterface> track,
+    const std::vector<std::string>& stream_ids) {
+  return RTCError(RTCErrorType::UNSUPPORTED_OPERATION, "Not implemented");
+}
+
+bool PeerConnectionInterface::RemoveTrack(RtpSenderInterface* sender) {
+  return RemoveTrackNew(sender).ok();
+}
+
+RTCError PeerConnectionInterface::RemoveTrackNew(
+    rtc::scoped_refptr<RtpSenderInterface> sender) {
+  return RTCError(RemoveTrack(sender) ? RTCErrorType::NONE
+                                      : RTCErrorType::INTERNAL_ERROR);
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(
+    rtc::scoped_refptr<MediaStreamTrackInterface> track) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(
+    rtc::scoped_refptr<MediaStreamTrackInterface> track,
+    const RtpTransceiverInit& init) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(cricket::MediaType media_type) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::AddTransceiver(cricket::MediaType media_type,
+                                        const RtpTransceiverInit& init) {
+  return RTCError(RTCErrorType::INTERNAL_ERROR, "not implemented");
+}
+
+rtc::scoped_refptr<RtpSenderInterface> PeerConnectionInterface::CreateSender(
+    const std::string& kind,
+    const std::string& stream_id) {
+  return rtc::scoped_refptr<RtpSenderInterface>();
+}
+
+std::vector<rtc::scoped_refptr<RtpSenderInterface>>
+PeerConnectionInterface::GetSenders() const {
+  return std::vector<rtc::scoped_refptr<RtpSenderInterface>>();
+}
+
+std::vector<rtc::scoped_refptr<RtpReceiverInterface>>
+PeerConnectionInterface::GetReceivers() const {
+  return std::vector<rtc::scoped_refptr<RtpReceiverInterface>>();
+}
+
+std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
+PeerConnectionInterface::GetTransceivers() const {
+  return std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>();
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::current_local_description() const {
+  return nullptr;
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::current_remote_description() const {
+  return nullptr;
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::pending_local_description() const {
+  return nullptr;
+}
+
+const SessionDescriptionInterface*
+PeerConnectionInterface::pending_remote_description() const {
+  return nullptr;
+}
+
+PeerConnectionInterface::RTCConfiguration
+PeerConnectionInterface::GetConfiguration() {
+  return PeerConnectionInterface::RTCConfiguration();
+}
+
+bool PeerConnectionInterface::SetConfiguration(
+    const PeerConnectionInterface::RTCConfiguration& config,
+    RTCError* error) {
+  return false;
+}
+
+bool PeerConnectionInterface::SetConfiguration(
+    const PeerConnectionInterface::RTCConfiguration& config) {
+  return false;
+}
+
+bool PeerConnectionInterface::RemoveIceCandidates(
+    const std::vector<cricket::Candidate>& candidates) {
+  return false;
+}
+
+RTCError PeerConnectionInterface::SetBitrate(const BitrateSettings& bitrate) {
+  BitrateParameters bitrate_parameters;
+  bitrate_parameters.min_bitrate_bps = bitrate.min_bitrate_bps;
+  bitrate_parameters.current_bitrate_bps = bitrate.start_bitrate_bps;
+  bitrate_parameters.max_bitrate_bps = bitrate.max_bitrate_bps;
+  return SetBitrate(bitrate_parameters);
+}
+
+RTCError PeerConnectionInterface::SetBitrate(
+    const BitrateParameters& bitrate_parameters) {
+  BitrateSettings bitrate;
+  bitrate.min_bitrate_bps = bitrate_parameters.min_bitrate_bps;
+  bitrate.start_bitrate_bps = bitrate_parameters.current_bitrate_bps;
+  bitrate.max_bitrate_bps = bitrate_parameters.max_bitrate_bps;
+  return SetBitrate(bitrate);
+}
+
+PeerConnectionInterface::IceConnectionState
+PeerConnectionInterface::standardized_ice_connection_state() {
+  return PeerConnectionInterface::IceConnectionState::kIceConnectionFailed;
+}
+
+PeerConnectionInterface::PeerConnectionState
+PeerConnectionInterface::peer_connection_state() {
+  return PeerConnectionInterface::PeerConnectionState::kFailed;
+}
+
+bool PeerConnectionInterface::StartRtcEventLog(rtc::PlatformFile file,
+                                               int64_t max_size_bytes) {
+  return false;
+}
+
+bool PeerConnectionInterface::StartRtcEventLog(
+    std::unique_ptr<RtcEventLogOutput> output,
+    int64_t output_period_ms) {
+  return false;
+}
+
+rtc::scoped_refptr<DtlsTransportInterface>
+PeerConnectionInterface::LookupDtlsTransportByMid(const std::string& mid) {
+  RTC_NOTREACHED();
+  return nullptr;
+}
+
+rtc::scoped_refptr<SctpTransportInterface>
+PeerConnectionInterface::GetSctpTransport() const {
+  RTC_NOTREACHED();
+  return nullptr;
+}
+
+PeerConnectionInterface::BitrateParameters::BitrateParameters() = default;
+
+PeerConnectionInterface::BitrateParameters::~BitrateParameters() = default;
+
+PeerConnectionDependencies::PeerConnectionDependencies(
+    PeerConnectionObserver* observer_in)
+    : observer(observer_in) {}
+
+PeerConnectionDependencies::PeerConnectionDependencies(
+    PeerConnectionDependencies&&) = default;
+
+PeerConnectionDependencies::~PeerConnectionDependencies() = default;
+
+PeerConnectionFactoryDependencies::PeerConnectionFactoryDependencies() =
+    default;
+
+PeerConnectionFactoryDependencies::PeerConnectionFactoryDependencies(
+    PeerConnectionFactoryDependencies&&) = default;
+
+PeerConnectionFactoryDependencies::~PeerConnectionFactoryDependencies() =
+    default;
+
+rtc::scoped_refptr<PeerConnectionInterface>
+PeerConnectionFactoryInterface::CreatePeerConnection(
+    const PeerConnectionInterface::RTCConfiguration& configuration,
+    std::unique_ptr<cricket::PortAllocator> allocator,
+    std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
+    PeerConnectionObserver* observer) {
+  return nullptr;
+}
+
+rtc::scoped_refptr<PeerConnectionInterface>
+PeerConnectionFactoryInterface::CreatePeerConnection(
+    const PeerConnectionInterface::RTCConfiguration& configuration,
+    PeerConnectionDependencies dependencies) {
+  return nullptr;
+}
+
+RtpCapabilities PeerConnectionFactoryInterface::GetRtpSenderCapabilities(
+    cricket::MediaType kind) const {
+  return {};
+}
+
+RtpCapabilities PeerConnectionFactoryInterface::GetRtpReceiverCapabilities(
+    cricket::MediaType kind) const {
+  return {};
+}
+
+}  // namespace webrtc
diff --git a/api/peer_connection_interface.h b/api/peer_connection_interface.h
new file mode 100644
index 0000000..1d7f96f
--- /dev/null
+++ b/api/peer_connection_interface.h
@@ -0,0 +1,1437 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// This file contains the PeerConnection interface as defined in
+// https://w3c.github.io/webrtc-pc/#peer-to-peer-connections
+//
+// The PeerConnectionFactory class provides factory methods to create
+// PeerConnection, MediaStream and MediaStreamTrack objects.
+//
+// The following steps are needed to setup a typical call using WebRTC:
+//
+// 1. Create a PeerConnectionFactoryInterface. Check constructors for more
+// information about input parameters.
+//
+// 2. Create a PeerConnection object. Provide a configuration struct which
+// points to STUN and/or TURN servers used to generate ICE candidates, and
+// provide an object that implements the PeerConnectionObserver interface,
+// which is used to receive callbacks from the PeerConnection.
+//
+// 3. Create local MediaStreamTracks using the PeerConnectionFactory and add
+// them to PeerConnection by calling AddTrack (or legacy method, AddStream).
+//
+// 4. Create an offer, call SetLocalDescription with it, serialize it, and send
+// it to the remote peer
+//
+// 5. Once an ICE candidate has been gathered, the PeerConnection will call the
+// observer function OnIceCandidate. The candidates must also be serialized and
+// sent to the remote peer.
+//
+// 6. Once an answer is received from the remote peer, call
+// SetRemoteDescription with the remote answer.
+//
+// 7. Once a remote candidate is received from the remote peer, provide it to
+// the PeerConnection by calling AddIceCandidate.
+//
+// The receiver of a call (assuming the application is "call"-based) can decide
+// to accept or reject the call; this decision will be taken by the application,
+// not the PeerConnection.
+//
+// If the application decides to accept the call, it should:
+//
+// 1. Create PeerConnectionFactoryInterface if it doesn't exist.
+//
+// 2. Create a new PeerConnection.
+//
+// 3. Provide the remote offer to the new PeerConnection object by calling
+// SetRemoteDescription.
+//
+// 4. Generate an answer to the remote offer by calling CreateAnswer and send it
+// back to the remote peer.
+//
+// 5. Provide the local answer to the new PeerConnection by calling
+// SetLocalDescription with the answer.
+//
+// 6. Provide the remote ICE candidates by calling AddIceCandidate.
+//
+// 7. Once a candidate has been gathered, the PeerConnection will call the
+// observer function OnIceCandidate. Send these candidates to the remote peer.
+
+#ifndef API_PEER_CONNECTION_INTERFACE_H_
+#define API_PEER_CONNECTION_INTERFACE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/async_resolver_factory.h"
+#include "api/audio/audio_mixer.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
+#include "api/audio_codecs/audio_encoder_factory.h"
+#include "api/audio_options.h"
+#include "api/call/call_factory_interface.h"
+#include "api/crypto/crypto_options.h"
+#include "api/data_channel_interface.h"
+#include "api/fec_controller.h"
+#include "api/jsep.h"
+#include "api/media_stream_interface.h"
+#include "api/media_transport_interface.h"
+#include "api/rtc_error.h"
+#include "api/rtc_event_log_output.h"
+#include "api/rtp_receiver_interface.h"
+#include "api/rtp_sender_interface.h"
+#include "api/rtp_transceiver_interface.h"
+#include "api/set_remote_description_observer_interface.h"
+#include "api/stats/rtc_stats_collector_callback.h"
+#include "api/stats_types.h"
+#include "api/transport/bitrate_settings.h"
+#include "api/transport/network_control.h"
+#include "api/turn_customizer.h"
+#include "logging/rtc_event_log/rtc_event_log_factory_interface.h"
+#include "media/base/media_config.h"
+// TODO(bugs.webrtc.org/7447): We plan to provide a way to let applications
+// inject a PacketSocketFactory and/or NetworkManager, and not expose
+// PortAllocator in the PeerConnection api.
+#include "media/base/media_engine.h"  // nogncheck
+#include "p2p/base/port_allocator.h"  // nogncheck
+// TODO(nisse): The interface for bitrate allocation strategy belongs in api/.
+#include "rtc_base/bitrate_allocation_strategy.h"
+#include "rtc_base/network.h"
+#include "rtc_base/platform_file.h"
+#include "rtc_base/rtc_certificate.h"
+#include "rtc_base/rtc_certificate_generator.h"
+#include "rtc_base/socket_address.h"
+#include "rtc_base/ssl_certificate.h"
+#include "rtc_base/ssl_stream_adapter.h"
+#include "rtc_base/system/rtc_export.h"
+
+namespace rtc {
+class SSLIdentity;
+class Thread;
+}  // namespace rtc
+
+namespace webrtc {
+class AudioDeviceModule;
+class AudioMixer;
+class AudioProcessing;
+class DtlsTransportInterface;
+class SctpTransportInterface;
+class VideoDecoderFactory;
+class VideoEncoderFactory;
+
+// MediaStream container interface.
+class StreamCollectionInterface : public rtc::RefCountInterface {
+ public:
+  // TODO(ronghuawu): Update the function names to c++ style, e.g. find -> Find.
+  virtual size_t count() = 0;
+  virtual MediaStreamInterface* at(size_t index) = 0;
+  virtual MediaStreamInterface* find(const std::string& label) = 0;
+  virtual MediaStreamTrackInterface* FindAudioTrack(const std::string& id) = 0;
+  virtual MediaStreamTrackInterface* FindVideoTrack(const std::string& id) = 0;
+
+ protected:
+  // Dtor protected as objects shouldn't be deleted via this interface.
+  ~StreamCollectionInterface() override = default;
+};
+
+class StatsObserver : public rtc::RefCountInterface {
+ public:
+  virtual void OnComplete(const StatsReports& reports) = 0;
+
+ protected:
+  ~StatsObserver() override = default;
+};
+
+enum class SdpSemantics { kPlanB, kUnifiedPlan };
+
+class PeerConnectionInterface : public rtc::RefCountInterface {
+ public:
+  // See https://w3c.github.io/webrtc-pc/#dom-rtcsignalingstate
+  enum SignalingState {
+    kStable,
+    kHaveLocalOffer,
+    kHaveLocalPrAnswer,
+    kHaveRemoteOffer,
+    kHaveRemotePrAnswer,
+    kClosed,
+  };
+
+  // See https://w3c.github.io/webrtc-pc/#dom-rtcicegatheringstate
+  enum IceGatheringState {
+    kIceGatheringNew,
+    kIceGatheringGathering,
+    kIceGatheringComplete
+  };
+
+  // See https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnectionstate
+  enum class PeerConnectionState {
+    kNew,
+    kConnecting,
+    kConnected,
+    kDisconnected,
+    kFailed,
+    kClosed,
+  };
+
+  // See https://w3c.github.io/webrtc-pc/#dom-rtciceconnectionstate
+  enum IceConnectionState {
+    kIceConnectionNew,
+    kIceConnectionChecking,
+    kIceConnectionConnected,
+    kIceConnectionCompleted,
+    kIceConnectionFailed,
+    kIceConnectionDisconnected,
+    kIceConnectionClosed,
+    kIceConnectionMax,
+  };
+
+  // TLS certificate policy.
+  enum TlsCertPolicy {
+    // For TLS based protocols, ensure the connection is secure by not
+    // circumventing certificate validation.
+    kTlsCertPolicySecure,
+    // For TLS based protocols, disregard security completely by skipping
+    // certificate validation. This is insecure and should never be used unless
+    // security is irrelevant in that particular context.
+    kTlsCertPolicyInsecureNoCheck,
+  };
+
+  struct IceServer {
+    IceServer();
+    IceServer(const IceServer&);
+    ~IceServer();
+
+    // TODO(jbauch): Remove uri when all code using it has switched to urls.
+    // List of URIs associated with this server. Valid formats are described
+    // in RFC7064 and RFC7065, and more may be added in the future. The "host"
+    // part of the URI may contain either an IP address or a hostname.
+    std::string uri;
+    std::vector<std::string> urls;
+    std::string username;
+    std::string password;
+    TlsCertPolicy tls_cert_policy = kTlsCertPolicySecure;
+    // If the URIs in |urls| only contain IP addresses, this field can be used
+    // to indicate the hostname, which may be necessary for TLS (using the SNI
+    // extension). If |urls| itself contains the hostname, this isn't
+    // necessary.
+    std::string hostname;
+    // List of protocols to be used in the TLS ALPN extension.
+    std::vector<std::string> tls_alpn_protocols;
+    // List of elliptic curves to be used in the TLS elliptic curves extension.
+    std::vector<std::string> tls_elliptic_curves;
+
+    bool operator==(const IceServer& o) const {
+      return uri == o.uri && urls == o.urls && username == o.username &&
+             password == o.password && tls_cert_policy == o.tls_cert_policy &&
+             hostname == o.hostname &&
+             tls_alpn_protocols == o.tls_alpn_protocols &&
+             tls_elliptic_curves == o.tls_elliptic_curves;
+    }
+    bool operator!=(const IceServer& o) const { return !(*this == o); }
+  };
+  typedef std::vector<IceServer> IceServers;
+
+  enum IceTransportsType {
+    // TODO(pthatcher): Rename these kTransporTypeXXX, but update
+    // Chromium at the same time.
+    kNone,
+    kRelay,
+    kNoHost,
+    kAll
+  };
+
+  // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1
+  enum BundlePolicy {
+    kBundlePolicyBalanced,
+    kBundlePolicyMaxBundle,
+    kBundlePolicyMaxCompat
+  };
+
+  // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24#section-4.1.1
+  enum RtcpMuxPolicy {
+    kRtcpMuxPolicyNegotiate,
+    kRtcpMuxPolicyRequire,
+  };
+
+  enum TcpCandidatePolicy {
+    kTcpCandidatePolicyEnabled,
+    kTcpCandidatePolicyDisabled
+  };
+
+  enum CandidateNetworkPolicy {
+    kCandidateNetworkPolicyAll,
+    kCandidateNetworkPolicyLowCost
+  };
+
+  enum ContinualGatheringPolicy { GATHER_ONCE, GATHER_CONTINUALLY };
+
+  enum class RTCConfigurationType {
+    // A configuration that is safer to use, despite not having the best
+    // performance. Currently this is the default configuration.
+    kSafe,
+    // An aggressive configuration that has better performance, although it
+    // may be riskier and may need extra support in the application.
+    kAggressive
+  };
+
+  // TODO(hbos): Change into class with private data and public getters.
+  // TODO(nisse): In particular, accessing fields directly from an
+  // application is brittle, since the organization mirrors the
+  // organization of the implementation, which isn't stable. So we
+  // need getters and setters at least for fields which applications
+  // are interested in.
+  struct RTC_EXPORT RTCConfiguration {
+    // This struct is subject to reorganization, both for naming
+    // consistency, and to group settings to match where they are used
+    // in the implementation. To do that, we need getter and setter
+    // methods for all settings which are of interest to applications,
+    // Chrome in particular.
+
+    RTCConfiguration();
+    RTCConfiguration(const RTCConfiguration&);
+    explicit RTCConfiguration(RTCConfigurationType type);
+    ~RTCConfiguration();
+
+    bool operator==(const RTCConfiguration& o) const;
+    bool operator!=(const RTCConfiguration& o) const;
+
+    bool dscp() const { return media_config.enable_dscp; }
+    void set_dscp(bool enable) { media_config.enable_dscp = enable; }
+
+    bool cpu_adaptation() const {
+      return media_config.video.enable_cpu_adaptation;
+    }
+    void set_cpu_adaptation(bool enable) {
+      media_config.video.enable_cpu_adaptation = enable;
+    }
+
+    bool suspend_below_min_bitrate() const {
+      return media_config.video.suspend_below_min_bitrate;
+    }
+    void set_suspend_below_min_bitrate(bool enable) {
+      media_config.video.suspend_below_min_bitrate = enable;
+    }
+
+    bool prerenderer_smoothing() const {
+      return media_config.video.enable_prerenderer_smoothing;
+    }
+    void set_prerenderer_smoothing(bool enable) {
+      media_config.video.enable_prerenderer_smoothing = enable;
+    }
+
+    bool experiment_cpu_load_estimator() const {
+      return media_config.video.experiment_cpu_load_estimator;
+    }
+    void set_experiment_cpu_load_estimator(bool enable) {
+      media_config.video.experiment_cpu_load_estimator = enable;
+    }
+
+    int audio_rtcp_report_interval_ms() const {
+      return media_config.audio.rtcp_report_interval_ms;
+    }
+    void set_audio_rtcp_report_interval_ms(int audio_rtcp_report_interval_ms) {
+      media_config.audio.rtcp_report_interval_ms =
+          audio_rtcp_report_interval_ms;
+    }
+
+    int video_rtcp_report_interval_ms() const {
+      return media_config.video.rtcp_report_interval_ms;
+    }
+    void set_video_rtcp_report_interval_ms(int video_rtcp_report_interval_ms) {
+      media_config.video.rtcp_report_interval_ms =
+          video_rtcp_report_interval_ms;
+    }
+
+    static const int kUndefined = -1;
+    // Default maximum number of packets in the audio jitter buffer.
+    static const int kAudioJitterBufferMaxPackets = 200;
+    // ICE connection receiving timeout for aggressive configuration.
+    static const int kAggressiveIceConnectionReceivingTimeout = 1000;
+
+    ////////////////////////////////////////////////////////////////////////
+    // The below few fields mirror the standard RTCConfiguration dictionary:
+    // https://w3c.github.io/webrtc-pc/#rtcconfiguration-dictionary
+    ////////////////////////////////////////////////////////////////////////
+
+    // TODO(pthatcher): Rename this ice_servers, but update Chromium
+    // at the same time.
+    IceServers servers;
+    // TODO(pthatcher): Rename this ice_transport_type, but update
+    // Chromium at the same time.
+    IceTransportsType type = kAll;
+    BundlePolicy bundle_policy = kBundlePolicyBalanced;
+    RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyRequire;
+    std::vector<rtc::scoped_refptr<rtc::RTCCertificate>> certificates;
+    int ice_candidate_pool_size = 0;
+
+    //////////////////////////////////////////////////////////////////////////
+    // The below fields correspond to constraints from the deprecated
+    // constraints interface for constructing a PeerConnection.
+    //
+    // absl::optional fields can be "missing", in which case the implementation
+    // default will be used.
+    //////////////////////////////////////////////////////////////////////////
+
+    // If set to true, don't gather IPv6 ICE candidates.
+    // TODO(deadbeef): Remove this? IPv6 support has long stopped being
+    // experimental
+    bool disable_ipv6 = false;
+
+    // If set to true, don't gather IPv6 ICE candidates on Wi-Fi.
+    // Only intended to be used on specific devices. Certain phones disable IPv6
+    // when the screen is turned off and it would be better to just disable the
+    // IPv6 ICE candidates on Wi-Fi in those cases.
+    bool disable_ipv6_on_wifi = false;
+
+    // By default, the PeerConnection will use a limited number of IPv6 network
+    // interfaces, in order to avoid too many ICE candidate pairs being created
+    // and delaying ICE completion.
+    //
+    // Can be set to INT_MAX to effectively disable the limit.
+    int max_ipv6_networks = cricket::kDefaultMaxIPv6Networks;
+
+    // Exclude link-local network interfaces
+    // from considertaion for gathering ICE candidates.
+    bool disable_link_local_networks = false;
+
+    // If set to true, use RTP data channels instead of SCTP.
+    // TODO(deadbeef): Remove this. We no longer commit to supporting RTP data
+    // channels, though some applications are still working on moving off of
+    // them.
+    bool enable_rtp_data_channel = false;
+
+    // Minimum bitrate at which screencast video tracks will be encoded at.
+    // This means adding padding bits up to this bitrate, which can help
+    // when switching from a static scene to one with motion.
+    absl::optional<int> screencast_min_bitrate;
+
+    // Use new combined audio/video bandwidth estimation?
+    absl::optional<bool> combined_audio_video_bwe;
+
+    // TODO(bugs.webrtc.org/9891) - Move to crypto_options
+    // Can be used to disable DTLS-SRTP. This should never be done, but can be
+    // useful for testing purposes, for example in setting up a loopback call
+    // with a single PeerConnection.
+    absl::optional<bool> enable_dtls_srtp;
+
+    /////////////////////////////////////////////////
+    // The below fields are not part of the standard.
+    /////////////////////////////////////////////////
+
+    // Can be used to disable TCP candidate generation.
+    TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled;
+
+    // Can be used to avoid gathering candidates for a "higher cost" network,
+    // if a lower cost one exists. For example, if both Wi-Fi and cellular
+    // interfaces are available, this could be used to avoid using the cellular
+    // interface.
+    CandidateNetworkPolicy candidate_network_policy =
+        kCandidateNetworkPolicyAll;
+
+    // The maximum number of packets that can be stored in the NetEq audio
+    // jitter buffer. Can be reduced to lower tolerated audio latency.
+    int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets;
+
+    // Whether to use the NetEq "fast mode" which will accelerate audio quicker
+    // if it falls behind.
+    bool audio_jitter_buffer_fast_accelerate = false;
+
+    // The minimum delay in milliseconds for the audio jitter buffer.
+    int audio_jitter_buffer_min_delay_ms = 0;
+
+    // Whether the audio jitter buffer adapts the delay to retransmitted
+    // packets.
+    bool audio_jitter_buffer_enable_rtx_handling = false;
+
+    // Timeout in milliseconds before an ICE candidate pair is considered to be
+    // "not receiving", after which a lower priority candidate pair may be
+    // selected.
+    int ice_connection_receiving_timeout = kUndefined;
+
+    // Interval in milliseconds at which an ICE "backup" candidate pair will be
+    // pinged. This is a candidate pair which is not actively in use, but may
+    // be switched to if the active candidate pair becomes unusable.
+    //
+    // This is relevant mainly to Wi-Fi/cell handoff; the application may not
+    // want this backup cellular candidate pair pinged frequently, since it
+    // consumes data/battery.
+    int ice_backup_candidate_pair_ping_interval = kUndefined;
+
+    // Can be used to enable continual gathering, which means new candidates
+    // will be gathered as network interfaces change. Note that if continual
+    // gathering is used, the candidate removal API should also be used, to
+    // avoid an ever-growing list of candidates.
+    ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE;
+
+    // If set to true, candidate pairs will be pinged in order of most likely
+    // to work (which means using a TURN server, generally), rather than in
+    // standard priority order.
+    bool prioritize_most_likely_ice_candidate_pairs = false;
+
+    // Implementation defined settings. A public member only for the benefit of
+    // the implementation. Applications must not access it directly, and should
+    // instead use provided accessor methods, e.g., set_cpu_adaptation.
+    struct cricket::MediaConfig media_config;
+
+    // If set to true, only one preferred TURN allocation will be used per
+    // network interface. UDP is preferred over TCP and IPv6 over IPv4. This
+    // can be used to cut down on the number of candidate pairings.
+    bool prune_turn_ports = false;
+
+    // If set to true, this means the ICE transport should presume TURN-to-TURN
+    // candidate pairs will succeed, even before a binding response is received.
+    // This can be used to optimize the initial connection time, since the DTLS
+    // handshake can begin immediately.
+    bool presume_writable_when_fully_relayed = false;
+
+    // If true, "renomination" will be added to the ice options in the transport
+    // description.
+    // See: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
+    bool enable_ice_renomination = false;
+
+    // If true, the ICE role is re-determined when the PeerConnection sets a
+    // local transport description that indicates an ICE restart.
+    //
+    // This is standard RFC5245 ICE behavior, but causes unnecessary role
+    // thrashing, so an application may wish to avoid it. This role
+    // re-determining was removed in ICEbis (ICE v2).
+    bool redetermine_role_on_ice_restart = true;
+
+    // The following fields define intervals in milliseconds at which ICE
+    // connectivity checks are sent.
+    //
+    // We consider ICE is "strongly connected" for an agent when there is at
+    // least one candidate pair that currently succeeds in connectivity check
+    // from its direction i.e. sending a STUN ping and receives a STUN ping
+    // response, AND all candidate pairs have sent a minimum number of pings for
+    // connectivity (this number is implementation-specific). Otherwise, ICE is
+    // considered in "weak connectivity".
+    //
+    // Note that the above notion of strong and weak connectivity is not defined
+    // in RFC 5245, and they apply to our current ICE implementation only.
+    //
+    // 1) ice_check_interval_strong_connectivity defines the interval applied to
+    // ALL candidate pairs when ICE is strongly connected, and it overrides the
+    // default value of this interval in the ICE implementation;
+    // 2) ice_check_interval_weak_connectivity defines the counterpart for ALL
+    // pairs when ICE is weakly connected, and it overrides the default value of
+    // this interval in the ICE implementation;
+    // 3) ice_check_min_interval defines the minimal interval (equivalently the
+    // maximum rate) that overrides the above two intervals when either of them
+    // is less.
+    absl::optional<int> ice_check_interval_strong_connectivity;
+    absl::optional<int> ice_check_interval_weak_connectivity;
+    absl::optional<int> ice_check_min_interval;
+
+    // The min time period for which a candidate pair must wait for response to
+    // connectivity checks before it becomes unwritable. This parameter
+    // overrides the default value in the ICE implementation if set.
+    absl::optional<int> ice_unwritable_timeout;
+
+    // The min number of connectivity checks that a candidate pair must sent
+    // without receiving response before it becomes unwritable. This parameter
+    // overrides the default value in the ICE implementation if set.
+    absl::optional<int> ice_unwritable_min_checks;
+
+    // The min time period for which a candidate pair must wait for response to
+    // connectivity checks it becomes inactive. This parameter overrides the
+    // default value in the ICE implementation if set.
+    absl::optional<int> ice_inactive_timeout;
+
+    // The interval in milliseconds at which STUN candidates will resend STUN
+    // binding requests to keep NAT bindings open.
+    absl::optional<int> stun_candidate_keepalive_interval;
+
+    // ICE Periodic Regathering
+    // If set, WebRTC will periodically create and propose candidates without
+    // starting a new ICE generation. The regathering happens continuously with
+    // interval specified in milliseconds by the uniform distribution [a, b].
+    absl::optional<rtc::IntervalRange> ice_regather_interval_range;
+
+    // Optional TurnCustomizer.
+    // With this class one can modify outgoing TURN messages.
+    // The object passed in must remain valid until PeerConnection::Close() is
+    // called.
+    webrtc::TurnCustomizer* turn_customizer = nullptr;
+
+    // Preferred network interface.
+    // A candidate pair on a preferred network has a higher precedence in ICE
+    // than one on an un-preferred network, regardless of priority or network
+    // cost.
+    absl::optional<rtc::AdapterType> network_preference;
+
+    // Configure the SDP semantics used by this PeerConnection. Note that the
+    // WebRTC 1.0 specification requires kUnifiedPlan semantics. The
+    // RtpTransceiver API is only available with kUnifiedPlan semantics.
+    //
+    // kPlanB will cause PeerConnection to create offers and answers with at
+    // most one audio and one video m= section with multiple RtpSenders and
+    // RtpReceivers specified as multiple a=ssrc lines within the section. This
+    // will also cause PeerConnection to ignore all but the first m= section of
+    // the same media type.
+    //
+    // kUnifiedPlan will cause PeerConnection to create offers and answers with
+    // multiple m= sections where each m= section maps to one RtpSender and one
+    // RtpReceiver (an RtpTransceiver), either both audio or both video. This
+    // will also cause PeerConnection to ignore all but the first a=ssrc lines
+    // that form a Plan B stream.
+    //
+    // For users who wish to send multiple audio/video streams and need to stay
+    // interoperable with legacy WebRTC implementations or use legacy APIs,
+    // specify kPlanB.
+    //
+    // For all other users, specify kUnifiedPlan.
+    SdpSemantics sdp_semantics = SdpSemantics::kPlanB;
+
+    // TODO(bugs.webrtc.org/9891) - Move to crypto_options or remove.
+    // Actively reset the SRTP parameters whenever the DTLS transports
+    // underneath are reset for every offer/answer negotiation.
+    // This is only intended to be a workaround for crbug.com/835958
+    // WARNING: This would cause RTP/RTCP packets decryption failure if not used
+    // correctly. This flag will be deprecated soon. Do not rely on it.
+    bool active_reset_srtp_params = false;
+
+    // If MediaTransportFactory is provided in PeerConnectionFactory, this flag
+    // informs PeerConnection that it should use the MediaTransportInterface for
+    // media (audio/video). It's invalid to set it to |true| if the
+    // MediaTransportFactory wasn't provided.
+    bool use_media_transport = false;
+
+    // If MediaTransportFactory is provided in PeerConnectionFactory, this flag
+    // informs PeerConnection that it should use the MediaTransportInterface for
+    // data channels.  It's invalid to set it to |true| if the
+    // MediaTransportFactory wasn't provided.  Data channels over media
+    // transport are not compatible with RTP or SCTP data channels.  Setting
+    // both |use_media_transport_for_data_channels| and
+    // |enable_rtp_data_channel| is invalid.
+    bool use_media_transport_for_data_channels = false;
+
+    // Defines advanced optional cryptographic settings related to SRTP and
+    // frame encryption for native WebRTC. Setting this will overwrite any
+    // settings set in PeerConnectionFactory (which is deprecated).
+    absl::optional<CryptoOptions> crypto_options;
+
+    // Configure if we should include the SDP attribute extmap-allow-mixed in
+    // our offer. Although we currently do support this, it's not included in
+    // our offer by default due to a previous bug that caused the SDP parser to
+    // abort parsing if this attribute was present. This is fixed in Chrome 71.
+    // TODO(webrtc:9985): Change default to true once sufficient time has
+    // passed.
+    bool offer_extmap_allow_mixed = false;
+
+    //
+    // Don't forget to update operator== if adding something.
+    //
+  };
+
+  // See: https://www.w3.org/TR/webrtc/#idl-def-rtcofferansweroptions
+  struct RTCOfferAnswerOptions {
+    static const int kUndefined = -1;
+    static const int kMaxOfferToReceiveMedia = 1;
+
+    // The default value for constraint offerToReceiveX:true.
+    static const int kOfferToReceiveMediaTrue = 1;
+
+    // These options are left as backwards compatibility for clients who need
+    // "Plan B" semantics. Clients who have switched to "Unified Plan" semantics
+    // should use the RtpTransceiver API (AddTransceiver) instead.
+    //
+    // offer_to_receive_X set to 1 will cause a media description to be
+    // generated in the offer, even if no tracks of that type have been added.
+    // Values greater than 1 are treated the same.
+    //
+    // If set to 0, the generated directional attribute will not include the
+    // "recv" direction (meaning it will be "sendonly" or "inactive".
+    int offer_to_receive_video = kUndefined;
+    int offer_to_receive_audio = kUndefined;
+
+    bool voice_activity_detection = true;
+    bool ice_restart = false;
+
+    // If true, will offer to BUNDLE audio/video/data together. Not to be
+    // confused with RTCP mux (multiplexing RTP and RTCP together).
+    bool use_rtp_mux = true;
+
+    // This will apply to all video tracks with a Plan B SDP offer/answer.
+    int num_simulcast_layers = 1;
+
+    RTCOfferAnswerOptions() = default;
+
+    RTCOfferAnswerOptions(int offer_to_receive_video,
+                          int offer_to_receive_audio,
+                          bool voice_activity_detection,
+                          bool ice_restart,
+                          bool use_rtp_mux)
+        : offer_to_receive_video(offer_to_receive_video),
+          offer_to_receive_audio(offer_to_receive_audio),
+          voice_activity_detection(voice_activity_detection),
+          ice_restart(ice_restart),
+          use_rtp_mux(use_rtp_mux) {}
+  };
+
+  // Used by GetStats to decide which stats to include in the stats reports.
+  // |kStatsOutputLevelStandard| includes the standard stats for Javascript API;
+  // |kStatsOutputLevelDebug| includes both the standard stats and additional
+  // stats for debugging purposes.
+  enum StatsOutputLevel {
+    kStatsOutputLevelStandard,
+    kStatsOutputLevelDebug,
+  };
+
+  // Accessor methods to active local streams.
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // GetSenders() instead.
+  virtual rtc::scoped_refptr<StreamCollectionInterface> local_streams() = 0;
+
+  // Accessor methods to remote streams.
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // GetReceivers() instead.
+  virtual rtc::scoped_refptr<StreamCollectionInterface> remote_streams() = 0;
+
+  // Add a new MediaStream to be sent on this PeerConnection.
+  // Note that a SessionDescription negotiation is needed before the
+  // remote peer can receive the stream.
+  //
+  // This has been removed from the standard in favor of a track-based API. So,
+  // this is equivalent to simply calling AddTrack for each track within the
+  // stream, with the one difference that if "stream->AddTrack(...)" is called
+  // later, the PeerConnection will automatically pick up the new track. Though
+  // this functionality will be deprecated in the future.
+  //
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // AddTrack instead.
+  virtual bool AddStream(MediaStreamInterface* stream) = 0;
+
+  // Remove a MediaStream from this PeerConnection.
+  // Note that a SessionDescription negotiation is needed before the
+  // remote peer is notified.
+  //
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // RemoveTrack instead.
+  virtual void RemoveStream(MediaStreamInterface* stream) = 0;
+
+  // Add a new MediaStreamTrack to be sent on this PeerConnection, and return
+  // the newly created RtpSender. The RtpSender will be associated with the
+  // streams specified in the |stream_ids| list.
+  //
+  // Errors:
+  // - INVALID_PARAMETER: |track| is null, has a kind other than audio or video,
+  //       or a sender already exists for the track.
+  // - INVALID_STATE: The PeerConnection is closed.
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>> AddTrack(
+      rtc::scoped_refptr<MediaStreamTrackInterface> track,
+      const std::vector<std::string>& stream_ids);
+
+  // Remove an RtpSender from this PeerConnection.
+  // Returns true on success.
+  // TODO(steveanton): Replace with signature that returns RTCError.
+  virtual bool RemoveTrack(RtpSenderInterface* sender);
+
+  // Plan B semantics: Removes the RtpSender from this PeerConnection.
+  // Unified Plan semantics: Stop sending on the RtpSender and mark the
+  // corresponding RtpTransceiver direction as no longer sending.
+  //
+  // Errors:
+  // - INVALID_PARAMETER: |sender| is null or (Plan B only) the sender is not
+  //       associated with this PeerConnection.
+  // - INVALID_STATE: PeerConnection is closed.
+  // TODO(bugs.webrtc.org/9534): Rename to RemoveTrack once the other signature
+  // is removed.
+  virtual RTCError RemoveTrackNew(
+      rtc::scoped_refptr<RtpSenderInterface> sender);
+
+  // AddTransceiver creates a new RtpTransceiver and adds it to the set of
+  // transceivers. Adding a transceiver will cause future calls to CreateOffer
+  // to add a media description for the corresponding transceiver.
+  //
+  // The initial value of |mid| in the returned transceiver is null. Setting a
+  // new session description may change it to a non-null value.
+  //
+  // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-addtransceiver
+  //
+  // Optionally, an RtpTransceiverInit structure can be specified to configure
+  // the transceiver from construction. If not specified, the transceiver will
+  // default to having a direction of kSendRecv and not be part of any streams.
+  //
+  // These methods are only available when Unified Plan is enabled (see
+  // RTCConfiguration).
+  //
+  // Common errors:
+  // - INTERNAL_ERROR: The configuration does not have Unified Plan enabled.
+  // TODO(steveanton): Make these pure virtual once downstream projects have
+  // updated.
+
+  // Adds a transceiver with a sender set to transmit the given track. The kind
+  // of the transceiver (and sender/receiver) will be derived from the kind of
+  // the track.
+  // Errors:
+  // - INVALID_PARAMETER: |track| is null.
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track);
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(rtc::scoped_refptr<MediaStreamTrackInterface> track,
+                 const RtpTransceiverInit& init);
+
+  // Adds a transceiver with the given kind. Can either be MEDIA_TYPE_AUDIO or
+  // MEDIA_TYPE_VIDEO.
+  // Errors:
+  // - INVALID_PARAMETER: |media_type| is not MEDIA_TYPE_AUDIO or
+  //                      MEDIA_TYPE_VIDEO.
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(cricket::MediaType media_type);
+  virtual RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
+  AddTransceiver(cricket::MediaType media_type, const RtpTransceiverInit& init);
+
+  // TODO(deadbeef): Make these pure virtual once all subclasses implement them.
+
+  // Creates a sender without a track. Can be used for "early media"/"warmup"
+  // use cases, where the application may want to negotiate video attributes
+  // before a track is available to send.
+  //
+  // The standard way to do this would be through "addTransceiver", but we
+  // don't support that API yet.
+  //
+  // |kind| must be "audio" or "video".
+  //
+  // |stream_id| is used to populate the msid attribute; if empty, one will
+  // be generated automatically.
+  //
+  // This method is not supported with kUnifiedPlan semantics. Please use
+  // AddTransceiver instead.
+  virtual rtc::scoped_refptr<RtpSenderInterface> CreateSender(
+      const std::string& kind,
+      const std::string& stream_id);
+
+  // If Plan B semantics are specified, gets all RtpSenders, created either
+  // through AddStream, AddTrack, or CreateSender. All senders of a specific
+  // media type share the same media description.
+  //
+  // If Unified Plan semantics are specified, gets the RtpSender for each
+  // RtpTransceiver.
+  virtual std::vector<rtc::scoped_refptr<RtpSenderInterface>> GetSenders()
+      const;
+
+  // If Plan B semantics are specified, gets all RtpReceivers created when a
+  // remote description is applied. All receivers of a specific media type share
+  // the same media description. It is also possible to have a media description
+  // with no associated RtpReceivers, if the directional attribute does not
+  // indicate that the remote peer is sending any media.
+  //
+  // If Unified Plan semantics are specified, gets the RtpReceiver for each
+  // RtpTransceiver.
+  virtual std::vector<rtc::scoped_refptr<RtpReceiverInterface>> GetReceivers()
+      const;
+
+  // Get all RtpTransceivers, created either through AddTransceiver, AddTrack or
+  // by a remote description applied with SetRemoteDescription.
+  //
+  // Note: This method is only available when Unified Plan is enabled (see
+  // RTCConfiguration).
+  virtual std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>
+  GetTransceivers() const;
+
+  // The legacy non-compliant GetStats() API. This correspond to the
+  // callback-based version of getStats() in JavaScript. The returned metrics
+  // are UNDOCUMENTED and many of them rely on implementation-specific details.
+  // The goal is to DELETE THIS VERSION but we can't today because it is heavily
+  // relied upon by third parties. See https://crbug.com/822696.
+  //
+  // This version is wired up into Chrome. Any stats implemented are
+  // automatically exposed to the Web Platform. This has BYPASSED the Chrome
+  // release processes for years and lead to cross-browser incompatibility
+  // issues and web application reliance on Chrome-only behavior.
+  //
+  // This API is in "maintenance mode", serious regressions should be fixed but
+  // adding new stats is highly discouraged.
+  //
+  // TODO(hbos): Deprecate and remove this when third parties have migrated to
+  // the spec-compliant GetStats() API. https://crbug.com/822696
+  virtual bool GetStats(StatsObserver* observer,
+                        MediaStreamTrackInterface* track,  // Optional
+                        StatsOutputLevel level) = 0;
+  // The spec-compliant GetStats() API. This correspond to the promise-based
+  // version of getStats() in JavaScript. Implementation status is described in
+  // api/stats/rtcstats_objects.h. For more details on stats, see spec:
+  // https://w3c.github.io/webrtc-pc/#dom-rtcpeerconnection-getstats
+  // TODO(hbos): Takes shared ownership, use rtc::scoped_refptr<> instead. This
+  // requires stop overriding the current version in third party or making third
+  // party calls explicit to avoid ambiguity during switch. Make the future
+  // version abstract as soon as third party projects implement it.
+  virtual void GetStats(RTCStatsCollectorCallback* callback) {}
+  // Spec-compliant getStats() performing the stats selection algorithm with the
+  // sender. https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-getstats
+  // TODO(hbos): Make abstract as soon as third party projects implement it.
+  virtual void GetStats(
+      rtc::scoped_refptr<RtpSenderInterface> selector,
+      rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {}
+  // Spec-compliant getStats() performing the stats selection algorithm with the
+  // receiver. https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-getstats
+  // TODO(hbos): Make abstract as soon as third party projects implement it.
+  virtual void GetStats(
+      rtc::scoped_refptr<RtpReceiverInterface> selector,
+      rtc::scoped_refptr<RTCStatsCollectorCallback> callback) {}
+  // Clear cached stats in the RTCStatsCollector.
+  // Exposed for testing while waiting for automatic cache clear to work.
+  // https://bugs.webrtc.org/8693
+  virtual void ClearStatsCache() {}
+
+  // Create a data channel with the provided config, or default config if none
+  // is provided. Note that an offer/answer negotiation is still necessary
+  // before the data channel can be used.
+  //
+  // Also, calling CreateDataChannel is the only way to get a data "m=" section
+  // in SDP, so it should be done before CreateOffer is called, if the
+  // application plans to use data channels.
+  virtual rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
+      const std::string& label,
+      const DataChannelInit* config) = 0;
+
+  // Returns the more recently applied description; "pending" if it exists, and
+  // otherwise "current". See below.
+  virtual const SessionDescriptionInterface* local_description() const = 0;
+  virtual const SessionDescriptionInterface* remote_description() const = 0;
+
+  // A "current" description the one currently negotiated from a complete
+  // offer/answer exchange.
+  virtual const SessionDescriptionInterface* current_local_description() const;
+  virtual const SessionDescriptionInterface* current_remote_description() const;
+
+  // A "pending" description is one that's part of an incomplete offer/answer
+  // exchange (thus, either an offer or a pranswer). Once the offer/answer
+  // exchange is finished, the "pending" description will become "current".
+  virtual const SessionDescriptionInterface* pending_local_description() const;
+  virtual const SessionDescriptionInterface* pending_remote_description() const;
+
+  // Create a new offer.
+  // The CreateSessionDescriptionObserver callback will be called when done.
+  virtual void CreateOffer(CreateSessionDescriptionObserver* observer,
+                           const RTCOfferAnswerOptions& options) = 0;
+
+  // Create an answer to an offer.
+  // The CreateSessionDescriptionObserver callback will be called when done.
+  virtual void CreateAnswer(CreateSessionDescriptionObserver* observer,
+                            const RTCOfferAnswerOptions& options) = 0;
+
+  // Sets the local session description.
+  // The PeerConnection takes the ownership of |desc| even if it fails.
+  // The |observer| callback will be called when done.
+  // TODO(deadbeef): Change |desc| to be a unique_ptr, to make it clear
+  // that this method always takes ownership of it.
+  virtual void SetLocalDescription(SetSessionDescriptionObserver* observer,
+                                   SessionDescriptionInterface* desc) = 0;
+  // Sets the remote session description.
+  // The PeerConnection takes the ownership of |desc| even if it fails.
+  // The |observer| callback will be called when done.
+  // TODO(hbos): Remove when Chrome implements the new signature.
+  virtual void SetRemoteDescription(SetSessionDescriptionObserver* observer,
+                                    SessionDescriptionInterface* desc) {}
+  // TODO(hbos): Make pure virtual when Chrome has updated its signature.
+  virtual void SetRemoteDescription(
+      std::unique_ptr<SessionDescriptionInterface> desc,
+      rtc::scoped_refptr<SetRemoteDescriptionObserverInterface> observer) {}
+
+  // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of
+  // PeerConnectionInterface implement it.
+  virtual PeerConnectionInterface::RTCConfiguration GetConfiguration();
+
+  // Sets the PeerConnection's global configuration to |config|.
+  //
+  // The members of |config| that may be changed are |type|, |servers|,
+  // |ice_candidate_pool_size| and |prune_turn_ports| (though the candidate
+  // pool size can't be changed after the first call to SetLocalDescription).
+  // Note that this means the BUNDLE and RTCP-multiplexing policies cannot be
+  // changed with this method.
+  //
+  // Any changes to STUN/TURN servers or ICE candidate policy will affect the
+  // next gathering phase, and cause the next call to createOffer to generate
+  // new ICE credentials, as described in JSEP. This also occurs when
+  // |prune_turn_ports| changes, for the same reasoning.
+  //
+  // If an error occurs, returns false and populates |error| if non-null:
+  // - INVALID_MODIFICATION if |config| contains a modified parameter other
+  //   than one of the parameters listed above.
+  // - INVALID_RANGE if |ice_candidate_pool_size| is out of range.
+  // - SYNTAX_ERROR if parsing an ICE server URL failed.
+  // - INVALID_PARAMETER if a TURN server is missing |username| or |password|.
+  // - INTERNAL_ERROR if an unexpected error occurred.
+  //
+  // TODO(deadbeef): Make this pure virtual once all Chrome subclasses of
+  // PeerConnectionInterface implement it.
+  virtual bool SetConfiguration(
+      const PeerConnectionInterface::RTCConfiguration& config,
+      RTCError* error);
+
+  // Version without error output param for backwards compatibility.
+  // TODO(deadbeef): Remove once chromium is updated.
+  virtual bool SetConfiguration(
+      const PeerConnectionInterface::RTCConfiguration& config);
+
+  // Provides a remote candidate to the ICE Agent.
+  // A copy of the |candidate| will be created and added to the remote
+  // description. So the caller of this method still has the ownership of the
+  // |candidate|.
+  virtual bool AddIceCandidate(const IceCandidateInterface* candidate) = 0;
+
+  // Removes a group of remote candidates from the ICE agent. Needed mainly for
+  // continual gathering, to avoid an ever-growing list of candidates as
+  // networks come and go.
+  virtual bool RemoveIceCandidates(
+      const std::vector<cricket::Candidate>& candidates);
+
+  // 0 <= min <= current <= max should hold for set parameters.
+  struct BitrateParameters {
+    BitrateParameters();
+    ~BitrateParameters();
+
+    absl::optional<int> min_bitrate_bps;
+    absl::optional<int> current_bitrate_bps;
+    absl::optional<int> max_bitrate_bps;
+  };
+
+  // SetBitrate limits the bandwidth allocated for all RTP streams sent by
+  // this PeerConnection. Other limitations might affect these limits and
+  // are respected (for example "b=AS" in SDP).
+  //
+  // Setting |current_bitrate_bps| will reset the current bitrate estimate
+  // to the provided value.
+  virtual RTCError SetBitrate(const BitrateSettings& bitrate);
+
+  // TODO(nisse): Deprecated - use version above. These two default
+  // implementations require subclasses to implement one or the other
+  // of the methods.
+  virtual RTCError SetBitrate(const BitrateParameters& bitrate_parameters);
+
+  // Sets current strategy. If not set default WebRTC allocator will be used.
+  // May be changed during an active session. The strategy
+  // ownership is passed with std::unique_ptr
+  // TODO(alexnarest): Make this pure virtual when tests will be updated
+  virtual void SetBitrateAllocationStrategy(
+      std::unique_ptr<rtc::BitrateAllocationStrategy>
+          bitrate_allocation_strategy) {}
+
+  // Enable/disable playout of received audio streams. Enabled by default. Note
+  // that even if playout is enabled, streams will only be played out if the
+  // appropriate SDP is also applied. Setting |playout| to false will stop
+  // playout of the underlying audio device but starts a task which will poll
+  // for audio data every 10ms to ensure that audio processing happens and the
+  // audio statistics are updated.
+  // TODO(henrika): deprecate and remove this.
+  virtual void SetAudioPlayout(bool playout) {}
+
+  // Enable/disable recording of transmitted audio streams. Enabled by default.
+  // Note that even if recording is enabled, streams will only be recorded if
+  // the appropriate SDP is also applied.
+  // TODO(henrika): deprecate and remove this.
+  virtual void SetAudioRecording(bool recording) {}
+
+  // Looks up the DtlsTransport associated with a MID value.
+  // In the Javascript API, DtlsTransport is a property of a sender, but
+  // because the PeerConnection owns the DtlsTransport in this implementation,
+  // it is better to look them up on the PeerConnection.
+  // TODO(hta): Remove default implementation after updating Chrome.
+  virtual rtc::scoped_refptr<DtlsTransportInterface> LookupDtlsTransportByMid(
+      const std::string& mid);
+
+  // Returns the SCTP transport, if any.
+  // TODO(hta): Remove default implementation after updating Chrome.
+  virtual rtc::scoped_refptr<SctpTransportInterface> GetSctpTransport() const;
+
+  // Returns the current SignalingState.
+  virtual SignalingState signaling_state() = 0;
+
+  // Returns an aggregate state of all ICE *and* DTLS transports.
+  // This is left in place to avoid breaking native clients who expect our old,
+  // nonstandard behavior.
+  // TODO(jonasolsson): deprecate and remove this.
+  virtual IceConnectionState ice_connection_state() = 0;
+
+  // Returns an aggregated state of all ICE transports.
+  virtual IceConnectionState standardized_ice_connection_state();
+
+  // Returns an aggregated state of all ICE and DTLS transports.
+  virtual PeerConnectionState peer_connection_state();
+
+  virtual IceGatheringState ice_gathering_state() = 0;
+
+  // Starts RtcEventLog using existing file. Takes ownership of |file| and
+  // passes it on to Call, which will take the ownership. If the
+  // operation fails the file will be closed.
+  // The logging will stop when |max_size_bytes| is reached or when the
+  // StopRtcEventLog function is called.
+  // TODO(eladalon): Deprecate and remove this.
+  virtual bool StartRtcEventLog(rtc::PlatformFile file, int64_t max_size_bytes);
+
+  // Start RtcEventLog using an existing output-sink. Takes ownership of
+  // |output| and passes it on to Call, which will take the ownership. If the
+  // operation fails the output will be closed and deallocated. The event log
+  // will send serialized events to the output object every |output_period_ms|.
+  virtual bool StartRtcEventLog(std::unique_ptr<RtcEventLogOutput> output,
+                                int64_t output_period_ms);
+
+  // Stops logging the RtcEventLog.
+  // TODO(ivoc): Make this pure virtual when Chrome is updated.
+  virtual void StopRtcEventLog() {}
+
+  // Terminates all media, closes the transports, and in general releases any
+  // resources used by the PeerConnection. This is an irreversible operation.
+  //
+  // Note that after this method completes, the PeerConnection will no longer
+  // use the PeerConnectionObserver interface passed in on construction, and
+  // thus the observer object can be safely destroyed.
+  virtual void Close() = 0;
+
+ protected:
+  // Dtor protected as objects shouldn't be deleted via this interface.
+  ~PeerConnectionInterface() override = default;
+};
+
+// PeerConnection callback interface, used for RTCPeerConnection events.
+// Application should implement these methods.
+class PeerConnectionObserver {
+ public:
+  virtual ~PeerConnectionObserver() = default;
+
+  // Triggered when the SignalingState changed.
+  virtual void OnSignalingChange(
+      PeerConnectionInterface::SignalingState new_state) = 0;
+
+  // Triggered when media is received on a new stream from remote peer.
+  virtual void OnAddStream(rtc::scoped_refptr<MediaStreamInterface> stream) {}
+
+  // Triggered when a remote peer closes a stream.
+  virtual void OnRemoveStream(rtc::scoped_refptr<MediaStreamInterface> stream) {
+  }
+
+  // Triggered when a remote peer opens a data channel.
+  virtual void OnDataChannel(
+      rtc::scoped_refptr<DataChannelInterface> data_channel) = 0;
+
+  // Triggered when renegotiation is needed. For example, an ICE restart
+  // has begun.
+  virtual void OnRenegotiationNeeded() = 0;
+
+  // Called any time the legacy IceConnectionState changes.
+  //
+  // Note that our ICE states lag behind the standard slightly. The most
+  // notable differences include the fact that "failed" occurs after 15
+  // seconds, not 30, and this actually represents a combination ICE + DTLS
+  // state, so it may be "failed" if DTLS fails while ICE succeeds.
+  //
+  // TODO(jonasolsson): deprecate and remove this.
+  virtual void OnIceConnectionChange(
+      PeerConnectionInterface::IceConnectionState new_state) = 0;
+
+  // Called any time the standards-compliant IceConnectionState changes.
+  virtual void OnStandardizedIceConnectionChange(
+      PeerConnectionInterface::IceConnectionState new_state) {}
+
+  // Called any time the PeerConnectionState changes.
+  virtual void OnConnectionChange(
+      PeerConnectionInterface::PeerConnectionState new_state) {}
+
+  // Called any time the IceGatheringState changes.
+  virtual void OnIceGatheringChange(
+      PeerConnectionInterface::IceGatheringState new_state) = 0;
+
+  // A new ICE candidate has been gathered.
+  virtual void OnIceCandidate(const IceCandidateInterface* candidate) = 0;
+
+  // Ice candidates have been removed.
+  // TODO(honghaiz): Make this a pure virtual method when all its subclasses
+  // implement it.
+  virtual void OnIceCandidatesRemoved(
+      const std::vector<cricket::Candidate>& candidates) {}
+
+  // Called when the ICE connection receiving status changes.
+  virtual void OnIceConnectionReceivingChange(bool receiving) {}
+
+  // This is called when a receiver and its track are created.
+  // TODO(zhihuang): Make this pure virtual when all subclasses implement it.
+  // Note: This is called with both Plan B and Unified Plan semantics. Unified
+  // Plan users should prefer OnTrack, OnAddTrack is only called as backwards
+  // compatibility (and is called in the exact same situations as OnTrack).
+  virtual void OnAddTrack(
+      rtc::scoped_refptr<RtpReceiverInterface> receiver,
+      const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams) {}
+
+  // This is called when signaling indicates a transceiver will be receiving
+  // media from the remote endpoint. This is fired during a call to
+  // SetRemoteDescription. The receiving track can be accessed by:
+  // |transceiver->receiver()->track()| and its associated streams by
+  // |transceiver->receiver()->streams()|.
+  // Note: This will only be called if Unified Plan semantics are specified.
+  // This behavior is specified in section 2.2.8.2.5 of the "Set the
+  // RTCSessionDescription" algorithm:
+  // https://w3c.github.io/webrtc-pc/#set-description
+  virtual void OnTrack(
+      rtc::scoped_refptr<RtpTransceiverInterface> transceiver) {}
+
+  // Called when signaling indicates that media will no longer be received on a
+  // track.
+  // With Plan B semantics, the given receiver will have been removed from the
+  // PeerConnection and the track muted.
+  // With Unified Plan semantics, the receiver will remain but the transceiver
+  // will have changed direction to either sendonly or inactive.
+  // https://w3c.github.io/webrtc-pc/#process-remote-track-removal
+  // TODO(hbos,deadbeef): Make pure virtual when all subclasses implement it.
+  virtual void OnRemoveTrack(
+      rtc::scoped_refptr<RtpReceiverInterface> receiver) {}
+
+  // Called when an interesting usage is detected by WebRTC.
+  // An appropriate action is to add information about the context of the
+  // PeerConnection and write the event to some kind of "interesting events"
+  // log function.
+  // The heuristics for defining what constitutes "interesting" are
+  // implementation-defined.
+  virtual void OnInterestingUsage(int usage_pattern) {}
+};
+
+// PeerConnectionDependencies holds all of PeerConnections dependencies.
+// A dependency is distinct from a configuration as it defines significant
+// executable code that can be provided by a user of the API.
+//
+// All new dependencies should be added as a unique_ptr to allow the
+// PeerConnection object to be the definitive owner of the dependencies
+// lifetime making injection safer.
+struct PeerConnectionDependencies final {
+  explicit PeerConnectionDependencies(PeerConnectionObserver* observer_in);
+  // This object is not copyable or assignable.
+  PeerConnectionDependencies(const PeerConnectionDependencies&) = delete;
+  PeerConnectionDependencies& operator=(const PeerConnectionDependencies&) =
+      delete;
+  // This object is only moveable.
+  PeerConnectionDependencies(PeerConnectionDependencies&&);
+  PeerConnectionDependencies& operator=(PeerConnectionDependencies&&) = default;
+  ~PeerConnectionDependencies();
+  // Mandatory dependencies
+  PeerConnectionObserver* observer = nullptr;
+  // Optional dependencies
+  std::unique_ptr<cricket::PortAllocator> allocator;
+  std::unique_ptr<webrtc::AsyncResolverFactory> async_resolver_factory;
+  std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator;
+  std::unique_ptr<rtc::SSLCertificateVerifier> tls_cert_verifier;
+};
+
+// PeerConnectionFactoryDependencies holds all of the PeerConnectionFactory
+// dependencies. All new dependencies should be added here instead of
+// overloading the function. This simplifies dependency injection and makes it
+// clear which are mandatory and optional. If possible please allow the peer
+// connection factory to take ownership of the dependency by adding a unique_ptr
+// to this structure.
+struct PeerConnectionFactoryDependencies final {
+  PeerConnectionFactoryDependencies();
+  // This object is not copyable or assignable.
+  PeerConnectionFactoryDependencies(const PeerConnectionFactoryDependencies&) =
+      delete;
+  PeerConnectionFactoryDependencies& operator=(
+      const PeerConnectionFactoryDependencies&) = delete;
+  // This object is only moveable.
+  PeerConnectionFactoryDependencies(PeerConnectionFactoryDependencies&&);
+  PeerConnectionFactoryDependencies& operator=(
+      PeerConnectionFactoryDependencies&&) = default;
+  ~PeerConnectionFactoryDependencies();
+
+  // Optional dependencies
+  rtc::Thread* network_thread = nullptr;
+  rtc::Thread* worker_thread = nullptr;
+  rtc::Thread* signaling_thread = nullptr;
+  std::unique_ptr<cricket::MediaEngineInterface> media_engine;
+  std::unique_ptr<CallFactoryInterface> call_factory;
+  std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory;
+  std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory;
+  std::unique_ptr<NetworkControllerFactoryInterface> network_controller_factory;
+  std::unique_ptr<MediaTransportFactory> media_transport_factory;
+};
+
+// PeerConnectionFactoryInterface is the factory interface used for creating
+// PeerConnection, MediaStream and MediaStreamTrack objects.
+//
+// The simplest method for obtaiing one, CreatePeerConnectionFactory will
+// create the required libjingle threads, socket and network manager factory
+// classes for networking if none are provided, though it requires that the
+// application runs a message loop on the thread that called the method (see
+// explanation below)
+//
+// If an application decides to provide its own threads and/or implementation
+// of networking classes, it should use the alternate
+// CreatePeerConnectionFactory method which accepts threads as input, and use
+// the CreatePeerConnection version that takes a PortAllocator as an argument.
+class PeerConnectionFactoryInterface : public rtc::RefCountInterface {
+ public:
+  class Options {
+   public:
+    Options() {}
+
+    // If set to true, created PeerConnections won't enforce any SRTP
+    // requirement, allowing unsecured media. Should only be used for
+    // testing/debugging.
+    bool disable_encryption = false;
+
+    // Deprecated. The only effect of setting this to true is that
+    // CreateDataChannel will fail, which is not that useful.
+    bool disable_sctp_data_channels = false;
+
+    // If set to true, any platform-supported network monitoring capability
+    // won't be used, and instead networks will only be updated via polling.
+    //
+    // This only has an effect if a PeerConnection is created with the default
+    // PortAllocator implementation.
+    bool disable_network_monitor = false;
+
+    // Sets the network types to ignore. For instance, calling this with
+    // ADAPTER_TYPE_ETHERNET | ADAPTER_TYPE_LOOPBACK will ignore Ethernet and
+    // loopback interfaces.
+    int network_ignore_mask = rtc::kDefaultNetworkIgnoreMask;
+
+    // Sets the maximum supported protocol version. The highest version
+    // supported by both ends will be used for the connection, i.e. if one
+    // party supports DTLS 1.0 and the other DTLS 1.2, DTLS 1.0 will be used.
+    rtc::SSLProtocolVersion ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12;
+
+    // Sets crypto related options, e.g. enabled cipher suites.
+    CryptoOptions crypto_options = CryptoOptions::NoGcm();
+  };
+
+  // Set the options to be used for subsequently created PeerConnections.
+  virtual void SetOptions(const Options& options) = 0;
+
+  // The preferred way to create a new peer connection. Simply provide the
+  // configuration and a PeerConnectionDependencies structure.
+  // TODO(benwright): Make pure virtual once downstream mock PC factory classes
+  // are updated.
+  virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
+      const PeerConnectionInterface::RTCConfiguration& configuration,
+      PeerConnectionDependencies dependencies);
+
+  // Deprecated; |allocator| and |cert_generator| may be null, in which case
+  // default implementations will be used.
+  //
+  // |observer| must not be null.
+  //
+  // Note that this method does not take ownership of |observer|; it's the
+  // responsibility of the caller to delete it. It can be safely deleted after
+  // Close has been called on the returned PeerConnection, which ensures no
+  // more observer callbacks will be invoked.
+  virtual rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
+      const PeerConnectionInterface::RTCConfiguration& configuration,
+      std::unique_ptr<cricket::PortAllocator> allocator,
+      std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
+      PeerConnectionObserver* observer);
+
+  // Returns the capabilities of an RTP sender of type |kind|.
+  // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
+  // TODO(orphis): Make pure virtual when all subclasses implement it.
+  virtual RtpCapabilities GetRtpSenderCapabilities(
+      cricket::MediaType kind) const;
+
+  // Returns the capabilities of an RTP receiver of type |kind|.
+  // If for some reason you pass in MEDIA_TYPE_DATA, returns an empty structure.
+  // TODO(orphis): Make pure virtual when all subclasses implement it.
+  virtual RtpCapabilities GetRtpReceiverCapabilities(
+      cricket::MediaType kind) const;
+
+  virtual rtc::scoped_refptr<MediaStreamInterface> CreateLocalMediaStream(
+      const std::string& stream_id) = 0;
+
+  // Creates an AudioSourceInterface.
+  // |options| decides audio processing settings.
+  virtual rtc::scoped_refptr<AudioSourceInterface> CreateAudioSource(
+      const cricket::AudioOptions& options) = 0;
+
+  // Creates a new local VideoTrack. The same |source| can be used in several
+  // tracks.
+  virtual rtc::scoped_refptr<VideoTrackInterface> CreateVideoTrack(
+      const std::string& label,
+      VideoTrackSourceInterface* source) = 0;
+
+  // Creates an new AudioTrack. At the moment |source| can be null.
+  virtual rtc::scoped_refptr<AudioTrackInterface> CreateAudioTrack(
+      const std::string& label,
+      AudioSourceInterface* source) = 0;
+
+  // Starts AEC dump using existing file. Takes ownership of |file| and passes
+  // it on to VoiceEngine (via other objects) immediately, which will take
+  // the ownerhip. If the operation fails, the file will be closed.
+  // A maximum file size in bytes can be specified. When the file size limit is
+  // reached, logging is stopped automatically. If max_size_bytes is set to a
+  // value <= 0, no limit will be used, and logging will continue until the
+  // StopAecDump function is called.
+  virtual bool StartAecDump(rtc::PlatformFile file, int64_t max_size_bytes) = 0;
+
+  // Stops logging the AEC dump.
+  virtual void StopAecDump() = 0;
+
+ protected:
+  // Dtor and ctor protected as objects shouldn't be created or deleted via
+  // this interface.
+  PeerConnectionFactoryInterface() {}
+  ~PeerConnectionFactoryInterface() override = default;
+};
+
+// This is a lower-level version of the CreatePeerConnectionFactory functions
+// above. It's implemented in the "peerconnection" build target, whereas the
+// above methods are only implemented in the broader "libjingle_peerconnection"
+// build target, which pulls in the implementations of every module webrtc may
+// use.
+//
+// If an application knows it will only require certain modules, it can reduce
+// webrtc's impact on its binary size by depending only on the "peerconnection"
+// target and the modules the application requires, using
+// CreateModularPeerConnectionFactory instead of one of the
+// CreatePeerConnectionFactory methods above. For example, if an application
+// only uses WebRTC for audio, it can pass in null pointers for the
+// video-specific interfaces, and omit the corresponding modules from its
+// build.
+//
+// If |network_thread| or |worker_thread| are null, the PeerConnectionFactory
+// will create the necessary thread internally. If |signaling_thread| is null,
+// the PeerConnectionFactory will use the thread on which this method is called
+// as the signaling thread, wrapping it in an rtc::Thread object if needed.
+//
+// If non-null, a reference is added to |default_adm|, and ownership of
+// |video_encoder_factory| and |video_decoder_factory| is transferred to the
+// returned factory.
+//
+// If |audio_mixer| is null, an internal audio mixer will be created and used.
+//
+// TODO(deadbeef): Use rtc::scoped_refptr<> and std::unique_ptr<> to make this
+// ownership transfer and ref counting more obvious.
+//
+// TODO(deadbeef): Encapsulate these modules in a struct, so that when a new
+// module is inevitably exposed, we can just add a field to the struct instead
+// of adding a whole new CreateModularPeerConnectionFactory overload.
+rtc::scoped_refptr<PeerConnectionFactoryInterface>
+CreateModularPeerConnectionFactory(
+    rtc::Thread* network_thread,
+    rtc::Thread* worker_thread,
+    rtc::Thread* signaling_thread,
+    std::unique_ptr<cricket::MediaEngineInterface> media_engine,
+    std::unique_ptr<CallFactoryInterface> call_factory,
+    std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory);
+
+rtc::scoped_refptr<PeerConnectionFactoryInterface>
+CreateModularPeerConnectionFactory(
+    rtc::Thread* network_thread,
+    rtc::Thread* worker_thread,
+    rtc::Thread* signaling_thread,
+    std::unique_ptr<cricket::MediaEngineInterface> media_engine,
+    std::unique_ptr<CallFactoryInterface> call_factory,
+    std::unique_ptr<RtcEventLogFactoryInterface> event_log_factory,
+    std::unique_ptr<FecControllerFactoryInterface> fec_controller_factory,
+    std::unique_ptr<NetworkControllerFactoryInterface>
+        network_controller_factory = nullptr);
+
+rtc::scoped_refptr<PeerConnectionFactoryInterface>
+CreateModularPeerConnectionFactory(
+    PeerConnectionFactoryDependencies dependencies);
+
+}  // namespace webrtc
+
+#endif  // API_PEER_CONNECTION_INTERFACE_H_
diff --git a/api/peer_connection_proxy.h b/api/peer_connection_proxy.h
new file mode 100644
index 0000000..61058b5
--- /dev/null
+++ b/api/peer_connection_proxy.h
@@ -0,0 +1,145 @@
+/*
+ *  Copyright 2012 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_PEER_CONNECTION_PROXY_H_
+#define API_PEER_CONNECTION_PROXY_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/peer_connection_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(PeerConnection)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_METHOD0(rtc::scoped_refptr<StreamCollectionInterface>, local_streams)
+PROXY_METHOD0(rtc::scoped_refptr<StreamCollectionInterface>, remote_streams)
+PROXY_METHOD1(bool, AddStream, MediaStreamInterface*)
+PROXY_METHOD1(void, RemoveStream, MediaStreamInterface*)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpSenderInterface>>,
+              AddTrack,
+              rtc::scoped_refptr<MediaStreamTrackInterface>,
+              const std::vector<std::string>&)
+PROXY_METHOD1(bool, RemoveTrack, RtpSenderInterface*)
+PROXY_METHOD1(RTCError, RemoveTrackNew, rtc::scoped_refptr<RtpSenderInterface>)
+PROXY_METHOD1(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              rtc::scoped_refptr<MediaStreamTrackInterface>)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              rtc::scoped_refptr<MediaStreamTrackInterface>,
+              const RtpTransceiverInit&)
+PROXY_METHOD1(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              cricket::MediaType)
+PROXY_METHOD2(RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>,
+              AddTransceiver,
+              cricket::MediaType,
+              const RtpTransceiverInit&)
+PROXY_METHOD2(rtc::scoped_refptr<RtpSenderInterface>,
+              CreateSender,
+              const std::string&,
+              const std::string&)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpSenderInterface>>,
+                   GetSenders)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpReceiverInterface>>,
+                   GetReceivers)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<RtpTransceiverInterface>>,
+                   GetTransceivers)
+PROXY_METHOD3(bool,
+              GetStats,
+              StatsObserver*,
+              MediaStreamTrackInterface*,
+              StatsOutputLevel)
+PROXY_METHOD1(void, GetStats, RTCStatsCollectorCallback*)
+PROXY_METHOD2(void,
+              GetStats,
+              rtc::scoped_refptr<RtpSenderInterface>,
+              rtc::scoped_refptr<RTCStatsCollectorCallback>)
+PROXY_METHOD2(void,
+              GetStats,
+              rtc::scoped_refptr<RtpReceiverInterface>,
+              rtc::scoped_refptr<RTCStatsCollectorCallback>)
+PROXY_METHOD2(rtc::scoped_refptr<DataChannelInterface>,
+              CreateDataChannel,
+              const std::string&,
+              const DataChannelInit*)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, remote_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   current_local_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   current_remote_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   pending_local_description)
+PROXY_CONSTMETHOD0(const SessionDescriptionInterface*,
+                   pending_remote_description)
+PROXY_METHOD2(void,
+              CreateOffer,
+              CreateSessionDescriptionObserver*,
+              const RTCOfferAnswerOptions&)
+PROXY_METHOD2(void,
+              CreateAnswer,
+              CreateSessionDescriptionObserver*,
+              const RTCOfferAnswerOptions&)
+PROXY_METHOD2(void,
+              SetLocalDescription,
+              SetSessionDescriptionObserver*,
+              SessionDescriptionInterface*)
+PROXY_METHOD2(void,
+              SetRemoteDescription,
+              SetSessionDescriptionObserver*,
+              SessionDescriptionInterface*)
+PROXY_METHOD2(void,
+              SetRemoteDescription,
+              std::unique_ptr<SessionDescriptionInterface>,
+              rtc::scoped_refptr<SetRemoteDescriptionObserverInterface>)
+PROXY_METHOD0(PeerConnectionInterface::RTCConfiguration, GetConfiguration)
+PROXY_METHOD2(bool,
+              SetConfiguration,
+              const PeerConnectionInterface::RTCConfiguration&,
+              RTCError*)
+PROXY_METHOD1(bool,
+              SetConfiguration,
+              const PeerConnectionInterface::RTCConfiguration&)
+PROXY_METHOD1(bool, AddIceCandidate, const IceCandidateInterface*)
+PROXY_METHOD1(bool, RemoveIceCandidates, const std::vector<cricket::Candidate>&)
+PROXY_METHOD1(RTCError, SetBitrate, const BitrateSettings&)
+PROXY_METHOD1(void,
+              SetBitrateAllocationStrategy,
+              std::unique_ptr<rtc::BitrateAllocationStrategy>)
+PROXY_METHOD1(void, SetAudioPlayout, bool)
+PROXY_METHOD1(void, SetAudioRecording, bool)
+PROXY_METHOD1(rtc::scoped_refptr<DtlsTransportInterface>,
+              LookupDtlsTransportByMid,
+              const std::string&)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<SctpTransportInterface>, GetSctpTransport)
+PROXY_METHOD0(SignalingState, signaling_state)
+PROXY_METHOD0(IceConnectionState, ice_connection_state)
+PROXY_METHOD0(IceConnectionState, standardized_ice_connection_state)
+PROXY_METHOD0(PeerConnectionState, peer_connection_state)
+PROXY_METHOD0(IceGatheringState, ice_gathering_state)
+PROXY_METHOD2(bool, StartRtcEventLog, rtc::PlatformFile, int64_t)
+PROXY_METHOD2(bool,
+              StartRtcEventLog,
+              std::unique_ptr<RtcEventLogOutput>,
+              int64_t)
+PROXY_METHOD0(void, StopRtcEventLog)
+PROXY_METHOD0(void, Close)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_PEER_CONNECTION_PROXY_H_
diff --git a/api/proxy.h b/api/proxy.h
index 9916051..6627aac 100644
--- a/api/proxy.h
+++ b/api/proxy.h
@@ -53,12 +53,20 @@
 #define API_PROXY_H_
 
 #include <memory>
+#include <string>
 #include <utility>
 
+#include "api/scoped_refptr.h"
 #include "rtc_base/event.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/thread.h"
 
+namespace rtc {
+class Location;
+}
+
 namespace webrtc {
 
 template <typename R>
diff --git a/api/ref_counted_base.h b/api/ref_counted_base.h
new file mode 100644
index 0000000..a1761db
--- /dev/null
+++ b/api/ref_counted_base.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2017 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_REF_COUNTED_BASE_H_
+#define API_REF_COUNTED_BASE_H_
+
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/ref_counter.h"
+
+namespace rtc {
+
+class RefCountedBase {
+ public:
+  RefCountedBase() = default;
+
+  void AddRef() const { ref_count_.IncRef(); }
+  RefCountReleaseStatus Release() const {
+    const auto status = ref_count_.DecRef();
+    if (status == RefCountReleaseStatus::kDroppedLastRef) {
+      delete this;
+    }
+    return status;
+  }
+
+ protected:
+  virtual ~RefCountedBase() = default;
+
+ private:
+  mutable webrtc::webrtc_impl::RefCounter ref_count_{0};
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(RefCountedBase);
+};
+
+}  // namespace rtc
+
+#endif  // API_REF_COUNTED_BASE_H_
diff --git a/api/rtc_error.cc b/api/rtc_error.cc
new file mode 100644
index 0000000..51fd07f
--- /dev/null
+++ b/api/rtc_error.cc
@@ -0,0 +1,61 @@
+/*
+ *  Copyright 2017 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/rtc_error.h"
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/arraysize.h"
+
+namespace {
+
+const absl::string_view kRTCErrorTypeNames[] = {
+    "NONE",
+    "UNSUPPORTED_OPERATION",
+    "UNSUPPORTED_PARAMETER",
+    "INVALID_PARAMETER",
+    "INVALID_RANGE",
+    "SYNTAX_ERROR",
+    "INVALID_STATE",
+    "INVALID_MODIFICATION",
+    "NETWORK_ERROR",
+    "RESOURCE_EXHAUSTED",
+    "INTERNAL_ERROR",
+};
+static_assert(static_cast<int>(webrtc::RTCErrorType::INTERNAL_ERROR) ==
+                  (arraysize(kRTCErrorTypeNames) - 1),
+              "kRTCErrorTypeNames must have as many strings as RTCErrorType "
+              "has values.");
+
+}  // namespace
+
+namespace webrtc {
+
+RTCError::RTCError(RTCError&& other) = default;
+RTCError& RTCError::operator=(RTCError&& other) = default;
+
+// static
+RTCError RTCError::OK() {
+  return RTCError();
+}
+
+const char* RTCError::message() const {
+  return message_.c_str();
+}
+
+void RTCError::set_message(std::string message) {
+  message_ = std::move(message);
+}
+
+absl::string_view ToString(RTCErrorType error) {
+  int index = static_cast<int>(error);
+  return kRTCErrorTypeNames[index];
+}
+
+}  // namespace webrtc
diff --git a/api/rtc_error.h b/api/rtc_error.h
new file mode 100644
index 0000000..904a619
--- /dev/null
+++ b/api/rtc_error.h
@@ -0,0 +1,297 @@
+/*
+ *  Copyright 2017 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_RTC_ERROR_H_
+#define API_RTC_ERROR_H_
+
+#ifdef UNIT_TEST
+#include <ostream>
+#endif  // UNIT_TEST
+#include <string>
+#include <utility>  // For std::move.
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+// Enumeration to represent distinct classes of errors that an application
+// may wish to act upon differently. These roughly map to DOMExceptions or
+// RTCError "errorDetailEnum" values in the web API, as described in the
+// comments below.
+enum class RTCErrorType {
+  // No error.
+  NONE,
+
+  // An operation is valid, but currently unsupported.
+  // Maps to OperationError DOMException.
+  UNSUPPORTED_OPERATION,
+
+  // A supplied parameter is valid, but currently unsupported.
+  // Maps to OperationError DOMException.
+  UNSUPPORTED_PARAMETER,
+
+  // General error indicating that a supplied parameter is invalid.
+  // Maps to InvalidAccessError or TypeError DOMException depending on context.
+  INVALID_PARAMETER,
+
+  // Slightly more specific than INVALID_PARAMETER; a parameter's value was
+  // outside the allowed range.
+  // Maps to RangeError DOMException.
+  INVALID_RANGE,
+
+  // Slightly more specific than INVALID_PARAMETER; an error occurred while
+  // parsing string input.
+  // Maps to SyntaxError DOMException.
+  SYNTAX_ERROR,
+
+  // The object does not support this operation in its current state.
+  // Maps to InvalidStateError DOMException.
+  INVALID_STATE,
+
+  // An attempt was made to modify the object in an invalid way.
+  // Maps to InvalidModificationError DOMException.
+  INVALID_MODIFICATION,
+
+  // An error occurred within an underlying network protocol.
+  // Maps to NetworkError DOMException.
+  NETWORK_ERROR,
+
+  // Some resource has been exhausted; file handles, hardware resources, ports,
+  // etc.
+  // Maps to OperationError DOMException.
+  RESOURCE_EXHAUSTED,
+
+  // The operation failed due to an internal error.
+  // Maps to OperationError DOMException.
+  INTERNAL_ERROR,
+};
+
+// Roughly corresponds to RTCError in the web api. Holds an error type, a
+// message, and possibly additional information specific to that error.
+//
+// Doesn't contain anything beyond a type and message now, but will in the
+// future as more errors are implemented.
+class RTCError {
+ public:
+  // Constructors.
+
+  // Creates a "no error" error.
+  RTCError() {}
+  explicit RTCError(RTCErrorType type) : type_(type) {}
+
+  RTCError(RTCErrorType type, std::string message)
+      : type_(type), message_(std::move(message)) {}
+
+  // Delete the copy constructor and assignment operator; there aren't any use
+  // cases where you should need to copy an RTCError, as opposed to moving it.
+  // Can revisit this decision if use cases arise in the future.
+  RTCError(const RTCError& other) = delete;
+  RTCError& operator=(const RTCError& other) = delete;
+
+  // Move constructor and move-assignment operator.
+  RTCError(RTCError&& other);
+  RTCError& operator=(RTCError&& other);
+
+  // Identical to default constructed error.
+  //
+  // Preferred over the default constructor for code readability.
+  static RTCError OK();
+
+  // Error type.
+  RTCErrorType type() const { return type_; }
+  void set_type(RTCErrorType type) { type_ = type; }
+
+  // Human-readable message describing the error. Shouldn't be used for
+  // anything but logging/diagnostics, since messages are not guaranteed to be
+  // stable.
+  const char* message() const;
+
+  void set_message(std::string message);
+
+  // Convenience method for situations where you only care whether or not an
+  // error occurred.
+  bool ok() const { return type_ == RTCErrorType::NONE; }
+
+ private:
+  RTCErrorType type_ = RTCErrorType::NONE;
+  std::string message_;
+};
+
+// Outputs the error as a friendly string. Update this method when adding a new
+// error type.
+//
+// Only intended to be used for logging/diagnostics. The string_view points
+// to literal string that lives for the whole duration of the program.
+absl::string_view ToString(RTCErrorType error);
+
+#ifdef UNIT_TEST
+inline std::ostream& operator<<(  // no-presubmit-check TODO(webrtc:8982)
+    std::ostream& stream,         // no-presubmit-check TODO(webrtc:8982)
+    RTCErrorType error) {
+  return stream << ToString(error);
+}
+#endif  // 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
+// std::string.
+#define LOG_AND_RETURN_ERROR_EX(type, message, severity)           \
+  {                                                                \
+    RTC_DCHECK(type != RTCErrorType::NONE);                        \
+    RTC_LOG(severity) << message << " (" << ToString(type) << ")"; \
+    return webrtc::RTCError(type, message);                        \
+  }
+
+#define LOG_AND_RETURN_ERROR(type, message) \
+  LOG_AND_RETURN_ERROR_EX(type, message, LS_ERROR)
+
+// RTCErrorOr<T> is the union of an RTCError object and a T object. RTCErrorOr
+// models the concept of an object that is either a usable value, or an error
+// Status explaining why such a value is not present. To this end RTCErrorOr<T>
+// does not allow its RTCErrorType value to be RTCErrorType::NONE. This is
+// enforced by a debug check in most cases.
+//
+// The primary use-case for RTCErrorOr<T> is as the return value of a function
+// which may fail. For example, CreateRtpSender will fail if the parameters
+// could not be successfully applied at the media engine level, but if
+// successful will return a unique_ptr to an RtpSender.
+//
+// Example client usage for a RTCErrorOr<std::unique_ptr<T>>:
+//
+//  RTCErrorOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+//  if (result.ok()) {
+//    std::unique_ptr<Foo> foo = result.ConsumeValue();
+//    foo->DoSomethingCool();
+//  } else {
+//    RTC_LOG(LS_ERROR) << result.error();
+//  }
+//
+// Example factory implementation returning RTCErrorOr<std::unique_ptr<T>>:
+//
+//  RTCErrorOr<std::unique_ptr<Foo>> FooFactory::MakeNewFoo(int arg) {
+//    if (arg <= 0) {
+//      return RTCError(RTCErrorType::INVALID_RANGE, "Arg must be positive");
+//    } else {
+//      return std::unique_ptr<Foo>(new Foo(arg));
+//    }
+//  }
+//
+template <typename T>
+class RTCErrorOr {
+  // Used to convert between RTCErrorOr<Foo>/RtcErrorOr<Bar>, when an implicit
+  // conversion from Foo to Bar exists.
+  template <typename U>
+  friend class RTCErrorOr;
+
+ public:
+  typedef T element_type;
+
+  // Constructs a new RTCErrorOr with RTCErrorType::INTERNAL_ERROR error. This
+  // is marked 'explicit' to try to catch cases like 'return {};', where people
+  // think RTCErrorOr<std::vector<int>> will be initialized with an empty
+  // vector, instead of a RTCErrorType::INTERNAL_ERROR error.
+  RTCErrorOr() : error_(RTCErrorType::INTERNAL_ERROR) {}
+
+  // Constructs a new RTCErrorOr with the given non-ok error. After calling
+  // this constructor, calls to value() will DCHECK-fail.
+  //
+  // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return
+  // value, so it is convenient and sensible to be able to do 'return
+  // RTCError(...)' when the return type is RTCErrorOr<T>.
+  //
+  // REQUIRES: !error.ok(). This requirement is DCHECKed.
+  RTCErrorOr(RTCError&& error) : error_(std::move(error)) {  // NOLINT
+    RTC_DCHECK(!error.ok());
+  }
+
+  // Constructs a new RTCErrorOr with the given value. After calling this
+  // constructor, calls to value() will succeed, and calls to error() will
+  // return a default-constructed RTCError.
+  //
+  // NOTE: Not explicit - we want to use RTCErrorOr<T> as a return type
+  // so it is convenient and sensible to be able to do 'return T()'
+  // when the return type is RTCErrorOr<T>.
+  RTCErrorOr(const T& value) : value_(value) {}        // NOLINT
+  RTCErrorOr(T&& value) : value_(std::move(value)) {}  // NOLINT
+
+  // Delete the copy constructor and assignment operator; there aren't any use
+  // cases where you should need to copy an RTCErrorOr, as opposed to moving
+  // it. Can revisit this decision if use cases arise in the future.
+  RTCErrorOr(const RTCErrorOr& other) = delete;
+  RTCErrorOr& operator=(const RTCErrorOr& other) = delete;
+
+  // Move constructor and move-assignment operator.
+  //
+  // Visual Studio doesn't support "= default" with move constructors or
+  // assignment operators (even though they compile, they segfault), so define
+  // them explicitly.
+  RTCErrorOr(RTCErrorOr&& other)
+      : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
+  RTCErrorOr& operator=(RTCErrorOr&& other) {
+    error_ = std::move(other.error_);
+    value_ = std::move(other.value_);
+    return *this;
+  }
+
+  // Conversion constructor and assignment operator; T must be copy or move
+  // constructible from U.
+  template <typename U>
+  RTCErrorOr(RTCErrorOr<U> other)  // NOLINT
+      : error_(std::move(other.error_)), value_(std::move(other.value_)) {}
+  template <typename U>
+  RTCErrorOr& operator=(RTCErrorOr<U> other) {
+    error_ = std::move(other.error_);
+    value_ = std::move(other.value_);
+    return *this;
+  }
+
+  // Returns a reference to our error. If this contains a T, then returns
+  // default-constructed RTCError.
+  const RTCError& error() const { return error_; }
+
+  // Moves the error. Can be useful if, say "CreateFoo" returns an
+  // RTCErrorOr<Foo>, and internally calls "CreateBar" which returns an
+  // RTCErrorOr<Bar>, and wants to forward the error up the stack.
+  RTCError MoveError() { return std::move(error_); }
+
+  // Returns this->error().ok()
+  bool ok() const { return error_.ok(); }
+
+  // Returns a reference to our current value, or DCHECK-fails if !this->ok().
+  //
+  // Can be convenient for the implementation; for example, a method may want
+  // to access the value in some way before returning it to the next method on
+  // the stack.
+  const T& value() const {
+    RTC_DCHECK(ok());
+    return value_;
+  }
+  T& value() {
+    RTC_DCHECK(ok());
+    return value_;
+  }
+
+  // Moves our current value out of this object and returns it, or DCHECK-fails
+  // if !this->ok().
+  T MoveValue() {
+    RTC_DCHECK(ok());
+    return std::move(value_);
+  }
+
+ private:
+  RTCError error_;
+  T value_;
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTC_ERROR_H_
diff --git a/api/rtc_error_unittest.cc b/api/rtc_error_unittest.cc
new file mode 100644
index 0000000..e9beb00
--- /dev/null
+++ b/api/rtc_error_unittest.cc
@@ -0,0 +1,241 @@
+/*
+ *  Copyright 2017 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 <utility>
+
+#include "api/rtc_error.h"
+#include "test/gtest.h"
+
+namespace {
+
+const int kDefaultMoveOnlyIntValue = 0xbadf00d;
+
+// Class that has no copy constructor, ensuring that RTCErrorOr can
+struct MoveOnlyInt {
+  MoveOnlyInt() {}
+  explicit MoveOnlyInt(int value) : value(value) {}
+  MoveOnlyInt(const MoveOnlyInt& other) = delete;
+  MoveOnlyInt& operator=(const MoveOnlyInt& other) = delete;
+  MoveOnlyInt(MoveOnlyInt&& other) : value(other.value) {}
+  MoveOnlyInt& operator=(MoveOnlyInt&& other) {
+    value = other.value;
+    return *this;
+  }
+
+  int value = kDefaultMoveOnlyIntValue;
+};
+
+// Same as above. Used to test conversion from RTCErrorOr<A> to RTCErrorOr<B>
+// when A can be converted to B.
+struct MoveOnlyInt2 {
+  MoveOnlyInt2() {}
+  explicit MoveOnlyInt2(int value) : value(value) {}
+  MoveOnlyInt2(const MoveOnlyInt2& other) = delete;
+  MoveOnlyInt2& operator=(const MoveOnlyInt2& other) = delete;
+  MoveOnlyInt2(MoveOnlyInt2&& other) : value(other.value) {}
+  MoveOnlyInt2& operator=(MoveOnlyInt2&& other) {
+    value = other.value;
+    return *this;
+  }
+
+  explicit MoveOnlyInt2(MoveOnlyInt&& other) : value(other.value) {}
+  MoveOnlyInt2& operator=(MoveOnlyInt&& other) {
+    value = other.value;
+    return *this;
+  }
+
+  int value = kDefaultMoveOnlyIntValue;
+};
+
+}  // namespace
+
+namespace webrtc {
+
+// Test that the default constructor creates a "no error" error.
+TEST(RTCErrorTest, DefaultConstructor) {
+  RTCError e;
+  EXPECT_EQ(RTCErrorType::NONE, e.type());
+  EXPECT_EQ(std::string(), e.message());
+  EXPECT_TRUE(e.ok());
+}
+
+TEST(RTCErrorTest, NormalConstructors) {
+  RTCError a(RTCErrorType::INVALID_PARAMETER);
+  EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, a.type());
+  EXPECT_EQ(std::string(), a.message());
+
+  // Constructor that takes const char* message.
+  RTCError b(RTCErrorType::UNSUPPORTED_PARAMETER, "foobar");
+  EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, b.type());
+  EXPECT_EQ(std::string("foobar"), b.message());
+
+  // Constructor that takes std::string message.
+  RTCError c(RTCErrorType::INVALID_RANGE, std::string("new"));
+  EXPECT_EQ(RTCErrorType::INVALID_RANGE, c.type());
+  EXPECT_EQ(std::string("new"), c.message());
+}
+
+TEST(RTCErrorTest, MoveConstructor) {
+  // Static string.
+  RTCError a(RTCErrorType::INVALID_PARAMETER, "foo");
+  RTCError b(std::move(a));
+  EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, b.type());
+  EXPECT_EQ(std::string("foo"), b.message());
+
+  // Non-static string.
+  RTCError c(RTCErrorType::UNSUPPORTED_PARAMETER, std::string("bar"));
+  RTCError d(std::move(c));
+  EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, d.type());
+  EXPECT_EQ(std::string("bar"), d.message());
+}
+
+TEST(RTCErrorTest, MoveAssignment) {
+  // Try all combinations of "is static string"/"is non-static string" moves.
+  RTCError e(RTCErrorType::INVALID_PARAMETER, "foo");
+
+  e = RTCError(RTCErrorType::UNSUPPORTED_PARAMETER, "bar");
+  EXPECT_EQ(RTCErrorType::UNSUPPORTED_PARAMETER, e.type());
+  EXPECT_EQ(std::string("bar"), e.message());
+
+  e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("baz"));
+  EXPECT_EQ(std::string("baz"), e.message());
+
+  e = RTCError(RTCErrorType::SYNTAX_ERROR, std::string("another"));
+  EXPECT_EQ(std::string("another"), e.message());
+
+  e = RTCError(RTCErrorType::SYNTAX_ERROR, "last");
+  EXPECT_EQ(std::string("last"), e.message());
+}
+
+// Test that the error returned by RTCError::OK() is a "no error" error.
+TEST(RTCErrorTest, OKConstant) {
+  RTCError ok = RTCError::OK();
+  EXPECT_EQ(RTCErrorType::NONE, ok.type());
+  EXPECT_EQ(std::string(), ok.message());
+  EXPECT_TRUE(ok.ok());
+}
+
+// Test that "error.ok()" behaves as expected.
+TEST(RTCErrorTest, OkMethod) {
+  RTCError success;
+  RTCError failure(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_TRUE(success.ok());
+  EXPECT_FALSE(failure.ok());
+}
+
+// Test that a message can be set using either static const strings or
+// std::strings.
+TEST(RTCErrorTest, SetMessage) {
+  RTCError e;
+  // Try all combinations of "is static string"/"is non-static string" calls.
+  e.set_message("foo");
+  EXPECT_EQ(std::string("foo"), e.message());
+
+  e.set_message("bar");
+  EXPECT_EQ(std::string("bar"), e.message());
+
+  e.set_message(std::string("string"));
+  EXPECT_EQ(std::string("string"), e.message());
+
+  e.set_message(std::string("more"));
+  EXPECT_EQ(std::string("more"), e.message());
+
+  e.set_message("love to test");
+  EXPECT_EQ(std::string("love to test"), e.message());
+}
+
+// Test that the default constructor creates an "INTERNAL_ERROR".
+TEST(RTCErrorOrTest, DefaultConstructor) {
+  RTCErrorOr<MoveOnlyInt> e;
+  EXPECT_EQ(RTCErrorType::INTERNAL_ERROR, e.error().type());
+}
+
+// Test that an RTCErrorOr can be implicitly constructed from a value.
+TEST(RTCErrorOrTest, ImplicitValueConstructor) {
+  RTCErrorOr<MoveOnlyInt> e = [] { return MoveOnlyInt(100); }();
+  EXPECT_EQ(100, e.value().value);
+}
+
+// Test that an RTCErrorOr can be implicitly constructed from an RTCError.
+TEST(RTCErrorOrTest, ImplicitErrorConstructor) {
+  RTCErrorOr<MoveOnlyInt> e = [] {
+    return RTCError(RTCErrorType::SYNTAX_ERROR);
+  }();
+  EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, e.error().type());
+}
+
+TEST(RTCErrorOrTest, MoveConstructor) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
+  RTCErrorOr<MoveOnlyInt> b(std::move(a));
+  EXPECT_EQ(5, b.value().value);
+}
+
+TEST(RTCErrorOrTest, MoveAssignment) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
+  RTCErrorOr<MoveOnlyInt> b(MoveOnlyInt(10));
+  a = std::move(b);
+  EXPECT_EQ(10, a.value().value);
+}
+
+TEST(RTCErrorOrTest, ConversionConstructor) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(1));
+  RTCErrorOr<MoveOnlyInt2> b(std::move(a));
+}
+
+TEST(RTCErrorOrTest, ConversionAssignment) {
+  RTCErrorOr<MoveOnlyInt> a(MoveOnlyInt(5));
+  RTCErrorOr<MoveOnlyInt2> b(MoveOnlyInt2(10));
+  b = std::move(a);
+  EXPECT_EQ(5, b.value().value);
+}
+
+TEST(RTCErrorOrTest, OkMethod) {
+  RTCErrorOr<int> success(1337);
+  RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_TRUE(success.ok());
+  EXPECT_FALSE(error.ok());
+}
+
+TEST(RTCErrorOrTest, MoveError) {
+  RTCErrorOr<int> e({RTCErrorType::SYNTAX_ERROR, "message"});
+  RTCError err = e.MoveError();
+  EXPECT_EQ(RTCErrorType::SYNTAX_ERROR, err.type());
+  EXPECT_EQ(std::string("message"), err.message());
+}
+
+TEST(RTCErrorOrTest, MoveValue) {
+  RTCErrorOr<MoveOnlyInt> e(MoveOnlyInt(88));
+  MoveOnlyInt value = e.MoveValue();
+  EXPECT_EQ(88, value.value);
+}
+
+// Death tests.
+// Disabled on Android because death tests misbehave on Android, see
+// base/test/gtest_util.h.
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+TEST(RTCErrorOrDeathTest, ConstructWithOkError) {
+  RTCErrorOr<int> err;
+  EXPECT_DEATH(err = RTCError::OK(), "");
+}
+
+TEST(RTCErrorOrDeathTest, DereferenceErrorValue) {
+  RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_DEATH(error.value(), "");
+}
+
+TEST(RTCErrorOrDeathTest, MoveErrorValue) {
+  RTCErrorOr<int> error = RTCError(RTCErrorType::INTERNAL_ERROR);
+  EXPECT_DEATH(error.MoveValue(), "");
+}
+
+#endif  // RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
+
+}  // namespace webrtc
diff --git a/api/rtc_event_log_output.h b/api/rtc_event_log_output.h
new file mode 100644
index 0000000..92fb9e8
--- /dev/null
+++ b/api/rtc_event_log_output.h
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2017 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_RTC_EVENT_LOG_OUTPUT_H_
+#define API_RTC_EVENT_LOG_OUTPUT_H_
+
+#include <string>
+
+namespace webrtc {
+
+// NOTE: This class is still under development and may change without notice.
+class RtcEventLogOutput {
+ public:
+  virtual ~RtcEventLogOutput() = default;
+
+  // An output normally starts out active, though that might not always be
+  // the case (e.g. failed to open a file for writing).
+  // Once an output has become inactive (e.g. maximum file size reached), it can
+  // never become active again.
+  virtual bool IsActive() const = 0;
+
+  // Write encoded events to an output. Returns true if the output was
+  // successfully written in its entirety. Otherwise, no guarantee is given
+  // about how much data was written, if any. The output sink becomes inactive
+  // after the first time |false| is returned. Write() may not be called on
+  // an inactive output sink.
+  virtual bool Write(const std::string& output) = 0;
+
+  // Indicates that buffers should be written to disk if applicable.
+  virtual void Flush() {}
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTC_EVENT_LOG_OUTPUT_H_
diff --git a/api/rtp_headers.h b/api/rtp_headers.h
index c766899..8ab560c 100644
--- a/api/rtp_headers.h
+++ b/api/rtp_headers.h
@@ -82,6 +82,17 @@
 // Mid represents RtpMid which is a string.
 typedef StringRtpHeaderExtension Mid;
 
+struct FeedbackRequest {
+  // Determines whether the recv delta as specified in
+  // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
+  // should be included.
+  bool include_timestamps;
+  // Include feedback of received packets in the range [sequence_number -
+  // sequence_count + 1, sequence_number]. That is, no feedback will be sent if
+  // sequence_count is zero.
+  int sequence_count;
+};
+
 struct RTPHeaderExtension {
   RTPHeaderExtension();
   RTPHeaderExtension(const RTPHeaderExtension& other);
@@ -93,6 +104,7 @@
   uint32_t absoluteSendTime;
   bool hasTransportSequenceNumber;
   uint16_t transportSequenceNumber;
+  absl::optional<FeedbackRequest> feedback_request;
 
   // Audio Level includes both level in dBov and voiced/unvoiced bit. See:
   // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/
diff --git a/api/rtp_parameters.cc b/api/rtp_parameters.cc
new file mode 100644
index 0000000..9ba2423
--- /dev/null
+++ b/api/rtp_parameters.cc
@@ -0,0 +1,238 @@
+/*
+ *  Copyright (c) 2017 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/rtp_parameters.h"
+
+#include <algorithm>
+#include <string>
+
+#include "api/array_view.h"
+#include "rtc_base/strings/string_builder.h"
+
+namespace webrtc {
+
+const double kDefaultBitratePriority = 1.0;
+
+RtcpFeedback::RtcpFeedback() = default;
+RtcpFeedback::RtcpFeedback(RtcpFeedbackType type) : type(type) {}
+RtcpFeedback::RtcpFeedback(RtcpFeedbackType type,
+                           RtcpFeedbackMessageType message_type)
+    : type(type), message_type(message_type) {}
+RtcpFeedback::RtcpFeedback(const RtcpFeedback& rhs) = default;
+RtcpFeedback::~RtcpFeedback() = default;
+
+RtpCodecCapability::RtpCodecCapability() = default;
+RtpCodecCapability::~RtpCodecCapability() = default;
+
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability() = default;
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
+    const std::string& uri)
+    : uri(uri) {}
+RtpHeaderExtensionCapability::RtpHeaderExtensionCapability(
+    const std::string& uri,
+    int preferred_id)
+    : uri(uri), preferred_id(preferred_id) {}
+RtpHeaderExtensionCapability::~RtpHeaderExtensionCapability() = default;
+
+RtpExtension::RtpExtension() = default;
+RtpExtension::RtpExtension(const std::string& uri, int id) : uri(uri), id(id) {}
+RtpExtension::RtpExtension(const std::string& uri, int id, bool encrypt)
+    : uri(uri), id(id), encrypt(encrypt) {}
+RtpExtension::~RtpExtension() = default;
+
+RtpFecParameters::RtpFecParameters() = default;
+RtpFecParameters::RtpFecParameters(FecMechanism mechanism)
+    : mechanism(mechanism) {}
+RtpFecParameters::RtpFecParameters(FecMechanism mechanism, uint32_t ssrc)
+    : ssrc(ssrc), mechanism(mechanism) {}
+RtpFecParameters::RtpFecParameters(const RtpFecParameters& rhs) = default;
+RtpFecParameters::~RtpFecParameters() = default;
+
+RtpRtxParameters::RtpRtxParameters() = default;
+RtpRtxParameters::RtpRtxParameters(uint32_t ssrc) : ssrc(ssrc) {}
+RtpRtxParameters::RtpRtxParameters(const RtpRtxParameters& rhs) = default;
+RtpRtxParameters::~RtpRtxParameters() = default;
+
+RtpEncodingParameters::RtpEncodingParameters() = default;
+RtpEncodingParameters::RtpEncodingParameters(const RtpEncodingParameters& rhs) =
+    default;
+RtpEncodingParameters::~RtpEncodingParameters() = default;
+
+RtpCodecParameters::RtpCodecParameters() = default;
+RtpCodecParameters::RtpCodecParameters(const RtpCodecParameters& rhs) = default;
+RtpCodecParameters::~RtpCodecParameters() = default;
+
+RtpCapabilities::RtpCapabilities() = default;
+RtpCapabilities::~RtpCapabilities() = default;
+
+RtcpParameters::RtcpParameters() = default;
+RtcpParameters::RtcpParameters(const RtcpParameters& rhs) = default;
+RtcpParameters::~RtcpParameters() = default;
+
+RtpParameters::RtpParameters() = default;
+RtpParameters::RtpParameters(const RtpParameters& rhs) = default;
+RtpParameters::~RtpParameters() = default;
+
+std::string RtpExtension::ToString() const {
+  char buf[256];
+  rtc::SimpleStringBuilder sb(buf);
+  sb << "{uri: " << uri;
+  sb << ", id: " << id;
+  if (encrypt) {
+    sb << ", encrypt";
+  }
+  sb << '}';
+  return sb.str();
+}
+
+const char RtpExtension::kAudioLevelUri[] =
+    "urn:ietf:params:rtp-hdrext:ssrc-audio-level";
+
+const char RtpExtension::kTimestampOffsetUri[] =
+    "urn:ietf:params:rtp-hdrext:toffset";
+
+const char RtpExtension::kAbsSendTimeUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
+
+const char RtpExtension::kVideoRotationUri[] = "urn:3gpp:video-orientation";
+
+const char RtpExtension::kTransportSequenceNumberUri[] =
+    "http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01";
+const char RtpExtension::kTransportSequenceNumberV2Uri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/transport-wide-cc-02";
+
+// This extension allows applications to adaptively limit the playout delay
+// on frames as per the current needs. For example, a gaming application
+// has very different needs on end-to-end delay compared to a video-conference
+// application.
+const char RtpExtension::kPlayoutDelayUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/playout-delay";
+
+const char RtpExtension::kVideoContentTypeUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/video-content-type";
+
+const char RtpExtension::kVideoTimingUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/video-timing";
+
+const char RtpExtension::kMidUri[] = "urn:ietf:params:rtp-hdrext:sdes:mid";
+
+const char RtpExtension::kFrameMarkingUri[] =
+    "http://tools.ietf.org/html/draft-ietf-avtext-framemarking-07";
+
+const char RtpExtension::kGenericFrameDescriptorUri00[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/generic-frame-descriptor-00";
+const char RtpExtension::kGenericFrameDescriptorUri01[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/generic-frame-descriptor-01";
+const char RtpExtension::kGenericFrameDescriptorUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/generic-frame-descriptor-00";
+
+const char RtpExtension::kEncryptHeaderExtensionsUri[] =
+    "urn:ietf:params:rtp-hdrext:encrypt";
+
+const char RtpExtension::kColorSpaceUri[] =
+    "http://www.webrtc.org/experiments/rtp-hdrext/color-space";
+
+const char RtpExtension::kRidUri[] =
+    "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
+
+const char RtpExtension::kRepairedRidUri[] =
+    "urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id";
+
+constexpr int RtpExtension::kMinId;
+constexpr int RtpExtension::kMaxId;
+constexpr int RtpExtension::kMaxValueSize;
+constexpr int RtpExtension::kOneByteHeaderExtensionMaxId;
+constexpr int RtpExtension::kOneByteHeaderExtensionMaxValueSize;
+
+bool RtpExtension::IsSupportedForAudio(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kAudioLevelUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
+         uri == webrtc::RtpExtension::kMidUri ||
+         uri == webrtc::RtpExtension::kRidUri ||
+         uri == webrtc::RtpExtension::kRepairedRidUri;
+}
+
+bool RtpExtension::IsSupportedForVideo(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kTimestampOffsetUri ||
+         uri == webrtc::RtpExtension::kAbsSendTimeUri ||
+         uri == webrtc::RtpExtension::kVideoRotationUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
+         uri == webrtc::RtpExtension::kPlayoutDelayUri ||
+         uri == webrtc::RtpExtension::kVideoContentTypeUri ||
+         uri == webrtc::RtpExtension::kVideoTimingUri ||
+         uri == webrtc::RtpExtension::kMidUri ||
+         uri == webrtc::RtpExtension::kFrameMarkingUri ||
+         uri == webrtc::RtpExtension::kGenericFrameDescriptorUri00 ||
+         uri == webrtc::RtpExtension::kGenericFrameDescriptorUri01 ||
+         uri == webrtc::RtpExtension::kColorSpaceUri ||
+         uri == webrtc::RtpExtension::kRidUri ||
+         uri == webrtc::RtpExtension::kRepairedRidUri;
+}
+
+bool RtpExtension::IsEncryptionSupported(const std::string& uri) {
+  return uri == webrtc::RtpExtension::kAudioLevelUri ||
+         uri == webrtc::RtpExtension::kTimestampOffsetUri ||
+#if !defined(ENABLE_EXTERNAL_AUTH)
+         // TODO(jbauch): Figure out a way to always allow "kAbsSendTimeUri"
+         // here and filter out later if external auth is really used in
+         // srtpfilter. External auth is used by Chromium and replaces the
+         // extension header value of "kAbsSendTimeUri", so it must not be
+         // encrypted (which can't be done by Chromium).
+         uri == webrtc::RtpExtension::kAbsSendTimeUri ||
+#endif
+         uri == webrtc::RtpExtension::kVideoRotationUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberUri ||
+         uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri ||
+         uri == webrtc::RtpExtension::kPlayoutDelayUri ||
+         uri == webrtc::RtpExtension::kVideoContentTypeUri ||
+         uri == webrtc::RtpExtension::kMidUri ||
+         uri == webrtc::RtpExtension::kRidUri ||
+         uri == webrtc::RtpExtension::kRepairedRidUri;
+}
+
+const RtpExtension* RtpExtension::FindHeaderExtensionByUri(
+    const std::vector<RtpExtension>& extensions,
+    const std::string& uri) {
+  for (const auto& extension : extensions) {
+    if (extension.uri == uri) {
+      return &extension;
+    }
+  }
+  return nullptr;
+}
+
+std::vector<RtpExtension> RtpExtension::FilterDuplicateNonEncrypted(
+    const std::vector<RtpExtension>& extensions) {
+  std::vector<RtpExtension> filtered;
+  for (auto extension = extensions.begin(); extension != extensions.end();
+       ++extension) {
+    if (extension->encrypt) {
+      filtered.push_back(*extension);
+      continue;
+    }
+
+    // Only add non-encrypted extension if no encrypted with the same URI
+    // is also present...
+    if (std::find_if(extension + 1, extensions.end(),
+                     [extension](const RtpExtension& check) {
+                       return extension->uri == check.uri;
+                     }) != extensions.end()) {
+      continue;
+    }
+
+    // ...and has not been added before.
+    if (!FindHeaderExtensionByUri(filtered, extension->uri)) {
+      filtered.push_back(*extension);
+    }
+  }
+  return filtered;
+}
+}  // namespace webrtc
diff --git a/api/rtp_parameters.h b/api/rtp_parameters.h
new file mode 100644
index 0000000..b7d7702
--- /dev/null
+++ b/api/rtp_parameters.h
@@ -0,0 +1,664 @@
+/*
+ *  Copyright 2015 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_RTP_PARAMETERS_H_
+#define API_RTP_PARAMETERS_H_
+
+#include <stdint.h>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/media_types.h"
+#include "rtc_base/system/rtc_export.h"
+
+namespace webrtc {
+
+// These structures are intended to mirror those defined by:
+// http://draft.ortc.org/#rtcrtpdictionaries*
+// Contains everything specified as of 2017 Jan 24.
+//
+// They are used when retrieving or modifying the parameters of an
+// RtpSender/RtpReceiver, or retrieving capabilities.
+//
+// Note on conventions: Where ORTC may use "octet", "short" and "unsigned"
+// types, we typically use "int", in keeping with our style guidelines. The
+// parameter's actual valid range will be enforced when the parameters are set,
+// rather than when the parameters struct is built. An exception is made for
+// SSRCs, since they use the full unsigned 32-bit range, and aren't expected to
+// be used for any numeric comparisons/operations.
+//
+// Additionally, where ORTC uses strings, we may use enums for things that have
+// a fixed number of supported values. However, for things that can be extended
+// (such as codecs, by providing an external encoder factory), a string
+// identifier is used.
+
+enum class FecMechanism {
+  RED,
+  RED_AND_ULPFEC,
+  FLEXFEC,
+};
+
+// Used in RtcpFeedback struct.
+enum class RtcpFeedbackType {
+  CCM,
+  NACK,
+  REMB,  // "goog-remb"
+  TRANSPORT_CC,
+};
+
+// Used in RtcpFeedback struct when type is NACK or CCM.
+enum class RtcpFeedbackMessageType {
+  // Equivalent to {type: "nack", parameter: undefined} in ORTC.
+  GENERIC_NACK,
+  PLI,  // Usable with NACK.
+  FIR,  // Usable with CCM.
+};
+
+enum class DtxStatus {
+  DISABLED,
+  ENABLED,
+};
+
+// Based on the spec in
+// https://w3c.github.io/webrtc-pc/#idl-def-rtcdegradationpreference.
+// These options are enforced on a best-effort basis. For instance, all of
+// these options may suffer some frame drops in order to avoid queuing.
+// TODO(sprang): Look into possibility of more strictly enforcing the
+// maintain-framerate option.
+// TODO(deadbeef): Default to "balanced", as the spec indicates?
+enum class DegradationPreference {
+  // Don't take any actions based on over-utilization signals. Not part of the
+  // web API.
+  DISABLED,
+  // On over-use, request lower frame rate, possibly causing frame drops.
+  MAINTAIN_FRAMERATE,
+  // On over-use, request lower resolution, possibly causing down-scaling.
+  MAINTAIN_RESOLUTION,
+  // Try to strike a "pleasing" balance between frame rate or resolution.
+  BALANCED,
+};
+
+extern const double kDefaultBitratePriority;
+
+struct RtcpFeedback {
+  RtcpFeedbackType type = RtcpFeedbackType::CCM;
+
+  // Equivalent to ORTC "parameter" field with slight differences:
+  // 1. It's an enum instead of a string.
+  // 2. Generic NACK feedback is represented by a GENERIC_NACK message type,
+  //    rather than an unset "parameter" value.
+  absl::optional<RtcpFeedbackMessageType> message_type;
+
+  // Constructors for convenience.
+  RtcpFeedback();
+  explicit RtcpFeedback(RtcpFeedbackType type);
+  RtcpFeedback(RtcpFeedbackType type, RtcpFeedbackMessageType message_type);
+  RtcpFeedback(const RtcpFeedback&);
+  ~RtcpFeedback();
+
+  bool operator==(const RtcpFeedback& o) const {
+    return type == o.type && message_type == o.message_type;
+  }
+  bool operator!=(const RtcpFeedback& o) const { return !(*this == o); }
+};
+
+// RtpCodecCapability is to RtpCodecParameters as RtpCapabilities is to
+// RtpParameters. This represents the static capabilities of an endpoint's
+// implementation of a codec.
+struct RtpCodecCapability {
+  RtpCodecCapability();
+  ~RtpCodecCapability();
+
+  // Build MIME "type/subtype" string from |name| and |kind|.
+  std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
+
+  // Used to identify the codec. Equivalent to MIME subtype.
+  std::string name;
+
+  // The media type of this codec. Equivalent to MIME top-level type.
+  cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
+
+  // Clock rate in Hertz. If unset, the codec is applicable to any clock rate.
+  absl::optional<int> clock_rate;
+
+  // Default payload type for this codec. Mainly needed for codecs that use
+  // that have statically assigned payload types.
+  absl::optional<int> preferred_payload_type;
+
+  // Maximum packetization time supported by an RtpReceiver for this codec.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> max_ptime;
+
+  // Preferred packetization time for an RtpReceiver or RtpSender of this
+  // codec.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> ptime;
+
+  // The number of audio channels supported. Unused for video codecs.
+  absl::optional<int> num_channels;
+
+  // Feedback mechanisms supported for this codec.
+  std::vector<RtcpFeedback> rtcp_feedback;
+
+  // Codec-specific parameters that must be signaled to the remote party.
+  //
+  // Corresponds to "a=fmtp" parameters in SDP.
+  //
+  // Contrary to ORTC, these parameters are named using all lowercase strings.
+  // This helps make the mapping to SDP simpler, if an application is using
+  // SDP. Boolean values are represented by the string "1".
+  std::unordered_map<std::string, std::string> parameters;
+
+  // Codec-specific parameters that may optionally be signaled to the remote
+  // party.
+  // TODO(deadbeef): Not implemented.
+  std::unordered_map<std::string, std::string> options;
+
+  // Maximum number of temporal layer extensions supported by this codec.
+  // For example, a value of 1 indicates that 2 total layers are supported.
+  // TODO(deadbeef): Not implemented.
+  int max_temporal_layer_extensions = 0;
+
+  // Maximum number of spatial layer extensions supported by this codec.
+  // For example, a value of 1 indicates that 2 total layers are supported.
+  // TODO(deadbeef): Not implemented.
+  int max_spatial_layer_extensions = 0;
+
+  // Whether the implementation can send/receive SVC layers with distinct
+  // SSRCs. Always false for audio codecs. True for video codecs that support
+  // scalable video coding with MRST.
+  // TODO(deadbeef): Not implemented.
+  bool svc_multi_stream_support = false;
+
+  bool operator==(const RtpCodecCapability& o) const {
+    return name == o.name && kind == o.kind && clock_rate == o.clock_rate &&
+           preferred_payload_type == o.preferred_payload_type &&
+           max_ptime == o.max_ptime && ptime == o.ptime &&
+           num_channels == o.num_channels && rtcp_feedback == o.rtcp_feedback &&
+           parameters == o.parameters && options == o.options &&
+           max_temporal_layer_extensions == o.max_temporal_layer_extensions &&
+           max_spatial_layer_extensions == o.max_spatial_layer_extensions &&
+           svc_multi_stream_support == o.svc_multi_stream_support;
+  }
+  bool operator!=(const RtpCodecCapability& o) const { return !(*this == o); }
+};
+
+// Used in RtpCapabilities; represents the capabilities/preferences of an
+// implementation for a header extension.
+//
+// Just called "RtpHeaderExtension" in ORTC, but the "Capability" suffix was
+// added here for consistency and to avoid confusion with
+// RtpHeaderExtensionParameters.
+//
+// Note that ORTC includes a "kind" field, but we omit this because it's
+// redundant; if you call "RtpReceiver::GetCapabilities(MEDIA_TYPE_AUDIO)",
+// you know you're getting audio capabilities.
+struct RtpHeaderExtensionCapability {
+  // URI of this extension, as defined in RFC8285.
+  std::string uri;
+
+  // Preferred value of ID that goes in the packet.
+  absl::optional<int> preferred_id;
+
+  // If true, it's preferred that the value in the header is encrypted.
+  // TODO(deadbeef): Not implemented.
+  bool preferred_encrypt = false;
+
+  // Constructors for convenience.
+  RtpHeaderExtensionCapability();
+  explicit RtpHeaderExtensionCapability(const std::string& uri);
+  RtpHeaderExtensionCapability(const std::string& uri, int preferred_id);
+  ~RtpHeaderExtensionCapability();
+
+  bool operator==(const RtpHeaderExtensionCapability& o) const {
+    return uri == o.uri && preferred_id == o.preferred_id &&
+           preferred_encrypt == o.preferred_encrypt;
+  }
+  bool operator!=(const RtpHeaderExtensionCapability& o) const {
+    return !(*this == o);
+  }
+};
+
+// RTP header extension, see RFC8285.
+struct RtpExtension {
+  RtpExtension();
+  RtpExtension(const std::string& uri, int id);
+  RtpExtension(const std::string& uri, int id, bool encrypt);
+  ~RtpExtension();
+  std::string ToString() const;
+  bool operator==(const RtpExtension& rhs) const {
+    return uri == rhs.uri && id == rhs.id && encrypt == rhs.encrypt;
+  }
+  static bool IsSupportedForAudio(const std::string& uri);
+  static bool IsSupportedForVideo(const std::string& uri);
+  // Return "true" if the given RTP header extension URI may be encrypted.
+  static bool IsEncryptionSupported(const std::string& uri);
+
+  // Returns the named header extension if found among all extensions,
+  // nullptr otherwise.
+  static const RtpExtension* FindHeaderExtensionByUri(
+      const std::vector<RtpExtension>& extensions,
+      const std::string& uri);
+
+  // Return a list of RTP header extensions with the non-encrypted extensions
+  // removed if both the encrypted and non-encrypted extension is present for
+  // the same URI.
+  static std::vector<RtpExtension> FilterDuplicateNonEncrypted(
+      const std::vector<RtpExtension>& extensions);
+
+  // Header extension for audio levels, as defined in:
+  // http://tools.ietf.org/html/draft-ietf-avtext-client-to-mixer-audio-level-03
+  static const char kAudioLevelUri[];
+
+  // Header extension for RTP timestamp offset, see RFC 5450 for details:
+  // http://tools.ietf.org/html/rfc5450
+  static const char kTimestampOffsetUri[];
+
+  // Header extension for absolute send time, see url for details:
+  // http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+  static const char kAbsSendTimeUri[];
+
+  // Header extension for coordination of video orientation, see url for
+  // details:
+  // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/ts_126114v120700p.pdf
+  static const char kVideoRotationUri[];
+
+  // Header extension for video content type. E.g. default or screenshare.
+  static const char kVideoContentTypeUri[];
+
+  // Header extension for video timing.
+  static const char kVideoTimingUri[];
+
+  // Header extension for video frame marking.
+  static const char kFrameMarkingUri[];
+
+  // Experimental codec agnostic frame descriptor.
+  static const char kGenericFrameDescriptorUri00[];
+  static const char kGenericFrameDescriptorUri01[];
+  // TODO(bugs.webrtc.org/10243): Remove once dependencies have been updated.
+  static const char kGenericFrameDescriptorUri[];
+
+  // Header extension for transport sequence number, see url for details:
+  // http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions
+  static const char kTransportSequenceNumberUri[];
+  static const char kTransportSequenceNumberV2Uri[];
+
+  static const char kPlayoutDelayUri[];
+
+  // Header extension for identifying media section within a transport.
+  // https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-49#section-15
+  static const char kMidUri[];
+
+  // Encryption of Header Extensions, see RFC 6904 for details:
+  // https://tools.ietf.org/html/rfc6904
+  static const char kEncryptHeaderExtensionsUri[];
+
+  // Header extension for color space information.
+  static const char kColorSpaceUri[];
+
+  // Header extension for RIDs and Repaired RIDs
+  // https://tools.ietf.org/html/draft-ietf-avtext-rid-09
+  // https://tools.ietf.org/html/draft-ietf-mmusic-rid-15
+  static const char kRidUri[];
+  static const char kRepairedRidUri[];
+
+  // Inclusive min and max IDs for two-byte header extensions and one-byte
+  // header extensions, per RFC8285 Section 4.2-4.3.
+  static constexpr int kMinId = 1;
+  static constexpr int kMaxId = 255;
+  static constexpr int kMaxValueSize = 255;
+  static constexpr int kOneByteHeaderExtensionMaxId = 14;
+  static constexpr int kOneByteHeaderExtensionMaxValueSize = 16;
+
+  std::string uri;
+  int id = 0;
+  bool encrypt = false;
+};
+
+// TODO(deadbeef): This is missing the "encrypt" flag, which is unimplemented.
+typedef RtpExtension RtpHeaderExtensionParameters;
+
+struct RtpFecParameters {
+  // If unset, a value is chosen by the implementation.
+  // Works just like RtpEncodingParameters::ssrc.
+  absl::optional<uint32_t> ssrc;
+
+  FecMechanism mechanism = FecMechanism::RED;
+
+  // Constructors for convenience.
+  RtpFecParameters();
+  explicit RtpFecParameters(FecMechanism mechanism);
+  RtpFecParameters(FecMechanism mechanism, uint32_t ssrc);
+  RtpFecParameters(const RtpFecParameters&);
+  ~RtpFecParameters();
+
+  bool operator==(const RtpFecParameters& o) const {
+    return ssrc == o.ssrc && mechanism == o.mechanism;
+  }
+  bool operator!=(const RtpFecParameters& o) const { return !(*this == o); }
+};
+
+struct RtpRtxParameters {
+  // If unset, a value is chosen by the implementation.
+  // Works just like RtpEncodingParameters::ssrc.
+  absl::optional<uint32_t> ssrc;
+
+  // Constructors for convenience.
+  RtpRtxParameters();
+  explicit RtpRtxParameters(uint32_t ssrc);
+  RtpRtxParameters(const RtpRtxParameters&);
+  ~RtpRtxParameters();
+
+  bool operator==(const RtpRtxParameters& o) const { return ssrc == o.ssrc; }
+  bool operator!=(const RtpRtxParameters& o) const { return !(*this == o); }
+};
+
+struct RtpEncodingParameters {
+  RtpEncodingParameters();
+  RtpEncodingParameters(const RtpEncodingParameters&);
+  ~RtpEncodingParameters();
+
+  // If unset, a value is chosen by the implementation.
+  //
+  // Note that the chosen value is NOT returned by GetParameters, because it
+  // may change due to an SSRC conflict, in which case the conflict is handled
+  // internally without any event. Another way of looking at this is that an
+  // unset SSRC acts as a "wildcard" SSRC.
+  absl::optional<uint32_t> ssrc;
+
+  // Can be used to reference a codec in the |codecs| member of the
+  // RtpParameters that contains this RtpEncodingParameters. If unset, the
+  // implementation will choose the first possible codec (if a sender), or
+  // prepare to receive any codec (for a receiver).
+  // TODO(deadbeef): Not implemented. Implementation of RtpSender will always
+  // choose the first codec from the list.
+  absl::optional<int> codec_payload_type;
+
+  // Specifies the FEC mechanism, if set.
+  // TODO(deadbeef): Not implemented. Current implementation will use whatever
+  // FEC codecs are available, including red+ulpfec.
+  absl::optional<RtpFecParameters> fec;
+
+  // Specifies the RTX parameters, if set.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
+  absl::optional<RtpRtxParameters> rtx;
+
+  // Only used for audio. If set, determines whether or not discontinuous
+  // transmission will be used, if an available codec supports it. If not
+  // set, the implementation default setting will be used.
+  // TODO(deadbeef): Not implemented. Current implementation will use a CN
+  // codec as long as it's present.
+  absl::optional<DtxStatus> dtx;
+
+  // The relative bitrate priority of this encoding. Currently this is
+  // implemented for the entire rtp sender by using the value of the first
+  // encoding parameter.
+  // TODO(webrtc.bugs.org/8630): Implement this per encoding parameter.
+  // Currently there is logic for how bitrate is distributed per simulcast layer
+  // in the VideoBitrateAllocator. This must be updated to incorporate relative
+  // bitrate priority.
+  double bitrate_priority = kDefaultBitratePriority;
+
+  // The relative DiffServ Code Point priority for this encoding, allowing
+  // packets to be marked relatively higher or lower without affecting
+  // bandwidth allocations. See https://w3c.github.io/webrtc-dscp-exp/ . NB
+  // we follow chromium's translation of the allowed string enum values for
+  // this field to 1.0, 0.5, et cetera, similar to bitrate_priority above.
+  // TODO(http://crbug.com/webrtc/8630): Implement this per encoding parameter.
+  double network_priority = kDefaultBitratePriority;
+
+  // Indicates the preferred duration of media represented by a packet in
+  // milliseconds for this encoding. If set, this will take precedence over the
+  // ptime set in the RtpCodecParameters. This could happen if SDP negotiation
+  // creates a ptime for a specific codec, which is later changed in the
+  // RtpEncodingParameters by the application.
+  // TODO(bugs.webrtc.org/8819): Not implemented.
+  absl::optional<int> ptime;
+
+  // If set, this represents the Transport Independent Application Specific
+  // maximum bandwidth defined in RFC3890. If unset, there is no maximum
+  // bitrate. Currently this is implemented for the entire rtp sender by using
+  // the value of the first encoding parameter.
+  //
+  // Just called "maxBitrate" in ORTC spec.
+  //
+  // TODO(deadbeef): With ORTC RtpSenders, this currently sets the total
+  // bandwidth for the entire bandwidth estimator (audio and video). This is
+  // just always how "b=AS" was handled, but it's not correct and should be
+  // fixed.
+  absl::optional<int> max_bitrate_bps;
+
+  // Specifies the minimum bitrate in bps for video.
+  // TODO(asapersson): Not implemented for ORTC API.
+  absl::optional<int> min_bitrate_bps;
+
+  // Specifies the maximum framerate in fps for video.
+  // TODO(asapersson): Different framerates are not supported per simulcast
+  // layer. If set, the maximum |max_framerate| is currently used.
+  // Not supported for screencast.
+  absl::optional<int> max_framerate;
+
+  // Specifies the number of temporal layers for video (if the feature is
+  // supported by the codec implementation).
+  // TODO(asapersson): Different number of temporal layers are not supported
+  // per simulcast layer.
+  // Screencast support is experimental.
+  absl::optional<int> num_temporal_layers;
+
+  // For video, scale the resolution down by this factor.
+  absl::optional<double> scale_resolution_down_by;
+
+  // Scale the framerate down by this factor.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<double> scale_framerate_down_by;
+
+  // 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
+  // off.
+  // TODO(webrtc.bugs.org/8807): Updating this parameter will trigger an encoder
+  // reset, but this isn't necessarily required.
+  bool active = true;
+
+  // Value to use for RID RTP header extension.
+  // Called "encodingId" in ORTC.
+  std::string rid;
+
+  // RIDs of encodings on which this layer depends.
+  // Called "dependencyEncodingIds" in ORTC spec.
+  // TODO(deadbeef): Not implemented.
+  std::vector<std::string> dependency_rids;
+
+  bool operator==(const RtpEncodingParameters& o) const {
+    return ssrc == o.ssrc && codec_payload_type == o.codec_payload_type &&
+           fec == o.fec && rtx == o.rtx && dtx == o.dtx &&
+           bitrate_priority == o.bitrate_priority &&
+           network_priority == o.network_priority && ptime == o.ptime &&
+           max_bitrate_bps == o.max_bitrate_bps &&
+           min_bitrate_bps == o.min_bitrate_bps &&
+           max_framerate == o.max_framerate &&
+           num_temporal_layers == o.num_temporal_layers &&
+           scale_resolution_down_by == o.scale_resolution_down_by &&
+           scale_framerate_down_by == o.scale_framerate_down_by &&
+           active == o.active && rid == o.rid &&
+           dependency_rids == o.dependency_rids;
+  }
+  bool operator!=(const RtpEncodingParameters& o) const {
+    return !(*this == o);
+  }
+};
+
+struct RtpCodecParameters {
+  RtpCodecParameters();
+  RtpCodecParameters(const RtpCodecParameters&);
+  ~RtpCodecParameters();
+
+  // Build MIME "type/subtype" string from |name| and |kind|.
+  std::string mime_type() const { return MediaTypeToString(kind) + "/" + name; }
+
+  // Used to identify the codec. Equivalent to MIME subtype.
+  std::string name;
+
+  // The media type of this codec. Equivalent to MIME top-level type.
+  cricket::MediaType kind = cricket::MEDIA_TYPE_AUDIO;
+
+  // Payload type used to identify this codec in RTP packets.
+  // This must always be present, and must be unique across all codecs using
+  // the same transport.
+  int payload_type = 0;
+
+  // If unset, the implementation default is used.
+  absl::optional<int> clock_rate;
+
+  // The number of audio channels used. Unset for video codecs. If unset for
+  // audio, the implementation default is used.
+  // TODO(deadbeef): The "implementation default" part isn't fully implemented.
+  // Only defaults to 1, even though some codecs (such as opus) should really
+  // default to 2.
+  absl::optional<int> num_channels;
+
+  // The maximum packetization time to be used by an RtpSender.
+  // If |ptime| is also set, this will be ignored.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> max_ptime;
+
+  // The packetization time to be used by an RtpSender.
+  // If unset, will use any time up to max_ptime.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<int> ptime;
+
+  // Feedback mechanisms to be used for this codec.
+  // TODO(deadbeef): Not implemented with PeerConnection senders/receivers.
+  std::vector<RtcpFeedback> rtcp_feedback;
+
+  // Codec-specific parameters that must be signaled to the remote party.
+  //
+  // Corresponds to "a=fmtp" parameters in SDP.
+  //
+  // Contrary to ORTC, these parameters are named using all lowercase strings.
+  // This helps make the mapping to SDP simpler, if an application is using
+  // SDP. Boolean values are represented by the string "1".
+  std::unordered_map<std::string, std::string> parameters;
+
+  bool operator==(const RtpCodecParameters& o) const {
+    return name == o.name && kind == o.kind && payload_type == o.payload_type &&
+           clock_rate == o.clock_rate && num_channels == o.num_channels &&
+           max_ptime == o.max_ptime && ptime == o.ptime &&
+           rtcp_feedback == o.rtcp_feedback && parameters == o.parameters;
+  }
+  bool operator!=(const RtpCodecParameters& o) const { return !(*this == o); }
+};
+
+// RtpCapabilities is used to represent the static capabilities of an
+// endpoint. An application can use these capabilities to construct an
+// RtpParameters.
+struct RtpCapabilities {
+  RtpCapabilities();
+  ~RtpCapabilities();
+
+  // Supported codecs.
+  std::vector<RtpCodecCapability> codecs;
+
+  // Supported RTP header extensions.
+  std::vector<RtpHeaderExtensionCapability> header_extensions;
+
+  // Supported Forward Error Correction (FEC) mechanisms. Note that the RED,
+  // ulpfec and flexfec codecs used by these mechanisms will still appear in
+  // |codecs|.
+  std::vector<FecMechanism> fec;
+
+  bool operator==(const RtpCapabilities& o) const {
+    return codecs == o.codecs && header_extensions == o.header_extensions &&
+           fec == o.fec;
+  }
+  bool operator!=(const RtpCapabilities& o) const { return !(*this == o); }
+};
+
+struct RtcpParameters final {
+  RtcpParameters();
+  RtcpParameters(const RtcpParameters&);
+  ~RtcpParameters();
+
+  // The SSRC to be used in the "SSRC of packet sender" field. If not set, one
+  // will be chosen by the implementation.
+  // TODO(deadbeef): Not implemented.
+  absl::optional<uint32_t> ssrc;
+
+  // The Canonical Name (CNAME) used by RTCP (e.g. in SDES messages).
+  //
+  // If empty in the construction of the RtpTransport, one will be generated by
+  // the implementation, and returned in GetRtcpParameters. Multiple
+  // RtpTransports created by the same OrtcFactory will use the same generated
+  // CNAME.
+  //
+  // If empty when passed into SetParameters, the CNAME simply won't be
+  // modified.
+  std::string cname;
+
+  // Send reduced-size RTCP?
+  bool reduced_size = false;
+
+  // Send RTCP multiplexed on the RTP transport?
+  // Not used with PeerConnection senders/receivers
+  bool mux = true;
+
+  bool operator==(const RtcpParameters& o) const {
+    return ssrc == o.ssrc && cname == o.cname &&
+           reduced_size == o.reduced_size && mux == o.mux;
+  }
+  bool operator!=(const RtcpParameters& o) const { return !(*this == o); }
+};
+
+struct RTC_EXPORT RtpParameters {
+  RtpParameters();
+  RtpParameters(const RtpParameters&);
+  ~RtpParameters();
+
+  // Used when calling getParameters/setParameters with a PeerConnection
+  // RtpSender, to ensure that outdated parameters are not unintentionally
+  // applied successfully.
+  std::string transaction_id;
+
+  // Value to use for MID RTP header extension.
+  // Called "muxId" in ORTC.
+  // TODO(deadbeef): Not implemented.
+  std::string mid;
+
+  std::vector<RtpCodecParameters> codecs;
+
+  std::vector<RtpHeaderExtensionParameters> header_extensions;
+
+  std::vector<RtpEncodingParameters> encodings;
+
+  // Only available with a Peerconnection RtpSender.
+  // In ORTC, our API includes an additional "RtpTransport"
+  // abstraction on which RTCP parameters are set.
+  RtcpParameters rtcp;
+
+  // When bandwidth is constrained and the RtpSender needs to choose between
+  // degrading resolution or degrading framerate, degradationPreference
+  // indicates which is preferred. Only for video tracks.
+  DegradationPreference degradation_preference =
+      DegradationPreference::BALANCED;
+
+  bool operator==(const RtpParameters& o) const {
+    return mid == o.mid && codecs == o.codecs &&
+           header_extensions == o.header_extensions &&
+           encodings == o.encodings && rtcp == o.rtcp &&
+           degradation_preference == o.degradation_preference;
+  }
+  bool operator!=(const RtpParameters& o) const { return !(*this == o); }
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTP_PARAMETERS_H_
diff --git a/api/rtp_parameters_unittest.cc b/api/rtp_parameters_unittest.cc
new file mode 100644
index 0000000..b6f2482
--- /dev/null
+++ b/api/rtp_parameters_unittest.cc
@@ -0,0 +1,49 @@
+/*
+ *  Copyright (c) 2017 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/rtp_parameters.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+using webrtc::RtpExtension;
+
+static const char kExtensionUri1[] = "extension-uri1";
+static const char kExtensionUri2[] = "extension-uri2";
+
+static const RtpExtension kExtension1(kExtensionUri1, 1);
+static const RtpExtension kExtension1Encrypted(kExtensionUri1, 10, true);
+static const RtpExtension kExtension2(kExtensionUri2, 2);
+
+TEST(RtpExtensionTest, FilterDuplicateNonEncrypted) {
+  std::vector<RtpExtension> extensions;
+  std::vector<RtpExtension> filtered;
+
+  extensions.push_back(kExtension1);
+  extensions.push_back(kExtension1Encrypted);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(1u, filtered.size());
+  EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered);
+
+  extensions.clear();
+  extensions.push_back(kExtension1Encrypted);
+  extensions.push_back(kExtension1);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(1u, filtered.size());
+  EXPECT_EQ(std::vector<RtpExtension>{kExtension1Encrypted}, filtered);
+
+  extensions.clear();
+  extensions.push_back(kExtension1);
+  extensions.push_back(kExtension2);
+  filtered = RtpExtension::FilterDuplicateNonEncrypted(extensions);
+  EXPECT_EQ(2u, filtered.size());
+  EXPECT_EQ(extensions, filtered);
+}
+}  // namespace webrtc
diff --git a/api/rtp_receiver_interface.cc b/api/rtp_receiver_interface.cc
new file mode 100644
index 0000000..52f72df
--- /dev/null
+++ b/api/rtp_receiver_interface.cc
@@ -0,0 +1,61 @@
+/*
+ *  Copyright 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/rtp_receiver_interface.h"
+
+namespace webrtc {
+
+RtpSource::RtpSource(int64_t timestamp_ms,
+                     uint32_t source_id,
+                     RtpSourceType source_type)
+    : timestamp_ms_(timestamp_ms),
+      source_id_(source_id),
+      source_type_(source_type) {}
+
+RtpSource::RtpSource(int64_t timestamp_ms,
+                     uint32_t source_id,
+                     RtpSourceType source_type,
+                     uint8_t audio_level)
+    : timestamp_ms_(timestamp_ms),
+      source_id_(source_id),
+      source_type_(source_type),
+      audio_level_(audio_level) {}
+
+RtpSource::RtpSource(const RtpSource&) = default;
+RtpSource& RtpSource::operator=(const RtpSource&) = default;
+RtpSource::~RtpSource() = default;
+
+std::vector<std::string> RtpReceiverInterface::stream_ids() const {
+  return {};
+}
+
+std::vector<rtc::scoped_refptr<MediaStreamInterface>>
+RtpReceiverInterface::streams() const {
+  return {};
+}
+
+std::vector<RtpSource> RtpReceiverInterface::GetSources() const {
+  return {};
+}
+
+void RtpReceiverInterface::SetFrameDecryptor(
+    rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor) {}
+
+rtc::scoped_refptr<FrameDecryptorInterface>
+RtpReceiverInterface::GetFrameDecryptor() const {
+  return nullptr;
+}
+
+rtc::scoped_refptr<DtlsTransportInterface>
+RtpReceiverInterface::dtls_transport() const {
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/api/rtp_receiver_interface.h b/api/rtp_receiver_interface.h
new file mode 100644
index 0000000..7d9870b
--- /dev/null
+++ b/api/rtp_receiver_interface.h
@@ -0,0 +1,176 @@
+/*
+ *  Copyright 2015 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.
+ */
+
+// This file contains interfaces for RtpReceivers
+// http://w3c.github.io/webrtc-pc/#rtcrtpreceiver-interface
+
+#ifndef API_RTP_RECEIVER_INTERFACE_H_
+#define API_RTP_RECEIVER_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "api/crypto/frame_decryptor_interface.h"
+#include "api/dtls_transport_interface.h"
+#include "api/media_stream_interface.h"
+#include "api/media_types.h"
+#include "api/proxy.h"
+#include "api/rtp_parameters.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+enum class RtpSourceType {
+  SSRC,
+  CSRC,
+};
+
+class RtpSource {
+ public:
+  RtpSource() = delete;
+  RtpSource(int64_t timestamp_ms,
+            uint32_t source_id,
+            RtpSourceType source_type);
+  RtpSource(int64_t timestamp_ms,
+            uint32_t source_id,
+            RtpSourceType source_type,
+            uint8_t audio_level);
+  RtpSource(const RtpSource&);
+  RtpSource& operator=(const RtpSource&);
+  ~RtpSource();
+
+  int64_t timestamp_ms() const { return timestamp_ms_; }
+  void update_timestamp_ms(int64_t timestamp_ms) {
+    RTC_DCHECK_LE(timestamp_ms_, timestamp_ms);
+    timestamp_ms_ = timestamp_ms;
+  }
+
+  // The identifier of the source can be the CSRC or the SSRC.
+  uint32_t source_id() const { return source_id_; }
+
+  // The source can be either a contributing source or a synchronization source.
+  RtpSourceType source_type() const { return source_type_; }
+
+  absl::optional<uint8_t> audio_level() const { return audio_level_; }
+  void set_audio_level(const absl::optional<uint8_t>& level) {
+    audio_level_ = level;
+  }
+
+  bool operator==(const RtpSource& o) const {
+    return timestamp_ms_ == o.timestamp_ms() && source_id_ == o.source_id() &&
+           source_type_ == o.source_type() && audio_level_ == o.audio_level_;
+  }
+
+ private:
+  int64_t timestamp_ms_;
+  uint32_t source_id_;
+  RtpSourceType source_type_;
+  absl::optional<uint8_t> audio_level_;
+};
+
+class RtpReceiverObserverInterface {
+ public:
+  // Note: Currently if there are multiple RtpReceivers of the same media type,
+  // they will all call OnFirstPacketReceived at once.
+  //
+  // In the future, it's likely that an RtpReceiver will only call
+  // OnFirstPacketReceived when a packet is received specifically for its
+  // SSRC/mid.
+  virtual void OnFirstPacketReceived(cricket::MediaType media_type) = 0;
+
+ protected:
+  virtual ~RtpReceiverObserverInterface() {}
+};
+
+class RtpReceiverInterface : public rtc::RefCountInterface {
+ public:
+  virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
+
+  // The dtlsTransport attribute exposes the DTLS transport on which the
+  // media is received. It may be null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtpreceiver-transport
+  // TODO(https://bugs.webrtc.org/907849) remove default implementation
+  virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const;
+
+  // The list of streams that |track| is associated with. This is the same as
+  // the [[AssociatedRemoteMediaStreams]] internal slot in the spec.
+  // https://w3c.github.io/webrtc-pc/#dfn-associatedremotemediastreams
+  // TODO(hbos): Make pure virtual as soon as Chromium's mock implements this.
+  // TODO(https://crbug.com/webrtc/9480): Remove streams() in favor of
+  // stream_ids() as soon as downstream projects are no longer dependent on
+  // stream objects.
+  virtual std::vector<std::string> stream_ids() const;
+  virtual std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams() const;
+
+  // Audio or video receiver?
+  virtual cricket::MediaType media_type() const = 0;
+
+  // Not to be confused with "mid", this is a field we can temporarily use
+  // to uniquely identify a receiver until we implement Unified Plan SDP.
+  virtual std::string id() const = 0;
+
+  // The WebRTC specification only defines RTCRtpParameters in terms of senders,
+  // but this API also applies them to receivers, similar to ORTC:
+  // http://ortc.org/wp-content/uploads/2016/03/ortc.html#rtcrtpparameters*.
+  virtual RtpParameters GetParameters() const = 0;
+  // Currently, doesn't support changing any parameters, but may in the future.
+  virtual bool SetParameters(const RtpParameters& parameters) = 0;
+
+  // Does not take ownership of observer.
+  // Must call SetObserver(nullptr) before the observer is destroyed.
+  virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0;
+
+  // TODO(zhihuang): Remove the default implementation once the subclasses
+  // implement this. Currently, the only relevant subclass is the
+  // content::FakeRtpReceiver in Chromium.
+  virtual std::vector<RtpSource> GetSources() const;
+
+  // Sets a user defined frame decryptor that will decrypt the entire frame
+  // before it is sent across the network. This will decrypt the entire frame
+  // using the user provided decryption mechanism regardless of whether SRTP is
+  // enabled or not.
+  virtual void SetFrameDecryptor(
+      rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor);
+
+  // Returns a pointer to the frame decryptor set previously by the
+  // user. This can be used to update the state of the object.
+  virtual rtc::scoped_refptr<FrameDecryptorInterface> GetFrameDecryptor() const;
+
+ protected:
+  ~RtpReceiverInterface() override = default;
+};
+
+// Define proxy for RtpReceiverInterface.
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtlsTransportInterface>, dtls_transport)
+PROXY_CONSTMETHOD0(std::vector<std::string>, stream_ids)
+PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<MediaStreamInterface>>,
+                   streams)
+PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(RtpParameters, GetParameters)
+PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
+PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*)
+PROXY_CONSTMETHOD0(std::vector<RtpSource>, GetSources)
+PROXY_METHOD1(void,
+              SetFrameDecryptor,
+              rtc::scoped_refptr<FrameDecryptorInterface>)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<FrameDecryptorInterface>,
+                   GetFrameDecryptor)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_RTP_RECEIVER_INTERFACE_H_
diff --git a/api/rtp_sender_interface.cc b/api/rtp_sender_interface.cc
new file mode 100644
index 0000000..d23fd18
--- /dev/null
+++ b/api/rtp_sender_interface.cc
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 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/rtp_sender_interface.h"
+
+namespace webrtc {
+
+void RtpSenderInterface::SetFrameEncryptor(
+    rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {}
+
+rtc::scoped_refptr<FrameEncryptorInterface>
+RtpSenderInterface::GetFrameEncryptor() const {
+  return nullptr;
+}
+
+std::vector<RtpEncodingParameters> RtpSenderInterface::init_send_encodings()
+    const {
+  return {};
+}
+
+rtc::scoped_refptr<DtlsTransportInterface> RtpSenderInterface::dtls_transport()
+    const {
+  return nullptr;
+}
+
+}  // namespace webrtc
diff --git a/api/rtp_sender_interface.h b/api/rtp_sender_interface.h
new file mode 100644
index 0000000..e0a29a3
--- /dev/null
+++ b/api/rtp_sender_interface.h
@@ -0,0 +1,119 @@
+/*
+ *  Copyright 2015 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.
+ */
+
+// This file contains interfaces for RtpSenders
+// http://w3c.github.io/webrtc-pc/#rtcrtpsender-interface
+
+#ifndef API_RTP_SENDER_INTERFACE_H_
+#define API_RTP_SENDER_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "api/crypto/frame_encryptor_interface.h"
+#include "api/dtls_transport_interface.h"
+#include "api/dtmf_sender_interface.h"
+#include "api/media_stream_interface.h"
+#include "api/media_types.h"
+#include "api/proxy.h"
+#include "api/rtc_error.h"
+#include "api/rtp_parameters.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+class RtpSenderInterface : public rtc::RefCountInterface {
+ public:
+  // Returns true if successful in setting the track.
+  // Fails if an audio track is set on a video RtpSender, or vice-versa.
+  virtual bool SetTrack(MediaStreamTrackInterface* track) = 0;
+  virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
+
+  // The dtlsTransport attribute exposes the DTLS transport on which the
+  // media is sent. It may be null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtpsender-transport
+  // TODO(https://bugs.webrtc.org/907849) remove default implementation
+  virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const;
+
+  // Returns primary SSRC used by this sender for sending media.
+  // Returns 0 if not yet determined.
+  // TODO(deadbeef): Change to absl::optional.
+  // TODO(deadbeef): Remove? With GetParameters this should be redundant.
+  virtual uint32_t ssrc() const = 0;
+
+  // Audio or video sender?
+  virtual cricket::MediaType media_type() const = 0;
+
+  // Not to be confused with "mid", this is a field we can temporarily use
+  // to uniquely identify a receiver until we implement Unified Plan SDP.
+  virtual std::string id() const = 0;
+
+  // Returns a list of media stream ids associated with this sender's track.
+  // These are signalled in the SDP so that the remote side can associate
+  // tracks.
+  virtual std::vector<std::string> stream_ids() const = 0;
+
+  // Returns the list of encoding parameters that will be applied when the SDP
+  // local description is set. These initial encoding parameters can be set by
+  // PeerConnection::AddTransceiver, and later updated with Get/SetParameters.
+  // TODO(orphis): Make it pure virtual once Chrome has updated
+  virtual std::vector<RtpEncodingParameters> init_send_encodings() const;
+
+  virtual RtpParameters GetParameters() const = 0;
+  // Note that only a subset of the parameters can currently be changed. See
+  // rtpparameters.h
+  // The encodings are in increasing quality order for simulcast.
+  virtual RTCError SetParameters(const RtpParameters& parameters) = 0;
+
+  // Returns null for a video sender.
+  virtual rtc::scoped_refptr<DtmfSenderInterface> GetDtmfSender() const = 0;
+
+  // Sets a user defined frame encryptor that will encrypt the entire frame
+  // before it is sent across the network. This will encrypt the entire frame
+  // using the user provided encryption mechanism regardless of whether SRTP is
+  // enabled or not.
+  virtual void SetFrameEncryptor(
+      rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor);
+
+  // Returns a pointer to the frame encryptor set previously by the
+  // user. This can be used to update the state of the object.
+  virtual rtc::scoped_refptr<FrameEncryptorInterface> GetFrameEncryptor() const;
+
+ protected:
+  ~RtpSenderInterface() override = default;
+};
+
+// Define proxy for RtpSenderInterface.
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_SIGNALING_PROXY_MAP(RtpSender)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtlsTransportInterface>, dtls_transport)
+PROXY_CONSTMETHOD0(uint32_t, ssrc)
+PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
+PROXY_CONSTMETHOD0(std::string, id)
+PROXY_CONSTMETHOD0(std::vector<std::string>, stream_ids)
+PROXY_CONSTMETHOD0(std::vector<RtpEncodingParameters>, init_send_encodings)
+PROXY_CONSTMETHOD0(RtpParameters, GetParameters)
+PROXY_METHOD1(RTCError, SetParameters, const RtpParameters&)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtmfSenderInterface>, GetDtmfSender)
+PROXY_METHOD1(void,
+              SetFrameEncryptor,
+              rtc::scoped_refptr<FrameEncryptorInterface>)
+PROXY_CONSTMETHOD0(rtc::scoped_refptr<FrameEncryptorInterface>,
+                   GetFrameEncryptor)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_RTP_SENDER_INTERFACE_H_
diff --git a/api/rtp_transceiver_interface.cc b/api/rtp_transceiver_interface.cc
new file mode 100644
index 0000000..0504331
--- /dev/null
+++ b/api/rtp_transceiver_interface.cc
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 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/rtp_transceiver_interface.h"
+
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+RtpTransceiverInit::RtpTransceiverInit() = default;
+
+RtpTransceiverInit::RtpTransceiverInit(const RtpTransceiverInit& rhs) = default;
+
+RtpTransceiverInit::~RtpTransceiverInit() = default;
+
+absl::optional<RtpTransceiverDirection>
+RtpTransceiverInterface::fired_direction() const {
+  return absl::nullopt;
+}
+
+void RtpTransceiverInterface::SetCodecPreferences(
+    rtc::ArrayView<RtpCodecCapability>) {
+  RTC_NOTREACHED() << "Not implemented";
+}
+
+}  // namespace webrtc
diff --git a/api/rtp_transceiver_interface.h b/api/rtp_transceiver_interface.h
new file mode 100644
index 0000000..aec0d15
--- /dev/null
+++ b/api/rtp_transceiver_interface.h
@@ -0,0 +1,140 @@
+/*
+ *  Copyright 2017 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_RTP_TRANSCEIVER_INTERFACE_H_
+#define API_RTP_TRANSCEIVER_INTERFACE_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/media_types.h"
+#include "api/rtp_parameters.h"
+#include "api/rtp_receiver_interface.h"
+#include "api/rtp_sender_interface.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverdirection
+enum class RtpTransceiverDirection {
+  kSendRecv,
+  kSendOnly,
+  kRecvOnly,
+  kInactive
+};
+
+// Structure for initializing an RtpTransceiver in a call to
+// PeerConnectionInterface::AddTransceiver.
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiverinit
+struct RtpTransceiverInit final {
+  RtpTransceiverInit();
+  RtpTransceiverInit(const RtpTransceiverInit&);
+  ~RtpTransceiverInit();
+  // Direction of the RtpTransceiver. See RtpTransceiverInterface::direction().
+  RtpTransceiverDirection direction = RtpTransceiverDirection::kSendRecv;
+
+  // The added RtpTransceiver will be added to these streams.
+  std::vector<std::string> stream_ids;
+
+  // TODO(bugs.webrtc.org/7600): Not implemented.
+  std::vector<RtpEncodingParameters> send_encodings;
+};
+
+// The RtpTransceiverInterface maps to the RTCRtpTransceiver defined by the
+// WebRTC specification. A transceiver represents a combination of an RtpSender
+// and an RtpReceiver than share a common mid. As defined in JSEP, an
+// RtpTransceiver is said to be associated with a media description if its mid
+// property is non-null; otherwise, it is said to be disassociated.
+// JSEP: https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-24
+//
+// Note that RtpTransceivers are only supported when using PeerConnection with
+// Unified Plan SDP.
+//
+// This class is thread-safe.
+//
+// WebRTC specification for RTCRtpTransceiver, the JavaScript analog:
+// https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver
+class RtpTransceiverInterface : public rtc::RefCountInterface {
+ public:
+  // Media type of the transceiver. Any sender(s)/receiver(s) will have this
+  // type as well.
+  virtual cricket::MediaType media_type() const = 0;
+
+  // The mid attribute is the mid negotiated and present in the local and
+  // remote descriptions. Before negotiation is complete, the mid value may be
+  // null. After rollbacks, the value may change from a non-null value to null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-mid
+  virtual absl::optional<std::string> mid() const = 0;
+
+  // The sender attribute exposes the RtpSender corresponding to the RTP media
+  // that may be sent with the transceiver's mid. The sender is always present,
+  // regardless of the direction of media.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-sender
+  virtual rtc::scoped_refptr<RtpSenderInterface> sender() const = 0;
+
+  // The receiver attribute exposes the RtpReceiver corresponding to the RTP
+  // media that may be received with the transceiver's mid. The receiver is
+  // always present, regardless of the direction of media.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-receiver
+  virtual rtc::scoped_refptr<RtpReceiverInterface> receiver() const = 0;
+
+  // The stopped attribute indicates that the sender of this transceiver will no
+  // longer send, and that the receiver will no longer receive. It is true if
+  // either stop has been called or if setting the local or remote description
+  // has caused the RtpTransceiver to be stopped.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stopped
+  virtual bool stopped() const = 0;
+
+  // The direction attribute indicates the preferred direction of this
+  // transceiver, which will be used in calls to CreateOffer and CreateAnswer.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+  virtual RtpTransceiverDirection direction() const = 0;
+
+  // Sets the preferred direction of this transceiver. An update of
+  // directionality does not take effect immediately. Instead, future calls to
+  // CreateOffer and CreateAnswer mark the corresponding media descriptions as
+  // sendrecv, sendonly, recvonly, or inactive.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-direction
+  virtual void SetDirection(RtpTransceiverDirection new_direction) = 0;
+
+  // The current_direction attribute indicates the current direction negotiated
+  // for this transceiver. If this transceiver has never been represented in an
+  // offer/answer exchange, or if the transceiver is stopped, the value is null.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-currentdirection
+  virtual absl::optional<RtpTransceiverDirection> current_direction() const = 0;
+
+  // An internal slot designating for which direction the relevant
+  // PeerConnection events have been fired. This is to ensure that events like
+  // OnAddTrack only get fired once even if the same session description is
+  // applied again.
+  // Exposed in the public interface for use by Chromium.
+  virtual absl::optional<RtpTransceiverDirection> fired_direction() const;
+
+  // The Stop method irreversibly stops the RtpTransceiver. The sender of this
+  // transceiver will no longer send, the receiver will no longer receive.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-stop
+  virtual void Stop() = 0;
+
+  // The SetCodecPreferences method overrides the default codec preferences used
+  // by WebRTC for this transceiver.
+  // https://w3c.github.io/webrtc-pc/#dom-rtcrtptransceiver-setcodecpreferences
+  // TODO(steveanton): Not implemented.
+  virtual void SetCodecPreferences(rtc::ArrayView<RtpCodecCapability> codecs);
+
+ protected:
+  ~RtpTransceiverInterface() override = default;
+};
+
+}  // namespace webrtc
+
+#endif  // API_RTP_TRANSCEIVER_INTERFACE_H_
diff --git a/api/scoped_refptr.h b/api/scoped_refptr.h
index 0993e03..67d179f 100644
--- a/api/scoped_refptr.h
+++ b/api/scoped_refptr.h
@@ -71,6 +71,8 @@
 template <class T>
 class scoped_refptr {
  public:
+  typedef T element_type;
+
   scoped_refptr() : ptr_(nullptr) {}
 
   scoped_refptr(T* p) : ptr_(p) {  // NOLINT(runtime/explicit)
diff --git a/api/sctp_transport_interface.cc b/api/sctp_transport_interface.cc
new file mode 100644
index 0000000..c6c1fbe
--- /dev/null
+++ b/api/sctp_transport_interface.cc
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 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 <utility>
+
+#include "api/sctp_transport_interface.h"
+
+namespace webrtc {
+
+SctpTransportInformation::SctpTransportInformation(SctpTransportState state)
+    : state_(state) {}
+
+SctpTransportInformation::SctpTransportInformation(
+    SctpTransportState state,
+    rtc::scoped_refptr<DtlsTransportInterface> dtls_transport,
+    absl::optional<double> max_message_size,
+    absl::optional<int> max_channels)
+    : state_(state),
+      dtls_transport_(std::move(dtls_transport)),
+      max_message_size_(max_message_size),
+      max_channels_(max_channels) {}
+
+SctpTransportInformation::~SctpTransportInformation() {}
+
+}  // namespace webrtc
diff --git a/api/sctp_transport_interface.h b/api/sctp_transport_interface.h
new file mode 100644
index 0000000..3698fc2
--- /dev/null
+++ b/api/sctp_transport_interface.h
@@ -0,0 +1,90 @@
+/*
+ *  Copyright 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.
+ */
+
+#ifndef API_SCTP_TRANSPORT_INTERFACE_H_
+#define API_SCTP_TRANSPORT_INTERFACE_H_
+
+#include "absl/types/optional.h"
+#include "api/dtls_transport_interface.h"
+#include "api/rtc_error.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// States of a SCTP transport, corresponding to the JS API specification.
+// http://w3c.github.io/webrtc-pc/#dom-rtcsctptransportstate
+enum class SctpTransportState {
+  kNew,         // Has not started negotiating yet. Non-standard state.
+  kConnecting,  // In the process of negotiating an association.
+  kConnected,   // Completed negotiation of an association.
+  kClosed,      // Closed by local or remote party.
+  kNumValues
+};
+
+// This object gives snapshot information about the changeable state of a
+// SctpTransport.
+// It reflects the readonly attributes of the object in the specification.
+// http://w3c.github.io/webrtc-pc/#rtcsctptransport-interface
+class SctpTransportInformation {
+ public:
+  explicit SctpTransportInformation(SctpTransportState state);
+  SctpTransportInformation(
+      SctpTransportState state,
+      rtc::scoped_refptr<DtlsTransportInterface> dtls_transport,
+      absl::optional<double> max_message_size,
+      absl::optional<int> max_channels);
+  ~SctpTransportInformation();
+  // The DTLS transport that supports this SCTP transport.
+  rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const {
+    return dtls_transport_;
+  }
+  SctpTransportState state() const { return state_; }
+  absl::optional<double> MaxMessageSize() const { return max_message_size_; }
+  absl::optional<int> MaxChannels() const { return max_channels_; }
+
+ private:
+  SctpTransportState state_;
+  rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+  absl::optional<double> max_message_size_;
+  absl::optional<int> max_channels_;
+};
+
+class SctpTransportObserverInterface {
+ public:
+  // This callback carries information about the state of the transport.
+  // The argument is a pass-by-value snapshot of the state.
+  // The callback will be called on the network thread.
+  virtual void OnStateChange(SctpTransportInformation info) = 0;
+
+ protected:
+  virtual ~SctpTransportObserverInterface() = default;
+};
+
+// A SCTP transport, as represented to the outside world.
+// This object is created on the network thread, and can only be
+// accessed on that thread, except for functions explicitly marked otherwise.
+// References can be held by other threads, and destruction can therefore
+// be initiated by other threads.
+class SctpTransportInterface : public rtc::RefCountInterface {
+ public:
+  // This function can be called from other threads.
+  virtual rtc::scoped_refptr<DtlsTransportInterface> dtls_transport() const = 0;
+  // Returns information on the state of the SctpTransport.
+  // This function can be called from other threads.
+  virtual SctpTransportInformation Information() const = 0;
+  // Observer management.
+  virtual void RegisterObserver(SctpTransportObserverInterface* observer) = 0;
+  virtual void UnregisterObserver() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_SCTP_TRANSPORT_INTERFACE_H_
diff --git a/api/set_remote_description_observer_interface.h b/api/set_remote_description_observer_interface.h
new file mode 100644
index 0000000..1782555
--- /dev/null
+++ b/api/set_remote_description_observer_interface.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2017 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_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_
+#define API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_
+
+#include "api/rtc_error.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// An observer for PeerConnectionInterface::SetRemoteDescription(). The
+// callback is invoked such that the state of the peer connection can be
+// examined to accurately reflect the effects of the SetRemoteDescription
+// operation.
+class SetRemoteDescriptionObserverInterface : public rtc::RefCountInterface {
+ public:
+  // On success, |error.ok()| is true.
+  virtual void OnSetRemoteDescriptionComplete(RTCError error) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_SET_REMOTE_DESCRIPTION_OBSERVER_INTERFACE_H_
diff --git a/api/stats_types.cc b/api/stats_types.cc
new file mode 100644
index 0000000..71b1f86
--- /dev/null
+++ b/api/stats_types.cc
@@ -0,0 +1,842 @@
+/*
+ *  Copyright 2014 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/stats_types.h"
+
+#include <string.h>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/ref_counted_object.h"
+
+// TODO(tommi): Could we have a static map of value name -> expected type
+// and use this to RTC_DCHECK on correct usage (somewhat strongly typed values)?
+// Alternatively, we could define the names+type in a separate document and
+// generate strongly typed inline C++ code that forces the correct type to be
+// used for a given name at compile time.
+
+using rtc::RefCountedObject;
+
+namespace webrtc {
+namespace {
+
+// The id of StatsReport of type kStatsReportTypeBwe.
+const char kStatsReportVideoBweId[] = "bweforvideo";
+
+// NOTE: These names need to be consistent with an external
+// specification (W3C Stats Identifiers).
+const char* InternalTypeToString(StatsReport::StatsType type) {
+  switch (type) {
+    case StatsReport::kStatsReportTypeSession:
+      return "googLibjingleSession";
+    case StatsReport::kStatsReportTypeBwe:
+      return "VideoBwe";
+    case StatsReport::kStatsReportTypeRemoteSsrc:
+      return "remoteSsrc";
+    case StatsReport::kStatsReportTypeSsrc:
+      return "ssrc";
+    case StatsReport::kStatsReportTypeTrack:
+      return "googTrack";
+    case StatsReport::kStatsReportTypeIceLocalCandidate:
+      return "localcandidate";
+    case StatsReport::kStatsReportTypeIceRemoteCandidate:
+      return "remotecandidate";
+    case StatsReport::kStatsReportTypeTransport:
+      return "transport";
+    case StatsReport::kStatsReportTypeComponent:
+      return "googComponent";
+    case StatsReport::kStatsReportTypeCandidatePair:
+      return "googCandidatePair";
+    case StatsReport::kStatsReportTypeCertificate:
+      return "googCertificate";
+    case StatsReport::kStatsReportTypeDataChannel:
+      return "datachannel";
+  }
+  RTC_NOTREACHED();
+  return nullptr;
+}
+
+class BandwidthEstimationId : public StatsReport::IdBase {
+ public:
+  BandwidthEstimationId()
+      : StatsReport::IdBase(StatsReport::kStatsReportTypeBwe) {}
+  std::string ToString() const override { return kStatsReportVideoBweId; }
+};
+
+class TypedId : public StatsReport::IdBase {
+ public:
+  TypedId(StatsReport::StatsType type, const std::string& id)
+      : StatsReport::IdBase(type), id_(id) {}
+
+  bool Equals(const IdBase& other) const override {
+    return IdBase::Equals(other) &&
+           static_cast<const TypedId&>(other).id_ == id_;
+  }
+
+  std::string ToString() const override {
+    return std::string(InternalTypeToString(type_)) + kSeparator + id_;
+  }
+
+ protected:
+  const std::string id_;
+};
+
+class TypedIntId : public StatsReport::IdBase {
+ public:
+  TypedIntId(StatsReport::StatsType type, int id)
+      : StatsReport::IdBase(type), id_(id) {}
+
+  bool Equals(const IdBase& other) const override {
+    return IdBase::Equals(other) &&
+           static_cast<const TypedIntId&>(other).id_ == id_;
+  }
+
+  std::string ToString() const override {
+    return std::string(InternalTypeToString(type_)) + kSeparator +
+           rtc::ToString(id_);
+  }
+
+ protected:
+  const int id_;
+};
+
+class IdWithDirection : public TypedId {
+ public:
+  IdWithDirection(StatsReport::StatsType type,
+                  const std::string& id,
+                  StatsReport::Direction direction)
+      : TypedId(type, id), direction_(direction) {}
+
+  bool Equals(const IdBase& other) const override {
+    return TypedId::Equals(other) &&
+           static_cast<const IdWithDirection&>(other).direction_ == direction_;
+  }
+
+  std::string ToString() const override {
+    std::string ret(TypedId::ToString());
+    ret += kSeparator;
+    ret += direction_ == StatsReport::kSend ? "send" : "recv";
+    return ret;
+  }
+
+ private:
+  const StatsReport::Direction direction_;
+};
+
+class CandidateId : public TypedId {
+ public:
+  CandidateId(bool local, const std::string& id)
+      : TypedId(local ? StatsReport::kStatsReportTypeIceLocalCandidate
+                      : StatsReport::kStatsReportTypeIceRemoteCandidate,
+                id) {}
+
+  std::string ToString() const override { return "Cand-" + id_; }
+};
+
+class ComponentId : public StatsReport::IdBase {
+ public:
+  ComponentId(const std::string& content_name, int component)
+      : ComponentId(StatsReport::kStatsReportTypeComponent,
+                    content_name,
+                    component) {}
+
+  bool Equals(const IdBase& other) const override {
+    return IdBase::Equals(other) &&
+           static_cast<const ComponentId&>(other).component_ == component_ &&
+           static_cast<const ComponentId&>(other).content_name_ ==
+               content_name_;
+  }
+
+  std::string ToString() const override { return ToString("Channel-"); }
+
+ protected:
+  ComponentId(StatsReport::StatsType type,
+              const std::string& content_name,
+              int component)
+      : IdBase(type), content_name_(content_name), component_(component) {}
+
+  std::string ToString(const char* prefix) const {
+    std::string ret(prefix);
+    ret += content_name_;
+    ret += '-';
+    ret += rtc::ToString(component_);
+    return ret;
+  }
+
+ private:
+  const std::string content_name_;
+  const int component_;
+};
+
+class CandidatePairId : public ComponentId {
+ public:
+  CandidatePairId(const std::string& content_name, int component, int index)
+      : ComponentId(StatsReport::kStatsReportTypeCandidatePair,
+                    content_name,
+                    component),
+        index_(index) {}
+
+  bool Equals(const IdBase& other) const override {
+    return ComponentId::Equals(other) &&
+           static_cast<const CandidatePairId&>(other).index_ == index_;
+  }
+
+  std::string ToString() const override {
+    std::string ret(ComponentId::ToString("Conn-"));
+    ret += '-';
+    ret += rtc::ToString(index_);
+    return ret;
+  }
+
+ private:
+  const int index_;
+};
+
+}  // namespace
+
+StatsReport::IdBase::IdBase(StatsType type) : type_(type) {}
+StatsReport::IdBase::~IdBase() {}
+
+StatsReport::StatsType StatsReport::IdBase::type() const {
+  return type_;
+}
+
+bool StatsReport::IdBase::Equals(const IdBase& other) const {
+  return other.type_ == type_;
+}
+
+StatsReport::Value::Value(StatsValueName name, int64_t value, Type int_type)
+    : name(name), type_(int_type) {
+  RTC_DCHECK(type_ == kInt || type_ == kInt64);
+  type_ == kInt ? value_.int_ = static_cast<int>(value) : value_.int64_ = value;
+}
+
+StatsReport::Value::Value(StatsValueName name, float f)
+    : name(name), type_(kFloat) {
+  value_.float_ = f;
+}
+
+StatsReport::Value::Value(StatsValueName name, const std::string& value)
+    : name(name), type_(kString) {
+  value_.string_ = new std::string(value);
+}
+
+StatsReport::Value::Value(StatsValueName name, const char* value)
+    : name(name), type_(kStaticString) {
+  value_.static_string_ = value;
+}
+
+StatsReport::Value::Value(StatsValueName name, bool b)
+    : name(name), type_(kBool) {
+  value_.bool_ = b;
+}
+
+StatsReport::Value::Value(StatsValueName name, const Id& value)
+    : name(name), type_(kId) {
+  value_.id_ = new Id(value);
+}
+
+StatsReport::Value::~Value() {
+  switch (type_) {
+    case kInt:
+    case kInt64:
+    case kFloat:
+    case kBool:
+    case kStaticString:
+      break;
+    case kString:
+      delete value_.string_;
+      break;
+    case kId:
+      delete value_.id_;
+      break;
+  }
+}
+
+bool StatsReport::Value::Equals(const Value& other) const {
+  if (name != other.name)
+    return false;
+
+  // There's a 1:1 relation between a name and a type, so we don't have to
+  // check that.
+  RTC_DCHECK_EQ(type_, other.type_);
+
+  switch (type_) {
+    case kInt:
+      return value_.int_ == other.value_.int_;
+    case kInt64:
+      return value_.int64_ == other.value_.int64_;
+    case kFloat:
+      return value_.float_ == other.value_.float_;
+    case kStaticString: {
+#if RTC_DCHECK_IS_ON
+      if (value_.static_string_ != other.value_.static_string_) {
+        RTC_DCHECK(strcmp(value_.static_string_, other.value_.static_string_) !=
+                   0)
+            << "Duplicate global?";
+      }
+#endif
+      return value_.static_string_ == other.value_.static_string_;
+    }
+    case kString:
+      return *value_.string_ == *other.value_.string_;
+    case kBool:
+      return value_.bool_ == other.value_.bool_;
+    case kId:
+      return (*value_.id_)->Equals(*other.value_.id_);
+  }
+  RTC_NOTREACHED();
+  return false;
+}
+
+bool StatsReport::Value::operator==(const std::string& value) const {
+  return (type_ == kString && value_.string_->compare(value) == 0) ||
+         (type_ == kStaticString && value.compare(value_.static_string_) == 0);
+}
+
+bool StatsReport::Value::operator==(const char* value) const {
+  if (type_ == kString)
+    return value_.string_->compare(value) == 0;
+  if (type_ != kStaticString)
+    return false;
+#if RTC_DCHECK_IS_ON
+  if (value_.static_string_ != value)
+    RTC_DCHECK(strcmp(value_.static_string_, value) != 0)
+        << "Duplicate global?";
+#endif
+  return value == value_.static_string_;
+}
+
+bool StatsReport::Value::operator==(int64_t value) const {
+  return type_ == kInt ? value_.int_ == static_cast<int>(value)
+                       : (type_ == kInt64 ? value_.int64_ == value : false);
+}
+
+bool StatsReport::Value::operator==(bool value) const {
+  return type_ == kBool && value_.bool_ == value;
+}
+
+bool StatsReport::Value::operator==(float value) const {
+  return type_ == kFloat && value_.float_ == value;
+}
+
+bool StatsReport::Value::operator==(const Id& value) const {
+  return type_ == kId && (*value_.id_)->Equals(value);
+}
+
+int StatsReport::Value::int_val() const {
+  RTC_DCHECK(type_ == kInt);
+  return value_.int_;
+}
+
+int64_t StatsReport::Value::int64_val() const {
+  RTC_DCHECK(type_ == kInt64);
+  return value_.int64_;
+}
+
+float StatsReport::Value::float_val() const {
+  RTC_DCHECK(type_ == kFloat);
+  return value_.float_;
+}
+
+const char* StatsReport::Value::static_string_val() const {
+  RTC_DCHECK(type_ == kStaticString);
+  return value_.static_string_;
+}
+
+const std::string& StatsReport::Value::string_val() const {
+  RTC_DCHECK(type_ == kString);
+  return *value_.string_;
+}
+
+bool StatsReport::Value::bool_val() const {
+  RTC_DCHECK(type_ == kBool);
+  return value_.bool_;
+}
+
+const char* StatsReport::Value::display_name() const {
+  switch (name) {
+    case kStatsValueNameAecDivergentFilterFraction:
+      return "aecDivergentFilterFraction";
+    case kStatsValueNameAudioOutputLevel:
+      return "audioOutputLevel";
+    case kStatsValueNameAudioInputLevel:
+      return "audioInputLevel";
+    case kStatsValueNameBytesSent:
+      return "bytesSent";
+    case kStatsValueNameConcealedSamples:
+      return "concealedSamples";
+    case kStatsValueNameConcealmentEvents:
+      return "concealmentEvents";
+    case kStatsValueNamePacketsSent:
+      return "packetsSent";
+    case kStatsValueNameBytesReceived:
+      return "bytesReceived";
+    case kStatsValueNameLabel:
+      return "label";
+    case kStatsValueNamePacketsReceived:
+      return "packetsReceived";
+    case kStatsValueNamePacketsLost:
+      return "packetsLost";
+    case kStatsValueNameProtocol:
+      return "protocol";
+    case kStatsValueNameTotalSamplesReceived:
+      return "totalSamplesReceived";
+    case kStatsValueNameTransportId:
+      return "transportId";
+    case kStatsValueNameSelectedCandidatePairId:
+      return "selectedCandidatePairId";
+    case kStatsValueNameSsrc:
+      return "ssrc";
+    case kStatsValueNameState:
+      return "state";
+    case kStatsValueNameDataChannelId:
+      return "datachannelid";
+    case kStatsValueNameFramesDecoded:
+      return "framesDecoded";
+    case kStatsValueNameFramesEncoded:
+      return "framesEncoded";
+    case kStatsValueNameJitterBufferDelay:
+      return "jitterBufferDelay";
+    case kStatsValueNameCodecImplementationName:
+      return "codecImplementationName";
+    case kStatsValueNameMediaType:
+      return "mediaType";
+    case kStatsValueNameQpSum:
+      return "qpSum";
+    // 'goog' prefixed constants.
+    case kStatsValueNameAccelerateRate:
+      return "googAccelerateRate";
+    case kStatsValueNameActiveConnection:
+      return "googActiveConnection";
+    case kStatsValueNameActualEncBitrate:
+      return "googActualEncBitrate";
+    case kStatsValueNameAvailableReceiveBandwidth:
+      return "googAvailableReceiveBandwidth";
+    case kStatsValueNameAvailableSendBandwidth:
+      return "googAvailableSendBandwidth";
+    case kStatsValueNameAvgEncodeMs:
+      return "googAvgEncodeMs";
+    case kStatsValueNameBucketDelay:
+      return "googBucketDelay";
+    case kStatsValueNameBandwidthLimitedResolution:
+      return "googBandwidthLimitedResolution";
+    // STUN ping related attributes.
+    //
+    // TODO(zhihuang) Rename these stats to follow the standards.
+    // Connectivity checks.
+    case kStatsValueNameSentPingRequestsTotal:
+      return "requestsSent";
+    case kStatsValueNameSentPingRequestsBeforeFirstResponse:
+      return "consentRequestsSent";
+    case kStatsValueNameSentPingResponses:
+      return "responsesSent";
+    case kStatsValueNameRecvPingRequests:
+      return "requestsReceived";
+    case kStatsValueNameRecvPingResponses:
+      return "responsesReceived";
+    // STUN Keepalive pings.
+    case kStatsValueNameSentStunKeepaliveRequests:
+      return "stunKeepaliveRequestsSent";
+    case kStatsValueNameRecvStunKeepaliveResponses:
+      return "stunKeepaliveResponsesReceived";
+    case kStatsValueNameStunKeepaliveRttTotal:
+      return "stunKeepaliveRttTotal";
+    case kStatsValueNameStunKeepaliveRttSquaredTotal:
+      return "stunKeepaliveRttSquaredTotal";
+
+    // Candidate related attributes. Values are taken from
+    // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
+    case kStatsValueNameCandidateIPAddress:
+      return "ipAddress";
+    case kStatsValueNameCandidateNetworkType:
+      return "networkType";
+    case kStatsValueNameCandidatePortNumber:
+      return "portNumber";
+    case kStatsValueNameCandidatePriority:
+      return "priority";
+    case kStatsValueNameCandidateTransportType:
+      return "transport";
+    case kStatsValueNameCandidateType:
+      return "candidateType";
+
+    case kStatsValueNameChannelId:
+      return "googChannelId";
+    case kStatsValueNameCodecName:
+      return "googCodecName";
+    case kStatsValueNameComponent:
+      return "googComponent";
+    case kStatsValueNameContentName:
+      return "googContentName";
+    case kStatsValueNameContentType:
+      return "googContentType";
+    case kStatsValueNameCpuLimitedResolution:
+      return "googCpuLimitedResolution";
+    case kStatsValueNameDecodingCTSG:
+      return "googDecodingCTSG";
+    case kStatsValueNameDecodingCTN:
+      return "googDecodingCTN";
+    case kStatsValueNameDecodingMutedOutput:
+      return "googDecodingMuted";
+    case kStatsValueNameDecodingNormal:
+      return "googDecodingNormal";
+    case kStatsValueNameDecodingPLC:
+      return "googDecodingPLC";
+    case kStatsValueNameDecodingCNG:
+      return "googDecodingCNG";
+    case kStatsValueNameDecodingPLCCNG:
+      return "googDecodingPLCCNG";
+    case kStatsValueNameDer:
+      return "googDerBase64";
+    case kStatsValueNameDtlsCipher:
+      return "dtlsCipher";
+    case kStatsValueNameEchoDelayMedian:
+      return "googEchoCancellationEchoDelayMedian";
+    case kStatsValueNameEchoDelayStdDev:
+      return "googEchoCancellationEchoDelayStdDev";
+    case kStatsValueNameEchoReturnLoss:
+      return "googEchoCancellationReturnLoss";
+    case kStatsValueNameEchoReturnLossEnhancement:
+      return "googEchoCancellationReturnLossEnhancement";
+    case kStatsValueNameEncodeUsagePercent:
+      return "googEncodeUsagePercent";
+    case kStatsValueNameExpandRate:
+      return "googExpandRate";
+    case kStatsValueNameFingerprint:
+      return "googFingerprint";
+    case kStatsValueNameFingerprintAlgorithm:
+      return "googFingerprintAlgorithm";
+    case kStatsValueNameFirsReceived:
+      return "googFirsReceived";
+    case kStatsValueNameFirsSent:
+      return "googFirsSent";
+    case kStatsValueNameFirstFrameReceivedToDecodedMs:
+      return "googFirstFrameReceivedToDecodedMs";
+    case kStatsValueNameFrameHeightInput:
+      return "googFrameHeightInput";
+    case kStatsValueNameFrameHeightReceived:
+      return "googFrameHeightReceived";
+    case kStatsValueNameFrameHeightSent:
+      return "googFrameHeightSent";
+    case kStatsValueNameFrameRateReceived:
+      return "googFrameRateReceived";
+    case kStatsValueNameFrameRateDecoded:
+      return "googFrameRateDecoded";
+    case kStatsValueNameFrameRateOutput:
+      return "googFrameRateOutput";
+    case kStatsValueNameDecodeMs:
+      return "googDecodeMs";
+    case kStatsValueNameMaxDecodeMs:
+      return "googMaxDecodeMs";
+    case kStatsValueNameCurrentDelayMs:
+      return "googCurrentDelayMs";
+    case kStatsValueNameTargetDelayMs:
+      return "googTargetDelayMs";
+    case kStatsValueNameJitterBufferMs:
+      return "googJitterBufferMs";
+    case kStatsValueNameMinPlayoutDelayMs:
+      return "googMinPlayoutDelayMs";
+    case kStatsValueNameRenderDelayMs:
+      return "googRenderDelayMs";
+    case kStatsValueNameCaptureStartNtpTimeMs:
+      return "googCaptureStartNtpTimeMs";
+    case kStatsValueNameFrameRateInput:
+      return "googFrameRateInput";
+    case kStatsValueNameFrameRateSent:
+      return "googFrameRateSent";
+    case kStatsValueNameFrameWidthInput:
+      return "googFrameWidthInput";
+    case kStatsValueNameFrameWidthReceived:
+      return "googFrameWidthReceived";
+    case kStatsValueNameFrameWidthSent:
+      return "googFrameWidthSent";
+    case kStatsValueNameHasEnteredLowResolution:
+      return "googHasEnteredLowResolution";
+    case kStatsValueNameHugeFramesSent:
+      return "hugeFramesSent";
+    case kStatsValueNameInitiator:
+      return "googInitiator";
+    case kStatsValueNameInterframeDelayMaxMs:
+      return "googInterframeDelayMax";
+    case kStatsValueNameIssuerId:
+      return "googIssuerId";
+    case kStatsValueNameJitterReceived:
+      return "googJitterReceived";
+    case kStatsValueNameLocalAddress:
+      return "googLocalAddress";
+    case kStatsValueNameLocalCandidateId:
+      return "localCandidateId";
+    case kStatsValueNameLocalCandidateType:
+      return "googLocalCandidateType";
+    case kStatsValueNameLocalCertificateId:
+      return "localCertificateId";
+    case kStatsValueNameAdaptationChanges:
+      return "googAdaptationChanges";
+    case kStatsValueNameNacksReceived:
+      return "googNacksReceived";
+    case kStatsValueNameNacksSent:
+      return "googNacksSent";
+    case kStatsValueNamePreemptiveExpandRate:
+      return "googPreemptiveExpandRate";
+    case kStatsValueNamePlisReceived:
+      return "googPlisReceived";
+    case kStatsValueNamePlisSent:
+      return "googPlisSent";
+    case kStatsValueNamePreferredJitterBufferMs:
+      return "googPreferredJitterBufferMs";
+    case kStatsValueNameReceiving:
+      return "googReadable";
+    case kStatsValueNameRemoteAddress:
+      return "googRemoteAddress";
+    case kStatsValueNameRemoteCandidateId:
+      return "remoteCandidateId";
+    case kStatsValueNameRemoteCandidateType:
+      return "googRemoteCandidateType";
+    case kStatsValueNameRemoteCertificateId:
+      return "remoteCertificateId";
+    case kStatsValueNameResidualEchoLikelihood:
+      return "googResidualEchoLikelihood";
+    case kStatsValueNameResidualEchoLikelihoodRecentMax:
+      return "googResidualEchoLikelihoodRecentMax";
+    case kStatsValueNameAnaBitrateActionCounter:
+      return "googAnaBitrateActionCounter";
+    case kStatsValueNameAnaChannelActionCounter:
+      return "googAnaChannelActionCounter";
+    case kStatsValueNameAnaDtxActionCounter:
+      return "googAnaDtxActionCounter";
+    case kStatsValueNameAnaFecActionCounter:
+      return "googAnaFecActionCounter";
+    case kStatsValueNameAnaFrameLengthIncreaseCounter:
+      return "googAnaFrameLengthIncreaseCounter";
+    case kStatsValueNameAnaFrameLengthDecreaseCounter:
+      return "googAnaFrameLengthDecreaseCounter";
+    case kStatsValueNameAnaUplinkPacketLossFraction:
+      return "googAnaUplinkPacketLossFraction";
+    case kStatsValueNameRetransmitBitrate:
+      return "googRetransmitBitrate";
+    case kStatsValueNameRtt:
+      return "googRtt";
+    case kStatsValueNameSecondaryDecodedRate:
+      return "googSecondaryDecodedRate";
+    case kStatsValueNameSecondaryDiscardedRate:
+      return "googSecondaryDiscardedRate";
+    case kStatsValueNameSendPacketsDiscarded:
+      return "packetsDiscardedOnSend";
+    case kStatsValueNameSpeechExpandRate:
+      return "googSpeechExpandRate";
+    case kStatsValueNameSrtpCipher:
+      return "srtpCipher";
+    case kStatsValueNameTargetEncBitrate:
+      return "googTargetEncBitrate";
+    case kStatsValueNameTotalAudioEnergy:
+      return "totalAudioEnergy";
+    case kStatsValueNameTotalSamplesDuration:
+      return "totalSamplesDuration";
+    case kStatsValueNameTransmitBitrate:
+      return "googTransmitBitrate";
+    case kStatsValueNameTransportType:
+      return "googTransportType";
+    case kStatsValueNameTrackId:
+      return "googTrackId";
+    case kStatsValueNameTimingFrameInfo:
+      return "googTimingFrameInfo";
+    case kStatsValueNameTypingNoiseState:
+      return "googTypingNoiseState";
+    case kStatsValueNameWritable:
+      return "googWritable";
+  }
+
+  return nullptr;
+}
+
+std::string StatsReport::Value::ToString() const {
+  switch (type_) {
+    case kInt:
+      return rtc::ToString(value_.int_);
+    case kInt64:
+      return rtc::ToString(value_.int64_);
+    case kFloat:
+      return rtc::ToString(value_.float_);
+    case kStaticString:
+      return std::string(value_.static_string_);
+    case kString:
+      return *value_.string_;
+    case kBool:
+      return value_.bool_ ? "true" : "false";
+    case kId:
+      return (*value_.id_)->ToString();
+  }
+  RTC_NOTREACHED();
+  return std::string();
+}
+
+StatsReport::StatsReport(const Id& id) : id_(id), timestamp_(0.0) {
+  RTC_DCHECK(id_.get());
+}
+
+StatsReport::~StatsReport() = default;
+
+// static
+StatsReport::Id StatsReport::NewBandwidthEstimationId() {
+  return Id(new RefCountedObject<BandwidthEstimationId>());
+}
+
+// static
+StatsReport::Id StatsReport::NewTypedId(StatsType type, const std::string& id) {
+  return Id(new RefCountedObject<TypedId>(type, id));
+}
+
+// static
+StatsReport::Id StatsReport::NewTypedIntId(StatsType type, int id) {
+  return Id(new RefCountedObject<TypedIntId>(type, id));
+}
+
+// static
+StatsReport::Id StatsReport::NewIdWithDirection(
+    StatsType type,
+    const std::string& id,
+    StatsReport::Direction direction) {
+  return Id(new RefCountedObject<IdWithDirection>(type, id, direction));
+}
+
+// static
+StatsReport::Id StatsReport::NewCandidateId(bool local, const std::string& id) {
+  return Id(new RefCountedObject<CandidateId>(local, id));
+}
+
+// static
+StatsReport::Id StatsReport::NewComponentId(const std::string& content_name,
+                                            int component) {
+  return Id(new RefCountedObject<ComponentId>(content_name, component));
+}
+
+// static
+StatsReport::Id StatsReport::NewCandidatePairId(const std::string& content_name,
+                                                int component,
+                                                int index) {
+  return Id(
+      new RefCountedObject<CandidatePairId>(content_name, component, index));
+}
+
+const char* StatsReport::TypeToString() const {
+  return InternalTypeToString(id_->type());
+}
+
+void StatsReport::AddString(StatsReport::StatsValueName name,
+                            const std::string& value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddString(StatsReport::StatsValueName name,
+                            const char* value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddInt64(StatsReport::StatsValueName name, int64_t value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value, Value::kInt64));
+}
+
+void StatsReport::AddInt(StatsReport::StatsValueName name, int value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == static_cast<int64_t>(value)))
+    values_[name] = ValuePtr(new Value(name, value, Value::kInt));
+}
+
+void StatsReport::AddFloat(StatsReport::StatsValueName name, float value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddBoolean(StatsReport::StatsValueName name, bool value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+void StatsReport::AddId(StatsReport::StatsValueName name, const Id& value) {
+  const Value* found = FindValue(name);
+  if (!found || !(*found == value))
+    values_[name] = ValuePtr(new Value(name, value));
+}
+
+const StatsReport::Value* StatsReport::FindValue(StatsValueName name) const {
+  Values::const_iterator it = values_.find(name);
+  return it == values_.end() ? nullptr : it->second.get();
+}
+
+StatsCollection::StatsCollection() {}
+
+StatsCollection::~StatsCollection() {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  for (auto* r : list_)
+    delete r;
+}
+
+StatsCollection::const_iterator StatsCollection::begin() const {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  return list_.begin();
+}
+
+StatsCollection::const_iterator StatsCollection::end() const {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  return list_.end();
+}
+
+size_t StatsCollection::size() const {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  return list_.size();
+}
+
+StatsReport* StatsCollection::InsertNew(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  RTC_DCHECK(Find(id) == nullptr);
+  StatsReport* report = new StatsReport(id);
+  list_.push_back(report);
+  return report;
+}
+
+StatsReport* StatsCollection::FindOrAddNew(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  StatsReport* ret = Find(id);
+  return ret ? ret : InsertNew(id);
+}
+
+StatsReport* StatsCollection::ReplaceOrAddNew(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  RTC_DCHECK(id.get());
+  Container::iterator it = std::find_if(
+      list_.begin(), list_.end(),
+      [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
+  if (it != end()) {
+    StatsReport* report = new StatsReport((*it)->id());
+    delete *it;
+    *it = report;
+    return report;
+  }
+  return InsertNew(id);
+}
+
+// Looks for a report with the given |id|.  If one is not found, null
+// will be returned.
+StatsReport* StatsCollection::Find(const StatsReport::Id& id) {
+  RTC_DCHECK(thread_checker_.CalledOnValidThread());
+  Container::iterator it = std::find_if(
+      list_.begin(), list_.end(),
+      [&id](const StatsReport* r) -> bool { return r->id()->Equals(id); });
+  return it == list_.end() ? nullptr : *it;
+}
+
+}  // namespace webrtc
diff --git a/api/stats_types.h b/api/stats_types.h
new file mode 100644
index 0000000..0e97eaf
--- /dev/null
+++ b/api/stats_types.h
@@ -0,0 +1,452 @@
+/*
+ *  Copyright 2012 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.
+ */
+
+// This file contains structures used for retrieving statistics from an ongoing
+// libjingle session.
+
+#ifndef API_STATS_TYPES_H_
+#define API_STATS_TYPES_H_
+
+#include <algorithm>
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "api/scoped_refptr.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/ref_count.h"
+#include "rtc_base/string_encode.h"
+#include "rtc_base/thread_checker.h"
+
+namespace webrtc {
+
+class StatsReport {
+ public:
+  // Indicates whether a track is for sending or receiving.
+  // Used in reports for audio/video tracks.
+  enum Direction {
+    kSend = 0,
+    kReceive,
+  };
+
+  enum StatsType {
+    // StatsReport types.
+    // A StatsReport of |type| = "googSession" contains overall information
+    // about the thing libjingle calls a session (which may contain one
+    // or more RTP sessions.
+    kStatsReportTypeSession,
+
+    // A StatsReport of |type| = "googTransport" contains information
+    // about a libjingle "transport".
+    kStatsReportTypeTransport,
+
+    // A StatsReport of |type| = "googComponent" contains information
+    // about a libjingle "channel" (typically, RTP or RTCP for a transport).
+    // This is intended to be the same thing as an ICE "Component".
+    kStatsReportTypeComponent,
+
+    // A StatsReport of |type| = "googCandidatePair" contains information
+    // about a libjingle "connection" - a single source/destination port pair.
+    // This is intended to be the same thing as an ICE "candidate pair".
+    kStatsReportTypeCandidatePair,
+
+    // A StatsReport of |type| = "VideoBWE" is statistics for video Bandwidth
+    // Estimation, which is global per-session.  The |id| field is "bweforvideo"
+    // (will probably change in the future).
+    kStatsReportTypeBwe,
+
+    // A StatsReport of |type| = "ssrc" is statistics for a specific rtp stream.
+    // The |id| field is the SSRC in decimal form of the rtp stream.
+    kStatsReportTypeSsrc,
+
+    // A StatsReport of |type| = "remoteSsrc" is statistics for a specific
+    // rtp stream, generated by the remote end of the connection.
+    kStatsReportTypeRemoteSsrc,
+
+    // A StatsReport of |type| = "googTrack" is statistics for a specific media
+    // track. The |id| field is the track id.
+    kStatsReportTypeTrack,
+
+    // A StatsReport of |type| = "localcandidate" or "remotecandidate" is
+    // attributes on a specific ICE Candidate. It links to its connection pair
+    // by candidate id. The string value is taken from
+    // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*.
+    kStatsReportTypeIceLocalCandidate,
+    kStatsReportTypeIceRemoteCandidate,
+
+    // A StatsReport of |type| = "googCertificate" contains an SSL certificate
+    // transmitted by one of the endpoints of this connection.  The |id| is
+    // controlled by the fingerprint, and is used to identify the certificate in
+    // the Channel stats (as "googLocalCertificateId" or
+    // "googRemoteCertificateId") and in any child certificates (as
+    // "googIssuerId").
+    kStatsReportTypeCertificate,
+
+    // A StatsReport of |type| = "datachannel" with statistics for a
+    // particular DataChannel.
+    kStatsReportTypeDataChannel,
+  };
+
+  enum StatsValueName {
+    kStatsValueNameActiveConnection,
+    kStatsValueNameAecDivergentFilterFraction,
+    kStatsValueNameAudioInputLevel,
+    kStatsValueNameAudioOutputLevel,
+    kStatsValueNameBytesReceived,
+    kStatsValueNameBytesSent,
+    kStatsValueNameCodecImplementationName,
+    kStatsValueNameConcealedSamples,
+    kStatsValueNameConcealmentEvents,
+    kStatsValueNameDataChannelId,
+    kStatsValueNameFramesDecoded,
+    kStatsValueNameFramesEncoded,
+    kStatsValueNameJitterBufferDelay,
+    kStatsValueNameMediaType,
+    kStatsValueNamePacketsLost,
+    kStatsValueNamePacketsReceived,
+    kStatsValueNamePacketsSent,
+    kStatsValueNameProtocol,
+    kStatsValueNameQpSum,
+    kStatsValueNameReceiving,
+    kStatsValueNameSelectedCandidatePairId,
+    kStatsValueNameSsrc,
+    kStatsValueNameState,
+    kStatsValueNameTotalAudioEnergy,
+    kStatsValueNameTotalSamplesDuration,
+    kStatsValueNameTotalSamplesReceived,
+    kStatsValueNameTransportId,
+    kStatsValueNameSentPingRequestsTotal,
+    kStatsValueNameSentPingRequestsBeforeFirstResponse,
+    kStatsValueNameSentPingResponses,
+    kStatsValueNameRecvPingRequests,
+    kStatsValueNameRecvPingResponses,
+    kStatsValueNameSentStunKeepaliveRequests,
+    kStatsValueNameRecvStunKeepaliveResponses,
+    kStatsValueNameStunKeepaliveRttTotal,
+    kStatsValueNameStunKeepaliveRttSquaredTotal,
+
+    // Internal StatsValue names.
+    kStatsValueNameAccelerateRate,
+    kStatsValueNameActualEncBitrate,
+    kStatsValueNameAdaptationChanges,
+    kStatsValueNameAvailableReceiveBandwidth,
+    kStatsValueNameAvailableSendBandwidth,
+    kStatsValueNameAvgEncodeMs,
+    kStatsValueNameBandwidthLimitedResolution,
+    kStatsValueNameBucketDelay,
+    kStatsValueNameCaptureStartNtpTimeMs,
+    kStatsValueNameCandidateIPAddress,
+    kStatsValueNameCandidateNetworkType,
+    kStatsValueNameCandidatePortNumber,
+    kStatsValueNameCandidatePriority,
+    kStatsValueNameCandidateTransportType,
+    kStatsValueNameCandidateType,
+    kStatsValueNameChannelId,
+    kStatsValueNameCodecName,
+    kStatsValueNameComponent,
+    kStatsValueNameContentName,
+    kStatsValueNameContentType,
+    kStatsValueNameCpuLimitedResolution,
+    kStatsValueNameCurrentDelayMs,
+    kStatsValueNameDecodeMs,
+    kStatsValueNameDecodingCNG,
+    kStatsValueNameDecodingCTN,
+    kStatsValueNameDecodingCTSG,
+    kStatsValueNameDecodingMutedOutput,
+    kStatsValueNameDecodingNormal,
+    kStatsValueNameDecodingPLC,
+    kStatsValueNameDecodingPLCCNG,
+    kStatsValueNameDer,
+    kStatsValueNameDtlsCipher,
+    kStatsValueNameEchoDelayMedian,
+    kStatsValueNameEchoDelayStdDev,
+    kStatsValueNameEchoReturnLoss,
+    kStatsValueNameEchoReturnLossEnhancement,
+    kStatsValueNameEncodeUsagePercent,
+    kStatsValueNameExpandRate,
+    kStatsValueNameFingerprint,
+    kStatsValueNameFingerprintAlgorithm,
+    kStatsValueNameFirsReceived,
+    kStatsValueNameFirsSent,
+    kStatsValueNameFirstFrameReceivedToDecodedMs,
+    kStatsValueNameFrameHeightInput,
+    kStatsValueNameFrameHeightReceived,
+    kStatsValueNameFrameHeightSent,
+    kStatsValueNameFrameRateDecoded,
+    kStatsValueNameFrameRateInput,
+    kStatsValueNameFrameRateOutput,
+    kStatsValueNameFrameRateReceived,
+    kStatsValueNameFrameRateSent,
+    kStatsValueNameFrameWidthInput,
+    kStatsValueNameFrameWidthReceived,
+    kStatsValueNameFrameWidthSent,
+    kStatsValueNameHasEnteredLowResolution,
+    kStatsValueNameHugeFramesSent,
+    kStatsValueNameInitiator,
+    kStatsValueNameInterframeDelayMaxMs,  // Max over last 10 seconds.
+    kStatsValueNameIssuerId,
+    kStatsValueNameJitterBufferMs,
+    kStatsValueNameJitterReceived,
+    kStatsValueNameLabel,
+    kStatsValueNameLocalAddress,
+    kStatsValueNameLocalCandidateId,
+    kStatsValueNameLocalCandidateType,
+    kStatsValueNameLocalCertificateId,
+    kStatsValueNameMaxDecodeMs,
+    kStatsValueNameMinPlayoutDelayMs,
+    kStatsValueNameNacksReceived,
+    kStatsValueNameNacksSent,
+    kStatsValueNamePlisReceived,
+    kStatsValueNamePlisSent,
+    kStatsValueNamePreemptiveExpandRate,
+    kStatsValueNamePreferredJitterBufferMs,
+    kStatsValueNameRemoteAddress,
+    kStatsValueNameRemoteCandidateId,
+    kStatsValueNameRemoteCandidateType,
+    kStatsValueNameRemoteCertificateId,
+    kStatsValueNameRenderDelayMs,
+    kStatsValueNameResidualEchoLikelihood,
+    kStatsValueNameResidualEchoLikelihoodRecentMax,
+    kStatsValueNameAnaBitrateActionCounter,
+    kStatsValueNameAnaChannelActionCounter,
+    kStatsValueNameAnaDtxActionCounter,
+    kStatsValueNameAnaFecActionCounter,
+    kStatsValueNameAnaFrameLengthIncreaseCounter,
+    kStatsValueNameAnaFrameLengthDecreaseCounter,
+    kStatsValueNameAnaUplinkPacketLossFraction,
+    kStatsValueNameRetransmitBitrate,
+    kStatsValueNameRtt,
+    kStatsValueNameSecondaryDecodedRate,
+    kStatsValueNameSecondaryDiscardedRate,
+    kStatsValueNameSendPacketsDiscarded,
+    kStatsValueNameSpeechExpandRate,
+    kStatsValueNameSrtpCipher,
+    kStatsValueNameTargetDelayMs,
+    kStatsValueNameTargetEncBitrate,
+    kStatsValueNameTimingFrameInfo,  // Result of |TimingFrameInfo::ToString|
+    kStatsValueNameTrackId,
+    kStatsValueNameTransmitBitrate,
+    kStatsValueNameTransportType,
+    kStatsValueNameTypingNoiseState,
+    kStatsValueNameWritable,
+  };
+
+  class IdBase : public rtc::RefCountInterface {
+   public:
+    ~IdBase() override;
+    StatsType type() const;
+
+    // Users of IdBase will be using the Id typedef, which is compatible with
+    // this Equals() function.  It simply calls the protected (and overridden)
+    // Equals() method.
+    bool Equals(const rtc::scoped_refptr<IdBase>& other) const {
+      return Equals(*other.get());
+    }
+
+    virtual std::string ToString() const = 0;
+
+   protected:
+    // Protected since users of the IdBase type will be using the Id typedef.
+    virtual bool Equals(const IdBase& other) const;
+
+    explicit IdBase(StatsType type);  // Only meant for derived classes.
+    const StatsType type_;
+
+    static const char kSeparator = '_';
+  };
+
+  typedef rtc::scoped_refptr<IdBase> Id;
+
+  struct Value {
+    enum Type {
+      kInt,           // int.
+      kInt64,         // int64_t.
+      kFloat,         // float.
+      kString,        // std::string
+      kStaticString,  // const char*.
+      kBool,          // bool.
+      kId,            // Id.
+    };
+
+    Value(StatsValueName name, int64_t value, Type int_type);
+    Value(StatsValueName name, float f);
+    Value(StatsValueName name, const std::string& value);
+    Value(StatsValueName name, const char* value);
+    Value(StatsValueName name, bool b);
+    Value(StatsValueName name, const Id& value);
+
+    ~Value();
+
+    // Support ref counting. Note that for performance reasons, we
+    // don't use thread safe operations. Therefore, all operations
+    // affecting the ref count (in practice, creation and copying of
+    // the Values mapping) must occur on webrtc's signalling thread.
+    int AddRef() const {
+      RTC_DCHECK_RUN_ON(&thread_checker_);
+      return ++ref_count_;
+    }
+    int Release() const {
+      RTC_DCHECK_RUN_ON(&thread_checker_);
+      int count = --ref_count_;
+      if (!count)
+        delete this;
+      return count;
+    }
+
+    // TODO(tommi): This compares name as well as value...
+    // I think we should only need to compare the value part and
+    // move the name part into a hash map.
+    bool Equals(const Value& other) const;
+
+    // Comparison operators. Return true iff the current instance is of the
+    // correct type and holds the same value.  No conversion is performed so
+    // a string value of "123" is not equal to an int value of 123 and an int
+    // value of 123 is not equal to a float value of 123.0f.
+    // One exception to this is that types kInt and kInt64 can be compared and
+    // kString and kStaticString too.
+    bool operator==(const std::string& value) const;
+    bool operator==(const char* value) const;
+    bool operator==(int64_t value) const;
+    bool operator==(bool value) const;
+    bool operator==(float value) const;
+    bool operator==(const Id& value) const;
+
+    // Getters that allow getting the native value directly.
+    // The caller must know the type beforehand or else hit a check.
+    int int_val() const;
+    int64_t int64_val() const;
+    float float_val() const;
+    const char* static_string_val() const;
+    const std::string& string_val() const;
+    bool bool_val() const;
+    const Id& id_val() const;
+
+    // Returns the string representation of |name|.
+    const char* display_name() const;
+
+    // Converts the native value to a string representation of the value.
+    std::string ToString() const;
+
+    Type type() const { return type_; }
+
+    // TODO(tommi): Move |name| and |display_name| out of the Value struct.
+    const StatsValueName name;
+
+   private:
+    rtc::ThreadChecker thread_checker_;
+    mutable int ref_count_ RTC_GUARDED_BY(thread_checker_) = 0;
+
+    const Type type_;
+    // TODO(tommi): Use C++ 11 union and make value_ const.
+    union InternalType {
+      int int_;
+      int64_t int64_;
+      float float_;
+      bool bool_;
+      std::string* string_;
+      const char* static_string_;
+      Id* id_;
+    } value_;
+
+    RTC_DISALLOW_COPY_AND_ASSIGN(Value);
+  };
+
+  typedef rtc::scoped_refptr<Value> ValuePtr;
+  typedef std::map<StatsValueName, ValuePtr> Values;
+
+  // Ownership of |id| is passed to |this|.
+  explicit StatsReport(const Id& id);
+  ~StatsReport();
+
+  // Factory functions for various types of stats IDs.
+  static Id NewBandwidthEstimationId();
+  static Id NewTypedId(StatsType type, const std::string& id);
+  static Id NewTypedIntId(StatsType type, int id);
+  static Id NewIdWithDirection(StatsType type,
+                               const std::string& id,
+                               Direction direction);
+  static Id NewCandidateId(bool local, const std::string& id);
+  static Id NewComponentId(const std::string& content_name, int component);
+  static Id NewCandidatePairId(const std::string& content_name,
+                               int component,
+                               int index);
+
+  const Id& id() const { return id_; }
+  StatsType type() const { return id_->type(); }
+  double timestamp() const { return timestamp_; }
+  void set_timestamp(double t) { timestamp_ = t; }
+  bool empty() const { return values_.empty(); }
+  const Values& values() const { return values_; }
+
+  const char* TypeToString() const;
+
+  void AddString(StatsValueName name, const std::string& value);
+  void AddString(StatsValueName name, const char* value);
+  void AddInt64(StatsValueName name, int64_t value);
+  void AddInt(StatsValueName name, int value);
+  void AddFloat(StatsValueName name, float value);
+  void AddBoolean(StatsValueName name, bool value);
+  void AddId(StatsValueName name, const Id& value);
+
+  const Value* FindValue(StatsValueName name) const;
+
+ private:
+  // The unique identifier for this object.
+  // This is used as a key for this report in ordered containers,
+  // so it must never be changed.
+  const Id id_;
+  double timestamp_;  // Time since 1970-01-01T00:00:00Z in milliseconds.
+  Values values_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(StatsReport);
+};
+
+// Typedef for an array of const StatsReport pointers.
+// Ownership of the pointers held by this implementation is assumed to lie
+// elsewhere and lifetime guarantees are made by the implementation that uses
+// this type.  In the StatsCollector, object ownership lies with the
+// StatsCollection class.
+typedef std::vector<const StatsReport*> StatsReports;
+
+// A map from the report id to the report.
+// This class wraps an STL container and provides a limited set of
+// functionality in order to keep things simple.
+class StatsCollection {
+ public:
+  StatsCollection();
+  ~StatsCollection();
+
+  typedef std::list<StatsReport*> Container;
+  typedef Container::iterator iterator;
+  typedef Container::const_iterator const_iterator;
+
+  const_iterator begin() const;
+  const_iterator end() const;
+  size_t size() const;
+
+  // Creates a new report object with |id| that does not already
+  // exist in the list of reports.
+  StatsReport* InsertNew(const StatsReport::Id& id);
+  StatsReport* FindOrAddNew(const StatsReport::Id& id);
+  StatsReport* ReplaceOrAddNew(const StatsReport::Id& id);
+
+  // Looks for a report with the given |id|.  If one is not found, null
+  // will be returned.
+  StatsReport* Find(const StatsReport::Id& id);
+
+ private:
+  Container list_;
+  rtc::ThreadChecker thread_checker_;
+};
+
+}  // namespace webrtc
+
+#endif  // API_STATS_TYPES_H_
diff --git a/api/task_queue/default_task_queue_factory.h b/api/task_queue/default_task_queue_factory.h
new file mode 100644
index 0000000..ccdd1eb
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory.h
@@ -0,0 +1,23 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_
+#define API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory();
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_DEFAULT_TASK_QUEUE_FACTORY_H_
diff --git a/api/task_queue/default_task_queue_factory_gcd.cc b/api/task_queue/default_task_queue_factory_gcd.cc
new file mode 100644
index 0000000..7e17b48
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_gcd.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 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 <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_gcd.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueGcdFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_libevent.cc b/api/task_queue/default_task_queue_factory_libevent.cc
new file mode 100644
index 0000000..f2fb418
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_libevent.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 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 <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_libevent.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueLibeventFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_stdlib.cc b/api/task_queue/default_task_queue_factory_stdlib.cc
new file mode 100644
index 0000000..ca7d720
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_stdlib.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 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 <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_stdlib.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueStdlibFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_unittest.cc b/api/task_queue/default_task_queue_factory_unittest.cc
new file mode 100644
index 0000000..92c17d8
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_unittest.cc
@@ -0,0 +1,24 @@
+/*
+ *  Copyright 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 "api/task_queue/default_task_queue_factory.h"
+
+#include "api/task_queue/task_queue_test.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace {
+
+INSTANTIATE_TEST_SUITE_P(Default,
+                         TaskQueueTest,
+                         ::testing::Values(CreateDefaultTaskQueueFactory));
+
+}  // namespace
+}  // namespace webrtc
diff --git a/api/task_queue/default_task_queue_factory_win.cc b/api/task_queue/default_task_queue_factory_win.cc
new file mode 100644
index 0000000..493ea66
--- /dev/null
+++ b/api/task_queue/default_task_queue_factory_win.cc
@@ -0,0 +1,21 @@
+/*
+ *  Copyright 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 <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "rtc_base/task_queue_win.h"
+
+namespace webrtc {
+
+std::unique_ptr<TaskQueueFactory> CreateDefaultTaskQueueFactory() {
+  return CreateTaskQueueWinFactory();
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/global_task_queue_factory.cc b/api/task_queue/global_task_queue_factory.cc
new file mode 100644
index 0000000..528d14d
--- /dev/null
+++ b/api/task_queue/global_task_queue_factory.cc
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 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 "api/task_queue/global_task_queue_factory.h"
+
+#include "api/task_queue/default_task_queue_factory.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace {
+
+TaskQueueFactory* GlobalOrDefault(TaskQueueFactory* global) {
+  static TaskQueueFactory* const factory =
+      global ? global : CreateDefaultTaskQueueFactory().release();
+  return factory;
+}
+
+}  // namespace
+
+void SetGlobalTaskQueueFactory(std::unique_ptr<TaskQueueFactory> factory) {
+  RTC_CHECK(factory) << "Can't set nullptr TaskQueueFactory";
+  // Own, but never delete the global factory.
+  TaskQueueFactory* global = factory.release();
+  RTC_CHECK(GlobalOrDefault(global) == global)
+      << "Task queue factory set after another SetFactory or after a task "
+         "queue was created";
+}
+
+TaskQueueFactory& GlobalTaskQueueFactory() {
+  return *GlobalOrDefault(nullptr);
+}
+
+}  // namespace webrtc
diff --git a/api/task_queue/global_task_queue_factory.h b/api/task_queue/global_task_queue_factory.h
new file mode 100644
index 0000000..a580833
--- /dev/null
+++ b/api/task_queue/global_task_queue_factory.h
@@ -0,0 +1,27 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TASK_QUEUE_GLOBAL_TASK_QUEUE_FACTORY_H_
+#define API_TASK_QUEUE_GLOBAL_TASK_QUEUE_FACTORY_H_
+
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+
+namespace webrtc {
+
+// May be called at most once, and before any TaskQueue is created.
+void SetGlobalTaskQueueFactory(std::unique_ptr<TaskQueueFactory> factory);
+
+// Returns TaskQueue factory. Always returns the same factory.
+TaskQueueFactory& GlobalTaskQueueFactory();
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_GLOBAL_TASK_QUEUE_FACTORY_H_
diff --git a/api/task_queue/module.mk b/api/task_queue/module.mk
new file mode 100644
index 0000000..37c23f4
--- /dev/null
+++ b/api/task_queue/module.mk
@@ -0,0 +1,5 @@
+# Copyright 2018 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include common.mk
diff --git a/api/task_queue/queued_task.h b/api/task_queue/queued_task.h
new file mode 100644
index 0000000..5748628
--- /dev/null
+++ b/api/task_queue/queued_task.h
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 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_TASK_QUEUE_QUEUED_TASK_H_
+#define API_TASK_QUEUE_QUEUED_TASK_H_
+
+namespace webrtc {
+
+// Base interface for asynchronously executed tasks.
+// The interface basically consists of a single function, Run(), that executes
+// on the target queue.  For more details see the Run() method and TaskQueue.
+class QueuedTask {
+ public:
+  virtual ~QueuedTask() = default;
+
+  // Main routine that will run when the task is executed on the desired queue.
+  // The task should return |true| to indicate that it should be deleted or
+  // |false| to indicate that the queue should consider ownership of the task
+  // having been transferred.  Returning |false| can be useful if a task has
+  // re-posted itself to a different queue or is otherwise being re-used.
+  virtual bool Run() = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_QUEUED_TASK_H_
diff --git a/api/task_queue/task_queue_base.cc b/api/task_queue/task_queue_base.cc
new file mode 100644
index 0000000..7d3539a
--- /dev/null
+++ b/api/task_queue/task_queue_base.cc
@@ -0,0 +1,79 @@
+/*
+ *  Copyright 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 "api/task_queue/task_queue_base.h"
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "rtc_base/checks.h"
+
+#if defined(ABSL_HAVE_THREAD_LOCAL)
+
+namespace webrtc {
+namespace {
+
+ABSL_CONST_INIT thread_local TaskQueueBase* current = nullptr;
+
+}  // namespace
+
+TaskQueueBase* TaskQueueBase::Current() {
+  return current;
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
+    TaskQueueBase* task_queue)
+    : previous_(current) {
+  current = task_queue;
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
+  current = previous_;
+}
+}  // namespace webrtc
+
+#elif defined(WEBRTC_POSIX)
+
+#include <pthread.h>
+
+namespace webrtc {
+namespace {
+
+ABSL_CONST_INIT pthread_key_t g_queue_ptr_tls = 0;
+
+void InitializeTls() {
+  RTC_CHECK(pthread_key_create(&g_queue_ptr_tls, nullptr) == 0);
+}
+
+pthread_key_t GetQueuePtrTls() {
+  static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+  RTC_CHECK(pthread_once(&init_once, &InitializeTls) == 0);
+  return g_queue_ptr_tls;
+}
+
+}  // namespace
+
+TaskQueueBase* TaskQueueBase::Current() {
+  return static_cast<TaskQueueBase*>(pthread_getspecific(GetQueuePtrTls()));
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::CurrentTaskQueueSetter(
+    TaskQueueBase* task_queue)
+    : previous_(TaskQueueBase::Current()) {
+  pthread_setspecific(GetQueuePtrTls(), task_queue);
+}
+
+TaskQueueBase::CurrentTaskQueueSetter::~CurrentTaskQueueSetter() {
+  pthread_setspecific(GetQueuePtrTls(), previous_);
+}
+
+}  // namespace webrtc
+
+#else
+#error Unsupported platform
+#endif
diff --git a/api/task_queue/task_queue_base.h b/api/task_queue/task_queue_base.h
new file mode 100644
index 0000000..b1b5cc7
--- /dev/null
+++ b/api/task_queue/task_queue_base.h
@@ -0,0 +1,91 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TASK_QUEUE_TASK_QUEUE_BASE_H_
+#define API_TASK_QUEUE_TASK_QUEUE_BASE_H_
+
+#include <memory>
+
+#include "api/task_queue/queued_task.h"
+
+// TODO(bugs.webrtc.org/10191): Remove when
+// rtc::TaskQueue* rtc::TaskQueue::Current() is unused.
+namespace rtc {
+class TaskQueue;
+}  // namespace rtc
+
+namespace webrtc {
+
+// Asynchronously executes tasks in a way that guarantees that they're executed
+// in FIFO order and that tasks never overlap. Tasks may always execute on the
+// same worker thread and they may not. To DCHECK that tasks are executing on a
+// known task queue, use IsCurrent().
+class TaskQueueBase {
+ public:
+  // Starts destruction of the task queue.
+  // On return ensures no task are running and no new tasks are able to start
+  // on the task queue.
+  // Responsible for deallocation. Deallocation may happen syncrhoniously during
+  // Delete or asynchronously after Delete returns.
+  // Code not running on the TaskQueue should not make any assumption when
+  // TaskQueue is deallocated and thus should not call any methods after Delete.
+  // Code running on the TaskQueue should not call Delete, but can assume
+  // TaskQueue still exists and may call other methods, e.g. PostTask.
+  virtual void Delete() = 0;
+
+  // Schedules a task to execute. Tasks are executed in FIFO order.
+  // If |task->Run()| returns true, task is deleted on the task queue
+  // before next QueuedTask starts executing.
+  // When a TaskQueue is deleted, pending tasks will not be executed but they
+  // will be deleted. The deletion of tasks may happen synchronously on the
+  // TaskQueue or it may happen asynchronously after TaskQueue is deleted.
+  // This may vary from one implementation to the next so assumptions about
+  // lifetimes of pending tasks should not be made.
+  virtual void PostTask(std::unique_ptr<QueuedTask> task) = 0;
+
+  // Schedules a task to execute a specified number of milliseconds from when
+  // the call is made. The precision should be considered as "best effort"
+  // and in some cases, such as on Windows when all high precision timers have
+  // been used up, can be off by as much as 15 millseconds.
+  virtual void PostDelayedTask(std::unique_ptr<QueuedTask> task,
+                               uint32_t milliseconds) = 0;
+
+  // Returns the task queue that is running the current thread.
+  // Returns nullptr if this thread is not associated with any task queue.
+  static TaskQueueBase* Current();
+  bool IsCurrent() const { return Current() == this; }
+
+ protected:
+  class CurrentTaskQueueSetter {
+   public:
+    explicit CurrentTaskQueueSetter(TaskQueueBase* task_queue);
+    CurrentTaskQueueSetter(const CurrentTaskQueueSetter&) = delete;
+    CurrentTaskQueueSetter& operator=(const CurrentTaskQueueSetter&) = delete;
+    ~CurrentTaskQueueSetter();
+
+   private:
+    TaskQueueBase* const previous_;
+  };
+
+  // Users of the TaskQueue should call Delete instead of directly deleting
+  // this object.
+  virtual ~TaskQueueBase() = default;
+
+ private:
+  friend class rtc::TaskQueue;
+  rtc::TaskQueue* task_queue_ = nullptr;
+};
+
+struct TaskQueueDeleter {
+  void operator()(TaskQueueBase* task_queue) const { task_queue->Delete(); }
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_TASK_QUEUE_BASE_H_
diff --git a/api/task_queue/task_queue_factory.h b/api/task_queue/task_queue_factory.h
new file mode 100644
index 0000000..b68ab33
--- /dev/null
+++ b/api/task_queue/task_queue_factory.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_
+#define API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_
+
+#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "api/task_queue/task_queue_base.h"
+
+namespace webrtc {
+
+// The implementation of this interface must be thread-safe.
+class TaskQueueFactory {
+ public:
+  // TaskQueue priority levels. On some platforms these will map to thread
+  // priorities, on others such as Mac and iOS, GCD queue priorities.
+  enum class Priority { NORMAL = 0, HIGH, LOW };
+
+  virtual ~TaskQueueFactory() = default;
+  virtual std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+      absl::string_view name,
+      Priority priority) const = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_TASK_QUEUE_FACTORY_H_
diff --git a/api/task_queue/task_queue_test.cc b/api/task_queue/task_queue_test.cc
new file mode 100644
index 0000000..e78dbd2
--- /dev/null
+++ b/api/task_queue/task_queue_test.cc
@@ -0,0 +1,254 @@
+/*
+ *  Copyright 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 "api/task_queue/task_queue_test.h"
+
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "rtc_base/event.h"
+#include "rtc_base/task_utils/to_queued_task.h"
+#include "rtc_base/time_utils.h"
+
+namespace webrtc {
+namespace {
+
+std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
+    const std::unique_ptr<webrtc::TaskQueueFactory>& factory,
+    absl::string_view task_queue_name,
+    TaskQueueFactory::Priority priority = TaskQueueFactory::Priority::NORMAL) {
+  return factory->CreateTaskQueue(task_queue_name, priority);
+}
+
+TEST_P(TaskQueueTest, Construct) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  auto queue = CreateTaskQueue(factory, "Construct");
+  EXPECT_FALSE(queue->IsCurrent());
+}
+
+TEST_P(TaskQueueTest, PostAndCheckCurrent) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue = CreateTaskQueue(factory, "PostAndCheckCurrent");
+
+  // We're not running a task, so there shouldn't be a current queue.
+  EXPECT_FALSE(queue->IsCurrent());
+  EXPECT_FALSE(TaskQueueBase::Current());
+
+  queue->PostTask(ToQueuedTask([&event, &queue] {
+    EXPECT_TRUE(queue->IsCurrent());
+    event.Set();
+  }));
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostCustomTask) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event ran;
+  auto queue = CreateTaskQueue(factory, "PostCustomImplementation");
+
+  class CustomTask : public QueuedTask {
+   public:
+    explicit CustomTask(rtc::Event* ran) : ran_(ran) {}
+
+   private:
+    bool Run() override {
+      ran_->Set();
+      return false;  // Do not allow the task to be deleted by the queue.
+    }
+
+    rtc::Event* const ran_;
+  } my_task(&ran);
+
+  queue->PostTask(absl::WrapUnique(&my_task));
+  EXPECT_TRUE(ran.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostDelayedZero) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue = CreateTaskQueue(factory, "PostDelayedZero");
+
+  queue->PostDelayedTask(ToQueuedTask([&event] { event.Set(); }), 0);
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostFromQueue) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue = CreateTaskQueue(factory, "PostFromQueue");
+
+  queue->PostTask(ToQueuedTask([&event, &queue] {
+    queue->PostTask(ToQueuedTask([&event] { event.Set(); }));
+  }));
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostDelayed) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto queue =
+      CreateTaskQueue(factory, "PostDelayed", TaskQueueFactory::Priority::HIGH);
+
+  int64_t start = rtc::TimeMillis();
+  queue->PostDelayedTask(ToQueuedTask([&event, &queue] {
+                           EXPECT_TRUE(queue->IsCurrent());
+                           event.Set();
+                         }),
+                         100);
+  EXPECT_TRUE(event.Wait(1000));
+  int64_t end = rtc::TimeMillis();
+  // These tests are a little relaxed due to how "powerful" our test bots can
+  // be.  Most recently we've seen windows bots fire the callback after 94-99ms,
+  // which is why we have a little bit of leeway backwards as well.
+  EXPECT_GE(end - start, 90u);
+  EXPECT_NEAR(end - start, 190u, 100u);  // Accept 90-290.
+}
+
+TEST_P(TaskQueueTest, PostMultipleDelayed) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  auto queue = CreateTaskQueue(factory, "PostMultipleDelayed");
+
+  std::vector<rtc::Event> events(100);
+  for (int i = 0; i < 100; ++i) {
+    rtc::Event* event = &events[i];
+    queue->PostDelayedTask(ToQueuedTask([event, &queue] {
+                             EXPECT_TRUE(queue->IsCurrent());
+                             event->Set();
+                           }),
+                           i);
+  }
+
+  for (rtc::Event& e : events)
+    EXPECT_TRUE(e.Wait(1000));
+}
+
+TEST_P(TaskQueueTest, PostDelayedAfterDestruct) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event run;
+  rtc::Event deleted;
+  auto queue = CreateTaskQueue(factory, "PostDelayedAfterDestruct");
+  queue->PostDelayedTask(
+      ToQueuedTask([&run] { run.Set(); }, [&deleted] { deleted.Set(); }), 100);
+  // Destroy the queue.
+  queue = nullptr;
+  // Task might outlive the TaskQueue, but still should be deleted.
+  EXPECT_TRUE(deleted.Wait(200));
+  EXPECT_FALSE(run.Wait(0));  // and should not run.
+}
+
+TEST_P(TaskQueueTest, PostAndReuse) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  rtc::Event event;
+  auto post_queue = CreateTaskQueue(factory, "PostQueue");
+  auto reply_queue = CreateTaskQueue(factory, "ReplyQueue");
+
+  int call_count = 0;
+
+  class ReusedTask : public QueuedTask {
+   public:
+    ReusedTask(int* counter, TaskQueueBase* reply_queue, rtc::Event* event)
+        : counter_(*counter), reply_queue_(reply_queue), event_(*event) {
+      EXPECT_EQ(counter_, 0);
+    }
+
+   private:
+    bool Run() override {
+      if (++counter_ == 1) {
+        reply_queue_->PostTask(absl::WrapUnique(this));
+        // At this point, the object is owned by reply_queue_ and it's
+        // theoratically possible that the object has been deleted (e.g. if
+        // posting wasn't possible).  So, don't touch any member variables here.
+
+        // Indicate to the current queue that ownership has been transferred.
+        return false;
+      } else {
+        EXPECT_EQ(counter_, 2);
+        EXPECT_TRUE(reply_queue_->IsCurrent());
+        event_.Set();
+        return true;  // Indicate that the object should be deleted.
+      }
+    }
+
+    int& counter_;
+    TaskQueueBase* const reply_queue_;
+    rtc::Event& event_;
+  };
+
+  auto task =
+      absl::make_unique<ReusedTask>(&call_count, reply_queue.get(), &event);
+  post_queue->PostTask(std::move(task));
+  EXPECT_TRUE(event.Wait(1000));
+}
+
+// Tests posting more messages than a queue can queue up.
+// In situations like that, tasks will get dropped.
+TEST_P(TaskQueueTest, PostALot) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  // To destruct the event after the queue has gone out of scope.
+  rtc::Event event;
+
+  int tasks_executed = 0;
+  int tasks_cleaned_up = 0;
+  static const int kTaskCount = 0xffff;
+
+  {
+    auto queue = CreateTaskQueue(factory, "PostALot");
+
+    // On linux, the limit of pending bytes in the pipe buffer is 0xffff.
+    // So here we post a total of 0xffff+1 messages, which triggers a failure
+    // case inside of the libevent queue implementation.
+
+    queue->PostTask(
+        ToQueuedTask([&event] { event.Wait(rtc::Event::kForever); }));
+    for (int i = 0; i < kTaskCount; ++i)
+      queue->PostTask(
+          ToQueuedTask([&tasks_executed] { ++tasks_executed; },
+                       [&tasks_cleaned_up] { ++tasks_cleaned_up; }));
+    event.Set();  // Unblock the first task.
+  }
+
+  EXPECT_GE(tasks_cleaned_up, tasks_executed);
+  EXPECT_EQ(tasks_cleaned_up, kTaskCount);
+}
+
+// Test posting two tasks that have shared state not protected by a
+// lock. The TaskQueue should guarantee memory read-write order and
+// FIFO task execution order, so the second task should always see the
+// changes that were made by the first task.
+//
+// If the TaskQueue doesn't properly synchronize the execution of
+// tasks, there will be a data race, which is undefined behavior. The
+// EXPECT calls may randomly catch this, but to make the most of this
+// unit test, run it under TSan or some other tool that is able to
+// directly detect data races.
+TEST_P(TaskQueueTest, PostTwoWithSharedUnprotectedState) {
+  std::unique_ptr<webrtc::TaskQueueFactory> factory = GetParam()();
+  struct SharedState {
+    // First task will set this value to 1 and second will assert it.
+    int state = 0;
+  } state;
+
+  auto queue = CreateTaskQueue(factory, "PostTwoWithSharedUnprotectedState");
+  rtc::Event done;
+  queue->PostTask(ToQueuedTask([&state, &queue, &done] {
+    // Post tasks from queue to guarantee, that 1st task won't be
+    // executed before the second one will be posted.
+    queue->PostTask(ToQueuedTask([&state] { state.state = 1; }));
+    queue->PostTask(ToQueuedTask([&state, &done] {
+      EXPECT_EQ(state.state, 1);
+      done.Set();
+    }));
+    // Check, that state changing tasks didn't start yet.
+    EXPECT_EQ(state.state, 0);
+  }));
+  EXPECT_TRUE(done.Wait(1000));
+}
+
+}  // namespace
+}  // namespace webrtc
diff --git a/api/task_queue/task_queue_test.h b/api/task_queue/task_queue_test.h
new file mode 100644
index 0000000..e2e4730
--- /dev/null
+++ b/api/task_queue/task_queue_test.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TASK_QUEUE_TASK_QUEUE_TEST_H_
+#define API_TASK_QUEUE_TASK_QUEUE_TEST_H_
+
+#include <functional>
+#include <memory>
+
+#include "api/task_queue/task_queue_factory.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+// Suite of tests to verify TaskQueue implementation with.
+// Example usage:
+//
+// namespace {
+//
+// using ::testing::Values;
+// using ::webrtc::TaskQueueTest;
+//
+// std::unique_ptr<webrtc::TaskQueueFactory> CreateMyFactory();
+//
+// INSTANTIATE_TEST_SUITE_P(My, TaskQueueTest, Values(CreateMyFactory));
+//
+// }  // namespace
+class TaskQueueTest : public ::testing::TestWithParam<
+                          std::function<std::unique_ptr<TaskQueueFactory>()>> {
+};
+
+}  // namespace webrtc
+
+#endif  // API_TASK_QUEUE_TASK_QUEUE_TEST_H_
diff --git a/api/transport/field_trial_based_config.cc b/api/transport/field_trial_based_config.cc
new file mode 100644
index 0000000..7e6764f
--- /dev/null
+++ b/api/transport/field_trial_based_config.cc
@@ -0,0 +1,17 @@
+/*
+ *  Copyright 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 "api/transport/field_trial_based_config.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+std::string FieldTrialBasedConfig::Lookup(absl::string_view key) const {
+  return webrtc::field_trial::FindFullName(std::string(key));
+}
+}  // namespace webrtc
diff --git a/api/transport/field_trial_based_config.h b/api/transport/field_trial_based_config.h
new file mode 100644
index 0000000..e0989db
--- /dev/null
+++ b/api/transport/field_trial_based_config.h
@@ -0,0 +1,25 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_
+#define API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_
+
+#include <string>
+#include "absl/strings/string_view.h"
+#include "api/transport/webrtc_key_value_config.h"
+
+namespace webrtc {
+// Implementation using the field trial API fo the key value lookup.
+class FieldTrialBasedConfig : public WebRtcKeyValueConfig {
+ public:
+  std::string Lookup(absl::string_view key) const override;
+};
+}  // namespace webrtc
+
+#endif  // API_TRANSPORT_FIELD_TRIAL_BASED_CONFIG_H_
diff --git a/api/transport/goog_cc_factory.cc b/api/transport/goog_cc_factory.cc
index 119e2dc..92fd4d1 100644
--- a/api/transport/goog_cc_factory.cc
+++ b/api/transport/goog_cc_factory.cc
@@ -10,8 +10,11 @@
 
 #include "api/transport/goog_cc_factory.h"
 
+#include <stdint.h>
+
 #include "absl/memory/memory.h"
 #include "modules/congestion_controller/goog_cc/goog_cc_network_control.h"
+
 namespace webrtc {
 GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory(
     RtcEventLog* event_log)
diff --git a/api/transport/network_control.h b/api/transport/network_control.h
index 9086260..53ac10e 100644
--- a/api/transport/network_control.h
+++ b/api/transport/network_control.h
@@ -14,6 +14,7 @@
 #include <memory>
 
 #include "api/transport/network_types.h"
+#include "api/transport/webrtc_key_value_config.h"
 
 namespace webrtc {
 
@@ -23,6 +24,9 @@
   // Called to indicate target transfer rate as well as giving information about
   // the current estimate of network parameters.
   virtual void OnTargetTransferRate(TargetTransferRate) = 0;
+  // Called to provide updates to the expected target rate in case it changes
+  // before the first call to OnTargetTransferRate.
+  virtual void OnStartRateUpdate(DataRate) {}
 };
 
 // Configuration sent to factory create function. The parameters here are
@@ -36,6 +40,10 @@
   // Initial stream specific configuration, these are changed at any later time
   // by calls to OnStreamsConfig.
   StreamsConfig stream_based_config;
+
+  // Optional override of configuration of WebRTC internals. Using nullptr here
+  // indicates that the field trial API will be used.
+  const WebRtcKeyValueConfig* key_value_config = nullptr;
 };
 
 // NetworkControllerInterface is implemented by network controllers. A network
diff --git a/api/transport/network_types.cc b/api/transport/network_types.cc
index 80214de..acc9c2b 100644
--- a/api/transport/network_types.cc
+++ b/api/transport/network_types.cc
@@ -81,4 +81,8 @@
          probe_cluster_min_bytes == rhs.probe_cluster_min_bytes;
 }
 
+ProcessInterval::ProcessInterval() = default;
+ProcessInterval::ProcessInterval(const ProcessInterval&) = default;
+ProcessInterval::~ProcessInterval() = default;
+
 }  // namespace webrtc
diff --git a/api/transport/network_types.h b/api/transport/network_types.h
index 0f1d7ab..e26561a 100644
--- a/api/transport/network_types.h
+++ b/api/transport/network_types.h
@@ -31,13 +31,11 @@
   StreamsConfig(const StreamsConfig&);
   ~StreamsConfig();
   Timestamp at_time = Timestamp::PlusInfinity();
-  bool requests_alr_probing = false;
+  absl::optional<bool> requests_alr_probing;
   absl::optional<double> pacing_factor;
   absl::optional<DataRate> min_pacing_rate;
   absl::optional<DataRate> max_padding_rate;
   absl::optional<DataRate> max_total_allocated_bitrate;
-  // The send rate of traffic for which feedback is not received.
-  DataRate unacknowledged_rate_allocation = DataRate::Zero();
 };
 
 struct TargetRateConstraints {
@@ -136,6 +134,7 @@
   ~TransportPacketsFeedback();
 
   Timestamp feedback_time = Timestamp::PlusInfinity();
+  Timestamp first_unacked_send_time = Timestamp::PlusInfinity();
   DataSize data_in_flight = DataSize::Zero();
   DataSize prior_in_flight = DataSize::Zero();
   std::vector<PacketResult> packet_feedbacks;
@@ -177,6 +176,7 @@
   DataRate target_data_rate = DataRate::Zero();
   TimeDelta target_duration = TimeDelta::Zero();
   int32_t target_probe_count = 0;
+  int32_t id = 0;
 };
 
 struct TargetTransferRate {
@@ -201,7 +201,11 @@
 
 // Process control
 struct ProcessInterval {
+  ProcessInterval();
+  ProcessInterval(const ProcessInterval&);
+  ~ProcessInterval();
   Timestamp at_time = Timestamp::PlusInfinity();
+  absl::optional<DataSize> pacer_queue;
 };
 }  // namespace webrtc
 
diff --git a/api/transport/webrtc_key_value_config.h b/api/transport/webrtc_key_value_config.h
new file mode 100644
index 0000000..c6376a9
--- /dev/null
+++ b/api/transport/webrtc_key_value_config.h
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 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.
+ */
+#ifndef API_TRANSPORT_WEBRTC_KEY_VALUE_CONFIG_H_
+#define API_TRANSPORT_WEBRTC_KEY_VALUE_CONFIG_H_
+
+#include <string>
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+
+// An interface that provides a key-value mapping for configuring internal
+// details of WebRTC. Note that there's no guarantess that the meaning of a
+// particular key value mapping will be preserved over time and no announcements
+// will be made if they are changed. It's up to the library user to ensure that
+// the behavior does not break.
+class WebRtcKeyValueConfig {
+ public:
+  virtual ~WebRtcKeyValueConfig() = default;
+  // The configured value for the given key. Defaults to an empty string.
+  virtual std::string Lookup(absl::string_view key) const = 0;
+};
+}  // namespace webrtc
+
+#endif  // API_TRANSPORT_WEBRTC_KEY_VALUE_CONFIG_H_
diff --git a/api/turn_customizer.h b/api/turn_customizer.h
new file mode 100644
index 0000000..f0bf0d9
--- /dev/null
+++ b/api/turn_customizer.h
@@ -0,0 +1,45 @@
+/*
+ *  Copyright 2017 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_TURN_CUSTOMIZER_H_
+#define API_TURN_CUSTOMIZER_H_
+
+#include <stdlib.h>
+
+namespace cricket {
+class PortInterface;
+class StunMessage;
+}  // namespace cricket
+
+namespace webrtc {
+
+class TurnCustomizer {
+ public:
+  // This is called before a TURN message is sent.
+  // This could be used to add implementation specific attributes to a request.
+  virtual void MaybeModifyOutgoingStunMessage(
+      cricket::PortInterface* port,
+      cricket::StunMessage* message) = 0;
+
+  // TURN can send data using channel data messages or Send indication.
+  // This method should return false if |data| should be sent using
+  // a Send indication instead of a ChannelData message, even if a
+  // channel is bound.
+  virtual bool AllowChannelData(cricket::PortInterface* port,
+                                const void* data,
+                                size_t size,
+                                bool payload) = 0;
+
+  virtual ~TurnCustomizer() {}
+};
+
+}  // namespace webrtc
+
+#endif  // API_TURN_CUSTOMIZER_H_
diff --git a/api/uma_metrics.h b/api/uma_metrics.h
new file mode 100644
index 0000000..51b0ff0
--- /dev/null
+++ b/api/uma_metrics.h
@@ -0,0 +1,168 @@
+/*
+ *  Copyright 2014 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.
+ */
+
+// This file contains enums related to IPv4/IPv6 metrics.
+
+#ifndef API_UMA_METRICS_H_
+#define API_UMA_METRICS_H_
+
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// Currently this contains information related to WebRTC network/transport
+// information.
+
+// The difference between PeerConnectionEnumCounter and
+// PeerConnectionMetricsName is that the "EnumCounter" is only counting the
+// occurrences of events, while "Name" has a value associated with it which is
+// used to form a histogram.
+
+// This enum is backed by Chromium's histograms.xml,
+// chromium/src/tools/metrics/histograms/histograms.xml
+// Existing values cannot be re-ordered and new enums must be added
+// before kBoundary.
+enum PeerConnectionAddressFamilyCounter {
+  kPeerConnection_IPv4,
+  kPeerConnection_IPv6,
+  kBestConnections_IPv4,
+  kBestConnections_IPv6,
+  kPeerConnectionAddressFamilyCounter_Max,
+};
+
+// TODO(guoweis): Keep previous name here until all references are renamed.
+#define kBoundary kPeerConnectionAddressFamilyCounter_Max
+
+// TODO(guoweis): Keep previous name here until all references are renamed.
+typedef PeerConnectionAddressFamilyCounter PeerConnectionUMAMetricsCounter;
+
+// This enum defines types for UMA samples, which will have a range.
+enum PeerConnectionMetricsName {
+  kNetworkInterfaces_IPv4,  // Number of IPv4 interfaces.
+  kNetworkInterfaces_IPv6,  // Number of IPv6 interfaces.
+  kTimeToConnect,           // In milliseconds.
+  kLocalCandidates_IPv4,    // Number of IPv4 local candidates.
+  kLocalCandidates_IPv6,    // Number of IPv6 local candidates.
+  kPeerConnectionMetricsName_Max
+};
+
+// TODO(guoweis): Keep previous name here until all references are renamed.
+typedef PeerConnectionMetricsName PeerConnectionUMAMetricsName;
+
+// The IceCandidatePairType has the format of
+// <local_candidate_type>_<remote_candidate_type>. It is recorded based on the
+// type of candidate pair used when the PeerConnection first goes to a completed
+// state. When BUNDLE is enabled, only the first transport gets recorded.
+enum IceCandidatePairType {
+  // HostHost is deprecated. It was replaced with the set of types at the bottom
+  // to report private or public host IP address.
+  kIceCandidatePairHostHost,
+  kIceCandidatePairHostSrflx,
+  kIceCandidatePairHostRelay,
+  kIceCandidatePairHostPrflx,
+  kIceCandidatePairSrflxHost,
+  kIceCandidatePairSrflxSrflx,
+  kIceCandidatePairSrflxRelay,
+  kIceCandidatePairSrflxPrflx,
+  kIceCandidatePairRelayHost,
+  kIceCandidatePairRelaySrflx,
+  kIceCandidatePairRelayRelay,
+  kIceCandidatePairRelayPrflx,
+  kIceCandidatePairPrflxHost,
+  kIceCandidatePairPrflxSrflx,
+  kIceCandidatePairPrflxRelay,
+
+  // The following 9 types tell whether local and remote hosts have hostname,
+  // private or public IP addresses.
+  kIceCandidatePairHostPrivateHostPrivate,
+  kIceCandidatePairHostPrivateHostPublic,
+  kIceCandidatePairHostPublicHostPrivate,
+  kIceCandidatePairHostPublicHostPublic,
+  kIceCandidatePairHostNameHostName,
+  kIceCandidatePairHostNameHostPrivate,
+  kIceCandidatePairHostNameHostPublic,
+  kIceCandidatePairHostPrivateHostName,
+  kIceCandidatePairHostPublicHostName,
+  kIceCandidatePairMax
+};
+
+enum KeyExchangeProtocolType {
+  kEnumCounterKeyProtocolDtls,
+  kEnumCounterKeyProtocolSdes,
+  kEnumCounterKeyProtocolMax
+};
+
+enum KeyExchangeProtocolMedia {
+  kEnumCounterKeyProtocolMediaTypeDtlsAudio,
+  kEnumCounterKeyProtocolMediaTypeDtlsVideo,
+  kEnumCounterKeyProtocolMediaTypeDtlsData,
+  kEnumCounterKeyProtocolMediaTypeSdesAudio,
+  kEnumCounterKeyProtocolMediaTypeSdesVideo,
+  kEnumCounterKeyProtocolMediaTypeSdesData,
+  kEnumCounterKeyProtocolMediaTypeMax
+};
+
+enum SdpSemanticRequested {
+  kSdpSemanticRequestDefault,
+  kSdpSemanticRequestPlanB,
+  kSdpSemanticRequestUnifiedPlan,
+  kSdpSemanticRequestMax
+};
+
+enum SdpSemanticNegotiated {
+  kSdpSemanticNegotiatedNone,
+  kSdpSemanticNegotiatedPlanB,
+  kSdpSemanticNegotiatedUnifiedPlan,
+  kSdpSemanticNegotiatedMixed,
+  kSdpSemanticNegotiatedMax
+};
+
+// Metric which records the format of the received SDP for tracking how much the
+// difference between Plan B and Unified Plan affect users.
+enum SdpFormatReceived {
+  // No audio or video tracks. This is worth special casing since it seems to be
+  // the most common scenario (data-channel only).
+  kSdpFormatReceivedNoTracks,
+  // No more than one audio and one video track. Should be compatible with both
+  // Plan B and Unified Plan endpoints.
+  kSdpFormatReceivedSimple,
+  // More than one audio track or more than one video track in the Plan B format
+  // (e.g., one audio media section with multiple streams).
+  kSdpFormatReceivedComplexPlanB,
+  // More than one audio track or more than one video track in the Unified Plan
+  // format (e.g., two audio media sections).
+  kSdpFormatReceivedComplexUnifiedPlan,
+  kSdpFormatReceivedMax
+};
+
+// Metric for counting the outcome of adding an ICE candidate
+enum AddIceCandidateResult {
+  kAddIceCandidateSuccess,
+  kAddIceCandidateFailClosed,
+  kAddIceCandidateFailNoRemoteDescription,
+  kAddIceCandidateFailNullCandidate,
+  kAddIceCandidateFailNotValid,
+  kAddIceCandidateFailNotReady,
+  kAddIceCandidateFailInAddition,
+  kAddIceCandidateFailNotUsable,
+  kAddIceCandidateMax
+};
+
+// Metric for recording which api surface was used to enable simulcast.
+enum SimulcastApiVersion {
+  kSimulcastApiVersionNone,
+  kSimulcastApiVersionLegacy,
+  kSimulcastApiVersionSpecCompliant,
+  kSimulcastApiVersionMax,
+};
+
+}  // namespace webrtc
+
+#endif  // API_UMA_METRICS_H_
diff --git a/api/units/data_rate.cc b/api/units/data_rate.cc
index d72d958..f9586c5 100644
--- a/api/units/data_rate.cc
+++ b/api/units/data_rate.cc
@@ -10,6 +10,7 @@
 
 #include "api/units/data_rate.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
@@ -17,8 +18,10 @@
 std::string ToString(DataRate value) {
   char buf[64];
   rtc::SimpleStringBuilder sb(buf);
-  if (value.IsInfinite()) {
-    sb << "inf bps";
+  if (value.IsPlusInfinity()) {
+    sb << "+inf bps";
+  } else if (value.IsMinusInfinity()) {
+    sb << "-inf bps";
   } else {
     if (value.bps() == 0 || value.bps() % 1000 != 0) {
       sb << value.bps() << " bps";
diff --git a/api/units/data_rate.h b/api/units/data_rate.h
index 7119284..9b09aa9 100644
--- a/api/units/data_rate.h
+++ b/api/units/data_rate.h
@@ -52,10 +52,17 @@
   }
   template <typename T>
   static constexpr DataRate bps(T bits_per_second) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(bits_per_second);
   }
   template <typename T>
+  static constexpr DataRate bytes_per_sec(T bytes_per_second) {
+    static_assert(std::is_arithmetic<T>::value, "");
+    return FromFraction<8>(bytes_per_second);
+  }
+  template <typename T>
   static constexpr DataRate kbps(T kilobits_per_sec) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000>(kilobits_per_sec);
   }
   template <typename T = int64_t>
@@ -63,6 +70,10 @@
     return ToValue<T>();
   }
   template <typename T = int64_t>
+  constexpr T bytes_per_sec() const {
+    return ToFraction<8, T>();
+  }
+  template <typename T = int64_t>
   T kbps() const {
     return ToFraction<1000, T>();
   }
diff --git a/api/units/data_size.cc b/api/units/data_size.cc
index 8a87786..45487df 100644
--- a/api/units/data_size.cc
+++ b/api/units/data_size.cc
@@ -10,6 +10,7 @@
 
 #include "api/units/data_size.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
@@ -17,8 +18,10 @@
 std::string ToString(DataSize value) {
   char buf[64];
   rtc::SimpleStringBuilder sb(buf);
-  if (value.IsInfinite()) {
-    sb << "inf bytes";
+  if (value.IsPlusInfinity()) {
+    sb << "+inf bytes";
+  } else if (value.IsMinusInfinity()) {
+    sb << "-inf bytes";
   } else {
     sb << value.bytes() << " bytes";
   }
diff --git a/api/units/data_size.h b/api/units/data_size.h
index b4cbb65..90ef00d 100644
--- a/api/units/data_size.h
+++ b/api/units/data_size.h
@@ -31,14 +31,13 @@
     return FromStaticValue<bytes>();
   }
 
-  template <
-      typename T,
-      typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
+  template <typename T>
   static DataSize bytes(T bytes) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(bytes);
   }
   template <typename T = int64_t>
-  typename std::enable_if<std::is_arithmetic<T>::value, T>::type bytes() const {
+  T bytes() const {
     return ToValue<T>();
   }
 
diff --git a/api/units/time_delta.cc b/api/units/time_delta.cc
index f90451b..9fe1308 100644
--- a/api/units/time_delta.cc
+++ b/api/units/time_delta.cc
@@ -10,6 +10,7 @@
 
 #include "api/units/time_delta.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
diff --git a/api/units/time_delta.h b/api/units/time_delta.h
index 6458369..e5172f4 100644
--- a/api/units/time_delta.h
+++ b/api/units/time_delta.h
@@ -46,14 +46,17 @@
   }
   template <typename T>
   static TimeDelta seconds(T seconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000000>(seconds);
   }
   template <typename T>
   static TimeDelta ms(T milliseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000>(milliseconds);
   }
   template <typename T>
   static TimeDelta us(T microseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(microseconds);
   }
   template <typename T = int64_t>
diff --git a/api/units/timestamp.cc b/api/units/timestamp.cc
index d3417cf..0b9cdd9 100644
--- a/api/units/timestamp.cc
+++ b/api/units/timestamp.cc
@@ -10,14 +10,17 @@
 
 #include "api/units/timestamp.h"
 
+#include "api/array_view.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
 std::string ToString(Timestamp value) {
   char buf[64];
   rtc::SimpleStringBuilder sb(buf);
-  if (value.IsInfinite()) {
-    sb << "inf ms";
+  if (value.IsPlusInfinity()) {
+    sb << "+inf ms";
+  } else if (value.IsMinusInfinity()) {
+    sb << "-inf ms";
   } else {
     if (value.ms() % 1000 == 0)
       sb << value.seconds() << " s";
diff --git a/api/units/timestamp.h b/api/units/timestamp.h
index a6e450f..370a091 100644
--- a/api/units/timestamp.h
+++ b/api/units/timestamp.h
@@ -45,14 +45,17 @@
 
   template <typename T>
   static Timestamp seconds(T seconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000000>(seconds);
   }
   template <typename T>
   static Timestamp ms(T milliseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromFraction<1000>(milliseconds);
   }
   template <typename T>
   static Timestamp us(T microseconds) {
+    static_assert(std::is_arithmetic<T>::value, "");
     return FromValue(microseconds);
   }
   template <typename T = int64_t>
diff --git a/api/video/builtin_video_bitrate_allocator_factory.cc b/api/video/builtin_video_bitrate_allocator_factory.cc
index 70f6ad0..b01e5c2 100644
--- a/api/video/builtin_video_bitrate_allocator_factory.cc
+++ b/api/video/builtin_video_bitrate_allocator_factory.cc
@@ -11,7 +11,9 @@
 #include "api/video/builtin_video_bitrate_allocator_factory.h"
 
 #include "absl/memory/memory.h"
-#include "media/base/codec.h"
+#include "api/video/video_bitrate_allocator.h"
+#include "api/video_codecs/video_codec.h"
+#include "common_types.h"  // NOLINT(build/include)
 #include "modules/video_coding/codecs/vp9/svc_rate_allocator.h"
 #include "modules/video_coding/utility/default_video_bitrate_allocator.h"
 #include "modules/video_coding/utility/simulcast_rate_allocator.h"
diff --git a/api/video/color_space.cc b/api/video/color_space.cc
index ad138ab..710bb43 100644
--- a/api/video/color_space.cc
+++ b/api/video/color_space.cc
@@ -10,6 +10,7 @@
 
 #include "api/video/color_space.h"
 
+namespace webrtc {
 namespace {
 // Try to convert |enum_value| into the enum class T. |enum_bitmask| is created
 // by the funciton below. Returns true if conversion was successful, false
@@ -50,9 +51,17 @@
   return MakeMask(0, N, values);
 }
 
-}  // namespace
+bool SetChromaSitingFromUint8(uint8_t enum_value,
+                              ColorSpace::ChromaSiting* chroma_siting) {
+  constexpr ColorSpace::ChromaSiting kChromaSitings[] = {
+      ColorSpace::ChromaSiting::kUnspecified,
+      ColorSpace::ChromaSiting::kCollocated, ColorSpace::ChromaSiting::kHalf};
+  constexpr uint64_t enum_bitmask = CreateEnumBitmask(kChromaSitings);
 
-namespace webrtc {
+  return SetFromUint8(enum_value, enum_bitmask, chroma_siting);
+}
+
+}  // namespace
 
 ColorSpace::ColorSpace() = default;
 ColorSpace::ColorSpace(const ColorSpace& other) = default;
@@ -63,17 +72,27 @@
                        TransferID transfer,
                        MatrixID matrix,
                        RangeID range)
-    : ColorSpace(primaries, transfer, matrix, range, nullptr) {}
+    : ColorSpace(primaries,
+                 transfer,
+                 matrix,
+                 range,
+                 ChromaSiting::kUnspecified,
+                 ChromaSiting::kUnspecified,
+                 nullptr) {}
 
 ColorSpace::ColorSpace(PrimaryID primaries,
                        TransferID transfer,
                        MatrixID matrix,
                        RangeID range,
+                       ChromaSiting chroma_siting_horz,
+                       ChromaSiting chroma_siting_vert,
                        const HdrMetadata* hdr_metadata)
     : primaries_(primaries),
       transfer_(transfer),
       matrix_(matrix),
       range_(range),
+      chroma_siting_horizontal_(chroma_siting_horz),
+      chroma_siting_vertical_(chroma_siting_vert),
       hdr_metadata_(hdr_metadata ? absl::make_optional(*hdr_metadata)
                                  : absl::nullopt) {}
 
@@ -93,17 +112,24 @@
   return range_;
 }
 
+ColorSpace::ChromaSiting ColorSpace::chroma_siting_horizontal() const {
+  return chroma_siting_horizontal_;
+}
+
+ColorSpace::ChromaSiting ColorSpace::chroma_siting_vertical() const {
+  return chroma_siting_vertical_;
+}
+
 const HdrMetadata* ColorSpace::hdr_metadata() const {
   return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
 }
 
 bool ColorSpace::set_primaries_from_uint8(uint8_t enum_value) {
   constexpr PrimaryID kPrimaryIds[] = {
-      PrimaryID::kInvalid,    PrimaryID::kBT709,      PrimaryID::kUNSPECIFIED,
-      PrimaryID::kBT470M,     PrimaryID::kBT470BG,    PrimaryID::kSMPTE170M,
-      PrimaryID::kSMPTE240M,  PrimaryID::kFILM,       PrimaryID::kBT2020,
-      PrimaryID::kSMPTEST428, PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432,
-      PrimaryID::kJEDECP22};
+      PrimaryID::kBT709,      PrimaryID::kUnspecified, PrimaryID::kBT470M,
+      PrimaryID::kBT470BG,    PrimaryID::kSMPTE170M,   PrimaryID::kSMPTE240M,
+      PrimaryID::kFILM,       PrimaryID::kBT2020,      PrimaryID::kSMPTEST428,
+      PrimaryID::kSMPTEST431, PrimaryID::kSMPTEST432,  PrimaryID::kJEDECP22};
   constexpr uint64_t enum_bitmask = CreateEnumBitmask(kPrimaryIds);
 
   return SetFromUint8(enum_value, enum_bitmask, &primaries_);
@@ -111,15 +137,15 @@
 
 bool ColorSpace::set_transfer_from_uint8(uint8_t enum_value) {
   constexpr TransferID kTransferIds[] = {
-      TransferID::kInvalid,      TransferID::kBT709,
-      TransferID::kUNSPECIFIED,  TransferID::kGAMMA22,
-      TransferID::kGAMMA28,      TransferID::kSMPTE170M,
-      TransferID::kSMPTE240M,    TransferID::kLINEAR,
-      TransferID::kLOG,          TransferID::kLOG_SQRT,
-      TransferID::kIEC61966_2_4, TransferID::kBT1361_ECG,
-      TransferID::kIEC61966_2_1, TransferID::kBT2020_10,
-      TransferID::kBT2020_12,    TransferID::kSMPTEST2084,
-      TransferID::kSMPTEST428,   TransferID::kARIB_STD_B67};
+      TransferID::kBT709,       TransferID::kUnspecified,
+      TransferID::kGAMMA22,     TransferID::kGAMMA28,
+      TransferID::kSMPTE170M,   TransferID::kSMPTE240M,
+      TransferID::kLINEAR,      TransferID::kLOG,
+      TransferID::kLOG_SQRT,    TransferID::kIEC61966_2_4,
+      TransferID::kBT1361_ECG,  TransferID::kIEC61966_2_1,
+      TransferID::kBT2020_10,   TransferID::kBT2020_12,
+      TransferID::kSMPTEST2084, TransferID::kSMPTEST428,
+      TransferID::kARIB_STD_B67};
   constexpr uint64_t enum_bitmask = CreateEnumBitmask(kTransferIds);
 
   return SetFromUint8(enum_value, enum_bitmask, &transfer_);
@@ -127,11 +153,11 @@
 
 bool ColorSpace::set_matrix_from_uint8(uint8_t enum_value) {
   constexpr MatrixID kMatrixIds[] = {
-      MatrixID::kRGB,       MatrixID::kBT709,        MatrixID::kUNSPECIFIED,
-      MatrixID::kFCC,       MatrixID::kBT470BG,      MatrixID::kSMPTE170M,
-      MatrixID::kSMPTE240M, MatrixID::kYCOCG,        MatrixID::kBT2020_NCL,
-      MatrixID::kBT2020_CL, MatrixID::kSMPTE2085,    MatrixID::kCDNCLS,
-      MatrixID::kCDCLS,     MatrixID::kBT2100_ICTCP, MatrixID::kInvalid};
+      MatrixID::kRGB,       MatrixID::kBT709,       MatrixID::kUnspecified,
+      MatrixID::kFCC,       MatrixID::kBT470BG,     MatrixID::kSMPTE170M,
+      MatrixID::kSMPTE240M, MatrixID::kYCOCG,       MatrixID::kBT2020_NCL,
+      MatrixID::kBT2020_CL, MatrixID::kSMPTE2085,   MatrixID::kCDNCLS,
+      MatrixID::kCDCLS,     MatrixID::kBT2100_ICTCP};
   constexpr uint64_t enum_bitmask = CreateEnumBitmask(kMatrixIds);
 
   return SetFromUint8(enum_value, enum_bitmask, &matrix_);
@@ -145,6 +171,14 @@
   return SetFromUint8(enum_value, enum_bitmask, &range_);
 }
 
+bool ColorSpace::set_chroma_siting_horizontal_from_uint8(uint8_t enum_value) {
+  return SetChromaSitingFromUint8(enum_value, &chroma_siting_horizontal_);
+}
+
+bool ColorSpace::set_chroma_siting_vertical_from_uint8(uint8_t enum_value) {
+  return SetChromaSitingFromUint8(enum_value, &chroma_siting_vertical_);
+}
+
 void ColorSpace::set_hdr_metadata(const HdrMetadata* hdr_metadata) {
   hdr_metadata_ =
       hdr_metadata ? absl::make_optional(*hdr_metadata) : absl::nullopt;
diff --git a/api/video/color_space.h b/api/video/color_space.h
index 79a15f5..91b4e17 100644
--- a/api/video/color_space.h
+++ b/api/video/color_space.h
@@ -35,9 +35,8 @@
  public:
   enum class PrimaryID : uint8_t {
     // The indices are equal to the values specified in T-REC H.273 Table 2.
-    kInvalid = 0,
     kBT709 = 1,
-    kUNSPECIFIED = 2,
+    kUnspecified = 2,
     kBT470M = 4,
     kBT470BG = 5,
     kSMPTE170M = 6,  // Identical to BT601
@@ -54,9 +53,8 @@
 
   enum class TransferID : uint8_t {
     // The indices are equal to the values specified in T-REC H.273 Table 3.
-    kInvalid = 0,
     kBT709 = 1,
-    kUNSPECIFIED = 2,
+    kUnspecified = 2,
     kGAMMA22 = 4,
     kGAMMA28 = 5,
     kSMPTE170M = 6,
@@ -80,7 +78,7 @@
     // The indices are equal to the values specified in T-REC H.273 Table 4.
     kRGB = 0,
     kBT709 = 1,
-    kUNSPECIFIED = 2,
+    kUnspecified = 2,
     kFCC = 4,
     kBT470BG = 5,
     kSMPTE170M = 6,
@@ -92,7 +90,6 @@
     kCDNCLS = 12,
     kCDCLS = 13,
     kBT2100_ICTCP = 14,
-    kInvalid = 63,
     // When adding/removing entries here, please make sure to do the
     // corresponding change to kMatrixIds.
   };
@@ -111,6 +108,19 @@
     // corresponding change to kRangeIds.
   };
 
+  enum class ChromaSiting {
+    // Chroma siting specifies how chroma is subsampled relative to the luma
+    // samples in a YUV video frame.
+    // The indices are equal to the values specified at
+    // https://www.webmproject.org/docs/container/#colour for the element
+    // ChromaSitingVert and ChromaSitingHorz.
+    kUnspecified = 0,
+    kCollocated = 1,
+    kHalf = 2,
+    // When adding/removing entries here, please make sure to do the
+    // corresponding change to kChromaSitings.
+  };
+
   ColorSpace();
   ColorSpace(const ColorSpace& other);
   ColorSpace(ColorSpace&& other);
@@ -118,40 +128,50 @@
   ColorSpace(PrimaryID primaries,
              TransferID transfer,
              MatrixID matrix,
-             RangeID full_range);
+             RangeID range);
   ColorSpace(PrimaryID primaries,
              TransferID transfer,
              MatrixID matrix,
              RangeID range,
+             ChromaSiting chroma_siting_horizontal,
+             ChromaSiting chroma_siting_vertical,
              const HdrMetadata* hdr_metadata);
-  bool operator==(const ColorSpace& other) const {
-    return primaries_ == other.primaries() && transfer_ == other.transfer() &&
-           matrix_ == other.matrix() && range_ == other.range() &&
-           ((hdr_metadata_.has_value() && other.hdr_metadata() &&
-             *hdr_metadata_ == *other.hdr_metadata()) ||
-            (!hdr_metadata_.has_value() && other.hdr_metadata() == nullptr));
+  friend bool operator==(const ColorSpace& lhs, const ColorSpace& rhs) {
+    return lhs.primaries_ == rhs.primaries_ && lhs.transfer_ == rhs.transfer_ &&
+           lhs.matrix_ == rhs.matrix_ && lhs.range_ == rhs.range_ &&
+           lhs.chroma_siting_horizontal_ == rhs.chroma_siting_horizontal_ &&
+           lhs.chroma_siting_vertical_ == rhs.chroma_siting_vertical_ &&
+           lhs.hdr_metadata_ == rhs.hdr_metadata_;
+  }
+  friend bool operator!=(const ColorSpace& lhs, const ColorSpace& rhs) {
+    return !(lhs == rhs);
   }
 
   PrimaryID primaries() const;
   TransferID transfer() const;
   MatrixID matrix() const;
   RangeID range() const;
+  ChromaSiting chroma_siting_horizontal() const;
+  ChromaSiting chroma_siting_vertical() const;
   const HdrMetadata* hdr_metadata() const;
 
   bool set_primaries_from_uint8(uint8_t enum_value);
   bool set_transfer_from_uint8(uint8_t enum_value);
   bool set_matrix_from_uint8(uint8_t enum_value);
   bool set_range_from_uint8(uint8_t enum_value);
+  bool set_chroma_siting_horizontal_from_uint8(uint8_t enum_value);
+  bool set_chroma_siting_vertical_from_uint8(uint8_t enum_value);
   void set_hdr_metadata(const HdrMetadata* hdr_metadata);
 
  private:
-  PrimaryID primaries_ = PrimaryID::kInvalid;
-  TransferID transfer_ = TransferID::kInvalid;
-  MatrixID matrix_ = MatrixID::kInvalid;
+  PrimaryID primaries_ = PrimaryID::kUnspecified;
+  TransferID transfer_ = TransferID::kUnspecified;
+  MatrixID matrix_ = MatrixID::kUnspecified;
   RangeID range_ = RangeID::kInvalid;
+  ChromaSiting chroma_siting_horizontal_ = ChromaSiting::kUnspecified;
+  ChromaSiting chroma_siting_vertical_ = ChromaSiting::kUnspecified;
   absl::optional<HdrMetadata> hdr_metadata_;
 };
 
 }  // namespace webrtc
-
 #endif  // API_VIDEO_COLOR_SPACE_H_
diff --git a/api/video/encoded_frame.h b/api/video/encoded_frame.h
index b8462c6..fa06568 100644
--- a/api/video/encoded_frame.h
+++ b/api/video/encoded_frame.h
@@ -13,6 +13,9 @@
 
 #include "modules/video_coding/encoded_frame.h"
 
+#include <stddef.h>
+#include <stdint.h>
+
 namespace webrtc {
 namespace video_coding {
 
@@ -56,8 +59,6 @@
   EncodedFrame() = default;
   virtual ~EncodedFrame() {}
 
-  virtual bool GetBitstream(uint8_t* destination) const = 0;
-
   // When this frame was received.
   virtual int64_t ReceivedTime() const = 0;
 
@@ -69,8 +70,6 @@
   //                 been implemented.
   virtual bool delayed_by_retransmission() const;
 
-  size_t size() const { return _length; }
-
   bool is_keyframe() const { return num_references == 0; }
 
   VideoLayerFrameId id;
@@ -80,6 +79,9 @@
   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;
 };
 
 }  // namespace video_coding
diff --git a/api/video/encoded_image.cc b/api/video/encoded_image.cc
index e7c6fad..d1fa046 100644
--- a/api/video/encoded_image.cc
+++ b/api/video/encoded_image.cc
@@ -29,10 +29,23 @@
 
 EncodedImage::EncodedImage() : EncodedImage(nullptr, 0, 0) {}
 
+EncodedImage::EncodedImage(EncodedImage&&) = default;
 EncodedImage::EncodedImage(const EncodedImage&) = default;
 
-EncodedImage::EncodedImage(uint8_t* buffer, size_t length, size_t size)
-    : _buffer(buffer), _length(length), _size(size) {}
+EncodedImage::EncodedImage(uint8_t* buffer, size_t size, size_t capacity)
+    : size_(size), buffer_(buffer), capacity_(capacity) {}
+
+EncodedImage::~EncodedImage() = default;
+
+EncodedImage& EncodedImage::operator=(EncodedImage&&) = default;
+EncodedImage& EncodedImage::operator=(const EncodedImage&) = default;
+
+void EncodedImage::Retain() {
+  if (buffer_) {
+    encoded_data_.SetData(buffer_, size_);
+    buffer_ = nullptr;
+  }
+}
 
 void EncodedImage::SetEncodeTime(int64_t encode_start_ms,
                                  int64_t encode_finish_ms) {
diff --git a/api/video/encoded_image.h b/api/video/encoded_image.h
index a7c719c..1d3bd46 100644
--- a/api/video/encoded_image.h
+++ b/api/video/encoded_image.h
@@ -15,13 +15,14 @@
 
 #include "absl/types/optional.h"
 #include "api/video/color_space.h"
-#include "api/video/video_bitrate_allocation.h"
+#include "api/video/video_codec_constants.h"
 #include "api/video/video_codec_type.h"
 #include "api/video/video_content_type.h"
 #include "api/video/video_rotation.h"
 #include "api/video/video_timing.h"
 #include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
@@ -37,8 +38,16 @@
   static size_t GetBufferPaddingBytes(VideoCodecType codec_type);
 
   EncodedImage();
+  EncodedImage(EncodedImage&&);
+  // Discouraged: potentially expensive.
   EncodedImage(const EncodedImage&);
-  EncodedImage(uint8_t* buffer, size_t length, size_t size);
+  EncodedImage(uint8_t* buffer, size_t length, size_t capacity);
+
+  ~EncodedImage();
+
+  EncodedImage& operator=(EncodedImage&&);
+  // Discouraged: potentially expensive.
+  EncodedImage& operator=(const EncodedImage&);
 
   // TODO(nisse): Change style to timestamp(), set_timestamp(), for consistency
   // with the VideoFrame class.
@@ -62,20 +71,51 @@
   const webrtc::ColorSpace* ColorSpace() const {
     return color_space_ ? &*color_space_ : nullptr;
   }
-  void SetColorSpace(const webrtc::ColorSpace* color_space) {
-    color_space_ =
-        color_space ? absl::make_optional(*color_space) : absl::nullopt;
+  void SetColorSpace(const absl::optional<webrtc::ColorSpace>& color_space) {
+    color_space_ = color_space;
   }
 
+  size_t size() const { return size_; }
+  void set_size(size_t new_size) {
+    RTC_DCHECK_LE(new_size, capacity());
+    size_ = new_size;
+  }
+  size_t capacity() const { return buffer_ ? capacity_ : encoded_data_.size(); }
+
+  void set_buffer(uint8_t* buffer, size_t capacity) {
+    buffer_ = buffer;
+    capacity_ = capacity;
+  }
+
+  void Allocate(size_t capacity) {
+    encoded_data_.SetSize(capacity);
+    buffer_ = nullptr;
+  }
+
+  uint8_t* data() { return buffer_ ? buffer_ : encoded_data_.data(); }
+  const uint8_t* data() const {
+    return buffer_ ? buffer_ : encoded_data_.cdata();
+  }
+  // TODO(nisse): At some places, code accepts a const ref EncodedImage, but
+  // still writes to it, to clear padding at the end of the encoded data.
+  // Padding is required by ffmpeg; the best way to deal with that is likely to
+  // make this class ensure that buffers always have a few zero padding bytes.
+  uint8_t* mutable_data() const { return const_cast<uint8_t*>(data()); }
+
+  // TODO(bugs.webrtc.org/9378): Delete. Used by code that wants to modify a
+  // buffer corresponding to a const EncodedImage. Requires an un-owned buffer.
+  uint8_t* buffer() const { return buffer_; }
+
+  // Hack to workaround lack of ownership of the encoded data. If we don't
+  // already own the underlying data, make an owned copy.
+  void Retain();
+
   uint32_t _encodedWidth = 0;
   uint32_t _encodedHeight = 0;
   // NTP time of the capture time in local timebase in milliseconds.
   int64_t ntp_time_ms_ = 0;
   int64_t capture_time_ms_ = 0;
   FrameType _frameType = kVideoFrameDelta;
-  uint8_t* _buffer;
-  size_t _length;
-  size_t _size;
   VideoRotation rotation_ = kVideoRotation_0;
   VideoContentType content_type_ = VideoContentType::UNSPECIFIED;
   bool _completeFrame = false;
@@ -99,6 +139,14 @@
   } timing_;
 
  private:
+  // TODO(bugs.webrtc.org/9378): We're transitioning to always owning the
+  // encoded data.
+  rtc::CopyOnWriteBuffer encoded_data_;
+  size_t size_;      // Size of encoded frame data.
+  // Non-null when used with an un-owned buffer.
+  uint8_t* buffer_;
+  // Allocated size of _buffer; relevant only if it's non-null.
+  size_t capacity_;
   uint32_t timestamp_rtp_ = 0;
   absl::optional<int> spatial_index_;
   absl::optional<webrtc::ColorSpace> color_space_;
diff --git a/api/video/hdr_metadata.h b/api/video/hdr_metadata.h
index 676a900..e9001a2 100644
--- a/api/video/hdr_metadata.h
+++ b/api/video/hdr_metadata.h
@@ -11,27 +11,47 @@
 #ifndef API_VIDEO_HDR_METADATA_H_
 #define API_VIDEO_HDR_METADATA_H_
 
-#include <stdint.h>
-
 namespace webrtc {
 
 // SMPTE ST 2086 mastering metadata,
 // see https://ieeexplore.ieee.org/document/8353899.
 struct HdrMasteringMetadata {
   struct Chromaticity {
-    // xy chromaticity coordinates must be calculated as specified in ISO
-    // 11664-3:2012 Section 7, and must be specified with four decimal places.
-    // The x coordinate must be in the range [0.0001, 0.7400] and the y
-    // coordinate must be in the range [0.0001, 0.8400].
-    float x = 0.0f;
-    float y = 0.0f;
+    Chromaticity();
+
     bool operator==(const Chromaticity& rhs) const {
       return x == rhs.x && y == rhs.y;
     }
 
-    Chromaticity();
+    bool Validate() const {
+      return x >= 0.0 && x <= 1.0 && y >= 0.0 && y <= 1.0;
+    }
+
+    // xy chromaticity coordinates must be calculated as specified in ISO
+    // 11664-3:2012 Section 7, and must be specified with four decimal places.
+    // The x coordinate should be in the range [0.0001, 0.7400] and the y
+    // coordinate should be in the range [0.0001, 0.8400]. Valid range [0.0000,
+    // 1.0000].
+    float x = 0.0f;
+    float y = 0.0f;
   };
 
+  HdrMasteringMetadata();
+
+  bool operator==(const HdrMasteringMetadata& rhs) const {
+    return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) &&
+            (primary_b == rhs.primary_b) && (white_point == rhs.white_point) &&
+            (luminance_max == rhs.luminance_max) &&
+            (luminance_min == rhs.luminance_min));
+  }
+
+  bool Validate() const {
+    return luminance_max >= 0.0 && luminance_max <= 20000.0 &&
+           luminance_min >= 0.0 && luminance_min <= 5.0 &&
+           primary_r.Validate() && primary_g.Validate() &&
+           primary_b.Validate() && white_point.Validate();
+  }
+
   // The nominal primaries of the mastering display.
   Chromaticity primary_r;
   Chromaticity primary_g;
@@ -41,37 +61,20 @@
   Chromaticity white_point;
 
   // The nominal maximum display luminance of the mastering display. Specified
-  // in the unit candela/m2. The value must be in the range [5, 10000] with zero
-  // decimal places.
+  // in the unit candela/m2. The value should be in the range [5, 10000] with
+  // zero decimal places. Valid range [0, 20000].
   float luminance_max = 0.0f;
 
   // The nominal minimum display luminance of the mastering display. Specified
-  // in the unit candela/m2. The value must be in the range [0.0001, 5.0000]
-  // with four decimal places.
+  // in the unit candela/m2. The value should be in the range [0.0001, 5.0000]
+  // with four decimal places. Valid range [0.0000, 5.0000].
   float luminance_min = 0.0f;
-
-  HdrMasteringMetadata();
-
-  bool operator==(const HdrMasteringMetadata& rhs) const {
-    return ((primary_r == rhs.primary_r) && (primary_g == rhs.primary_g) &&
-            (primary_b == rhs.primary_b) && (white_point == rhs.white_point) &&
-            (luminance_max == rhs.luminance_max) &&
-            (luminance_min == rhs.luminance_min));
-  }
 };
 
 // High dynamic range (HDR) metadata common for HDR10 and WebM/VP9-based HDR
 // formats. This struct replicates the HDRMetadata struct defined in
 // https://cs.chromium.org/chromium/src/media/base/hdr_metadata.h
 struct HdrMetadata {
-  HdrMasteringMetadata mastering_metadata;
-  // Max content light level (CLL), i.e. maximum brightness level present in the
-  // stream, in nits. 1 nit = 1 candela/m2.
-  uint32_t max_content_light_level = 0;
-  // Max frame-average light level (FALL), i.e. maximum average brightness of
-  // the brightest frame in the stream, in nits.
-  uint32_t max_frame_average_light_level = 0;
-
   HdrMetadata();
 
   bool operator==(const HdrMetadata& rhs) const {
@@ -80,6 +83,21 @@
         (max_frame_average_light_level == rhs.max_frame_average_light_level) &&
         (mastering_metadata == rhs.mastering_metadata));
   }
+
+  bool Validate() const {
+    return max_content_light_level >= 0 && max_content_light_level <= 20000 &&
+           max_frame_average_light_level >= 0 &&
+           max_frame_average_light_level <= 20000 &&
+           mastering_metadata.Validate();
+  }
+
+  HdrMasteringMetadata mastering_metadata;
+  // Max content light level (CLL), i.e. maximum brightness level present in the
+  // stream, in nits. 1 nit = 1 candela/m2. Valid range [0, 20000].
+  int max_content_light_level = 0;
+  // Max frame-average light level (FALL), i.e. maximum average brightness of
+  // the brightest frame in the stream, in nits. Valid range [0, 20000].
+  int max_frame_average_light_level = 0;
 };
 
 }  // namespace webrtc
diff --git a/api/video/i010_buffer.cc b/api/video/i010_buffer.cc
index adb5a5e..7286676 100644
--- a/api/video/i010_buffer.cc
+++ b/api/video/i010_buffer.cc
@@ -9,14 +9,12 @@
  */
 #include "api/video/i010_buffer.h"
 
-#include <algorithm>
 #include <utility>
 
 #include "api/video/i420_buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
-#include "third_party/libyuv/include/libyuv/planar_functions.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
 
 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
@@ -234,4 +232,35 @@
   CropAndScaleFrom(src, 0, 0, src.width(), src.height());
 }
 
+void I010Buffer::PasteFrom(const I010BufferInterface& picture,
+                           int offset_col,
+                           int offset_row) {
+  RTC_CHECK_LE(picture.width() + offset_col, width());
+  RTC_CHECK_LE(picture.height() + offset_row, height());
+  RTC_CHECK_GE(offset_col, 0);
+  RTC_CHECK_GE(offset_row, 0);
+
+  // Pasted picture has to be aligned so subsumpled UV plane isn't corrupted.
+  RTC_CHECK(offset_col % 2 == 0);
+  RTC_CHECK(offset_row % 2 == 0);
+  RTC_CHECK(picture.width() % 2 == 0 ||
+            picture.width() + offset_col == width());
+  RTC_CHECK(picture.height() % 2 == 0 ||
+            picture.height() + offset_row == height());
+
+  libyuv::CopyPlane_16(picture.DataY(), picture.StrideY(),
+                       MutableDataY() + StrideY() * offset_row + offset_col,
+                       StrideY(), picture.width(), picture.height());
+
+  libyuv::CopyPlane_16(
+      picture.DataU(), picture.StrideU(),
+      MutableDataU() + StrideU() * offset_row / 2 + offset_col / 2, StrideU(),
+      picture.width() / 2, picture.height() / 2);
+
+  libyuv::CopyPlane_16(
+      picture.DataV(), picture.StrideV(),
+      MutableDataV() + StrideV() * offset_row / 2 + offset_col / 2, StrideV(),
+      picture.width() / 2, picture.height() / 2);
+}
+
 }  // namespace webrtc
diff --git a/api/video/i010_buffer.h b/api/video/i010_buffer.h
index 1208b31..4b35ca3 100644
--- a/api/video/i010_buffer.h
+++ b/api/video/i010_buffer.h
@@ -11,8 +11,10 @@
 #ifndef API_VIDEO_I010_BUFFER_H_
 #define API_VIDEO_I010_BUFFER_H_
 
+#include <stdint.h>
 #include <memory>
 
+#include "api/scoped_refptr.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
 #include "rtc_base/memory/aligned_malloc.h"
@@ -63,6 +65,12 @@
   // Scale all of |src| to the size of |this| buffer, with no cropping.
   void ScaleFrom(const I010BufferInterface& src);
 
+  // Pastes whole picture to canvas at (offset_row, offset_col).
+  // Offsets and picture dimensions must be even.
+  void PasteFrom(const I010BufferInterface& picture,
+                 int offset_col,
+                 int offset_row);
+
  protected:
   I010Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
   ~I010Buffer() override;
diff --git a/api/video/i420_buffer.cc b/api/video/i420_buffer.cc
index 8d239f3..46de581 100644
--- a/api/video/i420_buffer.cc
+++ b/api/video/i420_buffer.cc
@@ -10,12 +10,11 @@
 #include "api/video/i420_buffer.h"
 
 #include <string.h>
-
 #include <algorithm>
 #include <utility>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/keep_ref_until_done.h"
+#include "rtc_base/ref_counted_object.h"
 #include "third_party/libyuv/include/libyuv/convert.h"
 #include "third_party/libyuv/include/libyuv/planar_functions.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
@@ -227,4 +226,35 @@
   CropAndScaleFrom(src, 0, 0, src.width(), src.height());
 }
 
+void I420Buffer::PasteFrom(const I420BufferInterface& picture,
+                           int offset_col,
+                           int offset_row) {
+  RTC_CHECK_LE(picture.width() + offset_col, width());
+  RTC_CHECK_LE(picture.height() + offset_row, height());
+  RTC_CHECK_GE(offset_col, 0);
+  RTC_CHECK_GE(offset_row, 0);
+
+  // Pasted picture has to be aligned so subsumpled UV plane isn't corrupted.
+  RTC_CHECK(offset_col % 2 == 0);
+  RTC_CHECK(offset_row % 2 == 0);
+  RTC_CHECK(picture.width() % 2 == 0 ||
+            picture.width() + offset_col == width());
+  RTC_CHECK(picture.height() % 2 == 0 ||
+            picture.height() + offset_row == height());
+
+  libyuv::CopyPlane(picture.DataY(), picture.StrideY(),
+                    MutableDataY() + StrideY() * offset_row + offset_col,
+                    StrideY(), picture.width(), picture.height());
+
+  libyuv::CopyPlane(
+      picture.DataU(), picture.StrideU(),
+      MutableDataU() + StrideU() * offset_row / 2 + offset_col / 2, StrideU(),
+      picture.width() / 2, picture.height() / 2);
+
+  libyuv::CopyPlane(
+      picture.DataV(), picture.StrideV(),
+      MutableDataV() + StrideV() * offset_row / 2 + offset_col / 2, StrideV(),
+      picture.width() / 2, picture.height() / 2);
+}
+
 }  // namespace webrtc
diff --git a/api/video/i420_buffer.h b/api/video/i420_buffer.h
index 631e394..b76a507 100644
--- a/api/video/i420_buffer.h
+++ b/api/video/i420_buffer.h
@@ -14,10 +14,10 @@
 #include <stdint.h>
 #include <memory>
 
+#include "api/scoped_refptr.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
 #include "rtc_base/memory/aligned_malloc.h"
-#include "rtc_base/scoped_ref_ptr.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
@@ -97,6 +97,12 @@
   // Scale all of |src| to the size of |this| buffer, with no cropping.
   void ScaleFrom(const I420BufferInterface& src);
 
+  // Pastes whole picture to canvas at (offset_row, offset_col).
+  // Offsets and picture dimensions must be even.
+  void PasteFrom(const I420BufferInterface& picture,
+                 int offset_col,
+                 int offset_row);
+
  protected:
   I420Buffer(int width, int height);
   I420Buffer(int width, int height, int stride_y, int stride_u, int stride_v);
diff --git a/api/video/video_bitrate_allocation.h b/api/video/video_bitrate_allocation.h
index d1771b4..ef64226 100644
--- a/api/video/video_bitrate_allocation.h
+++ b/api/video/video_bitrate_allocation.h
@@ -18,14 +18,10 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/video/video_codec_constants.h"
 
 namespace webrtc {
 
-// TODO(sprang): Move back to common_types when include of this is removed.
-enum : int { kMaxSimulcastStreams = 4 };
-enum : int { kMaxSpatialLayers = 5 };
-enum : int { kMaxTemporalStreams = 4 };
-
 // Class that describes how video bitrate, in bps, is allocated across temporal
 // and spatial layers. Not that bitrates are NOT cumulative. Depending on if
 // layers are dependent or not, it is up to the user to aggregate.
diff --git a/api/video/video_codec_constants.h b/api/video/video_codec_constants.h
new file mode 100644
index 0000000..a3f7cd2
--- /dev/null
+++ b/api/video/video_codec_constants.h
@@ -0,0 +1,22 @@
+/*
+ *  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.
+ */
+
+#ifndef API_VIDEO_VIDEO_CODEC_CONSTANTS_H_
+#define API_VIDEO_VIDEO_CODEC_CONSTANTS_H_
+
+namespace webrtc {
+
+enum : int { kMaxSimulcastStreams = 4 };
+enum : int { kMaxSpatialLayers = 5 };
+enum : int { kMaxTemporalStreams = 4 };
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_VIDEO_CODEC_CONSTANTS_H_
diff --git a/api/video/video_codec_type.h b/api/video/video_codec_type.h
index 447723c..2e406c0 100644
--- a/api/video/video_codec_type.h
+++ b/api/video/video_codec_type.h
@@ -21,7 +21,6 @@
   kVideoCodecVP8,
   kVideoCodecVP9,
   kVideoCodecH264,
-  kVideoCodecI420,
   kVideoCodecMultiplex,
 };
 
diff --git a/api/video/video_frame.cc b/api/video/video_frame.cc
index eaae33b..7a71f43 100644
--- a/api/video/video_frame.cc
+++ b/api/video/video_frame.cc
@@ -10,18 +10,63 @@
 
 #include "api/video/video_frame.h"
 
+#include <algorithm>
+
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
+void VideoFrame::UpdateRect::Union(const UpdateRect& other) {
+  if (other.IsEmpty())
+    return;
+  if (IsEmpty()) {
+    *this = other;
+    return;
+  }
+  int right = std::max(offset_x + width, other.offset_x + other.width);
+  int bottom = std::max(offset_y + height, other.offset_y + other.height);
+  offset_x = std::min(offset_x, other.offset_x);
+  offset_y = std::min(offset_y, other.offset_y);
+  width = right - offset_x;
+  height = bottom - offset_y;
+  RTC_DCHECK_GT(width, 0);
+  RTC_DCHECK_GT(height, 0);
+}
+
+void VideoFrame::UpdateRect::Intersect(const UpdateRect& other) {
+  if (other.IsEmpty() || IsEmpty()) {
+    MakeEmptyUpdate();
+    return;
+  }
+
+  int right = std::min(offset_x + width, other.offset_x + other.width);
+  int bottom = std::min(offset_y + height, other.offset_y + other.height);
+  offset_x = std::max(offset_x, other.offset_x);
+  offset_y = std::max(offset_y, other.offset_y);
+  width = right - offset_x;
+  height = bottom - offset_y;
+  if (width <= 0 || height <= 0) {
+    MakeEmptyUpdate();
+  }
+}
+
+void VideoFrame::UpdateRect::MakeEmptyUpdate() {
+  width = height = offset_x = offset_y = 0;
+}
+
+bool VideoFrame::UpdateRect::IsEmpty() const {
+  return width == 0 && height == 0;
+}
+
 VideoFrame::Builder::Builder() = default;
 
 VideoFrame::Builder::~Builder() = default;
 
 VideoFrame VideoFrame::Builder::build() {
-  return VideoFrame(video_frame_buffer_, timestamp_us_, timestamp_rtp_,
-                    ntp_time_ms_, rotation_, color_space_);
+  RTC_CHECK(video_frame_buffer_ != nullptr);
+  return VideoFrame(id_, video_frame_buffer_, timestamp_us_, timestamp_rtp_,
+                    ntp_time_ms_, rotation_, color_space_, update_rect_);
 }
 
 VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer(
@@ -59,7 +104,7 @@
 }
 
 VideoFrame::Builder& VideoFrame::Builder::set_color_space(
-    const ColorSpace& color_space) {
+    const absl::optional<ColorSpace>& color_space) {
   color_space_ = color_space;
   return *this;
 }
@@ -71,6 +116,17 @@
   return *this;
 }
 
+VideoFrame::Builder& VideoFrame::Builder::set_id(uint16_t id) {
+  id_ = id;
+  return *this;
+}
+
+VideoFrame::Builder& VideoFrame::Builder::set_update_rect(
+    const VideoFrame::UpdateRect& update_rect) {
+  update_rect_ = update_rect;
+  return *this;
+}
+
 VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                        webrtc::VideoRotation rotation,
                        int64_t timestamp_us)
@@ -78,7 +134,8 @@
       timestamp_rtp_(0),
       ntp_time_ms_(0),
       timestamp_us_(timestamp_us),
-      rotation_(rotation) {}
+      rotation_(rotation),
+      update_rect_{0, 0, buffer->width(), buffer->height()} {}
 
 VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                        uint32_t timestamp_rtp,
@@ -88,22 +145,33 @@
       timestamp_rtp_(timestamp_rtp),
       ntp_time_ms_(0),
       timestamp_us_(render_time_ms * rtc::kNumMicrosecsPerMillisec),
-      rotation_(rotation) {
+      rotation_(rotation),
+      update_rect_{0, 0, buffer->width(), buffer->height()} {
   RTC_DCHECK(buffer);
 }
 
-VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
+VideoFrame::VideoFrame(uint16_t id,
+                       const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
                        int64_t timestamp_us,
                        uint32_t timestamp_rtp,
                        int64_t ntp_time_ms,
                        VideoRotation rotation,
-                       const absl::optional<ColorSpace>& color_space)
-    : video_frame_buffer_(buffer),
+                       const absl::optional<ColorSpace>& color_space,
+                       const absl::optional<UpdateRect>& update_rect)
+    : id_(id),
+      video_frame_buffer_(buffer),
       timestamp_rtp_(timestamp_rtp),
       ntp_time_ms_(ntp_time_ms),
       timestamp_us_(timestamp_us),
       rotation_(rotation),
-      color_space_(color_space) {}
+      color_space_(color_space),
+      update_rect_(update_rect.value_or(UpdateRect{
+          0, 0, video_frame_buffer_->width(), video_frame_buffer_->height()})) {
+  RTC_DCHECK_GE(update_rect_.offset_x, 0);
+  RTC_DCHECK_GE(update_rect_.offset_y, 0);
+  RTC_DCHECK_LE(update_rect_.offset_x + update_rect_.width, width());
+  RTC_DCHECK_LE(update_rect_.offset_y + update_rect_.height, height());
+}
 
 VideoFrame::~VideoFrame() = default;
 
diff --git a/api/video/video_frame.h b/api/video/video_frame.h
index 2c5d081..c7dd02a 100644
--- a/api/video/video_frame.h
+++ b/api/video/video_frame.h
@@ -14,17 +14,36 @@
 #include <stdint.h>
 
 #include "absl/types/optional.h"
+#include "api/scoped_refptr.h"
 #include "api/video/color_space.h"
 #include "api/video/hdr_metadata.h"
 #include "api/video/video_frame_buffer.h"
 #include "api/video/video_rotation.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/checks.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
 
 class RTC_EXPORT VideoFrame {
  public:
+  struct UpdateRect {
+    int offset_x;
+    int offset_y;
+    int width;
+    int height;
+
+    // Makes this UpdateRect a bounding box of this and other rect.
+    void Union(const UpdateRect& other);
+
+    // Makes this UpdateRect an intersection of this and other rect.
+    void Intersect(const UpdateRect& other);
+
+    // Sets everything to 0, making this UpdateRect a zero-size (empty) update.
+    void MakeEmptyUpdate();
+
+    bool IsEmpty() const;
+  };
+
   // Preferred way of building VideoFrame objects.
   class Builder {
    public:
@@ -39,16 +58,20 @@
     Builder& set_timestamp_rtp(uint32_t timestamp_rtp);
     Builder& set_ntp_time_ms(int64_t ntp_time_ms);
     Builder& set_rotation(VideoRotation rotation);
-    Builder& set_color_space(const ColorSpace& color_space);
+    Builder& set_color_space(const absl::optional<ColorSpace>& color_space);
     Builder& set_color_space(const ColorSpace* color_space);
+    Builder& set_id(uint16_t id);
+    Builder& set_update_rect(const UpdateRect& update_rect);
 
    private:
+    uint16_t id_ = 0;
     rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_;
     int64_t timestamp_us_ = 0;
     uint32_t timestamp_rtp_ = 0;
     int64_t ntp_time_ms_ = 0;
     VideoRotation rotation_ = kVideoRotation_0;
     absl::optional<ColorSpace> color_space_;
+    absl::optional<UpdateRect> update_rect_;
   };
 
   // To be deprecated. Migrate all use to Builder.
@@ -75,6 +98,15 @@
   // Get frame size in pixels.
   uint32_t size() const;
 
+  // Get frame ID. Returns 0 if ID is not set. Not guarantee to be transferred
+  // from the sender to the receiver, but preserved on single side. The id
+  // should be propagated between all frame modifications during its lifetime
+  // from capturing to sending as encoded image. It is intended to be unique
+  // over a time window of a few minutes for peer connection, to which
+  // corresponding video stream belongs to.
+  uint16_t id() const { return id_; }
+  void set_id(uint16_t id) { id_ = id; }
+
   // System monotonic clock, same timebase as rtc::TimeMicros().
   int64_t timestamp_us() const { return timestamp_us_; }
   void set_timestamp_us(int64_t timestamp_us) { timestamp_us_ = timestamp_us; }
@@ -115,8 +147,9 @@
   void set_rotation(VideoRotation rotation) { rotation_ = rotation; }
 
   // Get color space when available.
-  const ColorSpace* color_space() const {
-    return color_space_ ? &*color_space_ : nullptr;
+  const absl::optional<ColorSpace>& color_space() const { return color_space_; }
+  void set_color_space(const absl::optional<ColorSpace>& color_space) {
+    color_space_ = color_space;
   }
 
   // Get render time in milliseconds.
@@ -133,14 +166,29 @@
     return video_frame_buffer()->type() == VideoFrameBuffer::Type::kNative;
   }
 
+  // Always initialized to whole frame update, can be set by Builder or manually
+  // by |set_update_rect|.
+  UpdateRect update_rect() const { return update_rect_; }
+  // Rectangle must be within the frame dimensions.
+  void set_update_rect(const VideoFrame::UpdateRect& update_rect) {
+    RTC_DCHECK_GE(update_rect.offset_x, 0);
+    RTC_DCHECK_GE(update_rect.offset_y, 0);
+    RTC_DCHECK_LE(update_rect.offset_x + update_rect.width, width());
+    RTC_DCHECK_LE(update_rect.offset_y + update_rect.height, height());
+    update_rect_ = update_rect;
+  }
+
  private:
-  VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
+  VideoFrame(uint16_t id,
+             const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
              int64_t timestamp_us,
              uint32_t timestamp_rtp,
              int64_t ntp_time_ms,
              VideoRotation rotation,
-             const absl::optional<ColorSpace>& color_space);
+             const absl::optional<ColorSpace>& color_space,
+             const absl::optional<UpdateRect>& update_rect);
 
+  uint16_t id_;
   // An opaque reference counted handle that stores the pixel data.
   rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_;
   uint32_t timestamp_rtp_;
@@ -148,6 +196,9 @@
   int64_t timestamp_us_;
   VideoRotation rotation_;
   absl::optional<ColorSpace> color_space_;
+  // Updated since the last frame area. Unless set explicitly, will always be
+  // a full frame rectangle.
+  UpdateRect update_rect_;
 };
 
 }  // namespace webrtc
diff --git a/api/video/video_frame_buffer.h b/api/video/video_frame_buffer.h
index 1e8169a..7fb603e 100644
--- a/api/video/video_frame_buffer.h
+++ b/api/video/video_frame_buffer.h
@@ -13,8 +13,8 @@
 
 #include <stdint.h>
 
-#include "rtc_base/refcount.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/ref_count.h"
 
 namespace webrtc {
 
diff --git a/api/video/video_source_interface.h b/api/video/video_source_interface.h
index 2bf7370..9d1641c 100644
--- a/api/video/video_source_interface.h
+++ b/api/video/video_source_interface.h
@@ -47,15 +47,13 @@
 template <typename VideoFrameT>
 class VideoSourceInterface {
  public:
+  virtual ~VideoSourceInterface() = default;
+
   virtual void AddOrUpdateSink(VideoSinkInterface<VideoFrameT>* sink,
                                const VideoSinkWants& wants) = 0;
   // RemoveSink must guarantee that at the time the method returns,
   // there is no current and no future calls to VideoSinkInterface::OnFrame.
   virtual void RemoveSink(VideoSinkInterface<VideoFrameT>* sink) = 0;
-
- protected:
-  // Non-public, since one shouldn't own sources via this interface.
-  virtual ~VideoSourceInterface() {}
 };
 
 }  // namespace rtc
diff --git a/api/video/video_stream_encoder_create.cc b/api/video/video_stream_encoder_create.cc
index 3147d34..875edd9 100644
--- a/api/video/video_stream_encoder_create.cc
+++ b/api/video/video_stream_encoder_create.cc
@@ -11,17 +11,30 @@
 #include "api/video/video_stream_encoder_create.h"
 
 #include "absl/memory/memory.h"
+#include "api/task_queue/global_task_queue_factory.h"
+#include "video/overuse_frame_detector.h"
 #include "video/video_stream_encoder.h"
 
 namespace webrtc {
 std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
     uint32_t number_of_cores,
     VideoStreamEncoderObserver* encoder_stats_observer,
-    const VideoStreamEncoderSettings& settings,
-    // Deprecated, used for tests only.
-    rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback) {
-  return absl::make_unique<VideoStreamEncoder>(
-      number_of_cores, encoder_stats_observer, settings, pre_encode_callback,
-      absl::make_unique<OveruseFrameDetector>(encoder_stats_observer));
+    const VideoStreamEncoderSettings& settings) {
+  return CreateVideoStreamEncoder(Clock::GetRealTimeClock(),
+                                  &GlobalTaskQueueFactory(), number_of_cores,
+                                  encoder_stats_observer, settings);
 }
+
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    Clock* clock,
+    TaskQueueFactory* task_queue_factory,
+    uint32_t number_of_cores,
+    VideoStreamEncoderObserver* encoder_stats_observer,
+    const VideoStreamEncoderSettings& settings) {
+  return absl::make_unique<VideoStreamEncoder>(
+      clock, number_of_cores, encoder_stats_observer, settings,
+      absl::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
index 9117273..4241626 100644
--- a/api/video/video_stream_encoder_create.h
+++ b/api/video/video_stream_encoder_create.h
@@ -11,31 +11,31 @@
 #ifndef API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
 #define API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
 
-#include <map>
+#include <stdint.h>
 #include <memory>
-#include <utility>
 
+#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(
     uint32_t number_of_cores,
     VideoStreamEncoderObserver* encoder_stats_observer,
-    const VideoStreamEncoderSettings& settings,
-    // Deprecated, used for tests only.
-    rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback);
+    const VideoStreamEncoderSettings& settings);
 
-inline std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+std::unique_ptr<VideoStreamEncoderInterface> CreateVideoStreamEncoder(
+    Clock* clock,
+    TaskQueueFactory* task_queue_factory,
     uint32_t number_of_cores,
     VideoStreamEncoderObserver* encoder_stats_observer,
-    const VideoStreamEncoderSettings& settings) {
-  return CreateVideoStreamEncoder(number_of_cores, encoder_stats_observer,
-                                  settings, nullptr);
-}
-
+    const VideoStreamEncoderSettings& settings);
 }  // namespace webrtc
 
 #endif  // API_VIDEO_VIDEO_STREAM_ENCODER_CREATE_H_
diff --git a/api/video/video_stream_encoder_interface.h b/api/video/video_stream_encoder_interface.h
index 2f95e58..7181143 100644
--- a/api/video/video_stream_encoder_interface.h
+++ b/api/video/video_stream_encoder_interface.h
@@ -13,7 +13,8 @@
 
 #include <vector>
 
-#include "api/rtpparameters.h"  // For DegradationPreference.
+#include "api/rtp_parameters.h"  // For DegradationPreference.
+#include "api/video/video_bitrate_allocator.h"
 #include "api/video/video_sink_interface.h"
 #include "api/video/video_source_interface.h"
 #include "api/video_codecs/video_encoder.h"
@@ -21,9 +22,6 @@
 
 namespace webrtc {
 
-// TODO(nisse): Move full declaration to api/.
-class VideoBitrateAllocationObserver;
-
 // This interface represents a class responsible for creating and driving the
 // encoder(s) for a single video stream. It is also responsible for adaptation
 // decisions related to video quality, requesting reduced frame rate or
@@ -44,6 +42,7 @@
    public:
     virtual void OnEncoderConfigurationChanged(
         std::vector<VideoStream> streams,
+        VideoEncoderConfig::ContentType content_type,
         int min_transmit_bitrate_bps) = 0;
   };
 
diff --git a/api/video/video_timing.cc b/api/video/video_timing.cc
index 40de011..df1bc48 100644
--- a/api/video/video_timing.cc
+++ b/api/video/video_timing.cc
@@ -10,10 +10,21 @@
 
 #include "api/video/video_timing.h"
 
+#include "api/array_view.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/strings/string_builder.h"
 
 namespace webrtc {
 
+uint16_t VideoSendTiming::GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) {
+  if (time_ms < base_ms) {
+    RTC_DLOG(LS_ERROR) << "Delta " << (time_ms - base_ms)
+                       << "ms expected to be positive";
+  }
+  return rtc::saturated_cast<uint16_t>(time_ms - base_ms);
+}
+
 TimingFrameInfo::TimingFrameInfo()
     : rtp_timestamp(0),
       capture_time_ms(-1),
diff --git a/api/video/video_timing.h b/api/video/video_timing.h
index e787a45..745afbc 100644
--- a/api/video/video_timing.h
+++ b/api/video/video_timing.h
@@ -16,9 +16,6 @@
 #include <limits>
 #include <string>
 
-#include "rtc_base/checks.h"
-#include "rtc_base/numerics/safe_conversions.h"
-
 namespace webrtc {
 
 // Video timing timestamps in ms counted from capture_time_ms of a frame.
@@ -46,10 +43,7 @@
   // Used to fill this data structure as per
   // https://webrtc.org/experiments/rtp-hdrext/video-timing/ extension stores
   // 16-bit deltas of timestamps from packet capture time.
-  static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms) {
-    RTC_DCHECK_GE(time_ms, base_ms);
-    return rtc::saturated_cast<uint16_t>(time_ms - base_ms);
-  }
+  static uint16_t GetDeltaCappedMs(int64_t base_ms, int64_t time_ms);
 
   uint16_t encode_start_delta_ms;
   uint16_t encode_finish_delta_ms;
diff --git a/api/video_track_source_proxy.h b/api/video_track_source_proxy.h
new file mode 100644
index 0000000..eb11bef
--- /dev/null
+++ b/api/video_track_source_proxy.h
@@ -0,0 +1,43 @@
+/*
+ *  Copyright 2012 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_TRACK_SOURCE_PROXY_H_
+#define API_VIDEO_TRACK_SOURCE_PROXY_H_
+
+#include "api/media_stream_interface.h"
+#include "api/proxy.h"
+
+namespace webrtc {
+
+// Makes sure the real VideoTrackSourceInterface implementation is destroyed on
+// the signaling thread and marshals all method calls to the signaling thread.
+// TODO(deadbeef): Move this to .cc file and out of api/. What threads methods
+// are called on is an implementation detail.
+BEGIN_PROXY_MAP(VideoTrackSource)
+PROXY_SIGNALING_THREAD_DESTRUCTOR()
+PROXY_CONSTMETHOD0(SourceState, state)
+PROXY_CONSTMETHOD0(bool, remote)
+PROXY_CONSTMETHOD0(bool, is_screencast)
+PROXY_CONSTMETHOD0(absl::optional<bool>, needs_denoising)
+PROXY_METHOD1(bool, GetStats, Stats*)
+PROXY_WORKER_METHOD2(void,
+                     AddOrUpdateSink,
+                     rtc::VideoSinkInterface<VideoFrame>*,
+                     const rtc::VideoSinkWants&)
+PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
+PROXY_WORKER_METHOD1(void, SetLatency, double)
+PROXY_WORKER_CONSTMETHOD0(double, GetLatency)
+PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
+PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
+END_PROXY_MAP()
+
+}  // namespace webrtc
+
+#endif  // API_VIDEO_TRACK_SOURCE_PROXY_H_
diff --git a/audio/BUILD.gn b/audio/BUILD.gn
index c045af6..3a1d123 100644
--- a/audio/BUILD.gn
+++ b/audio/BUILD.gn
@@ -37,15 +37,11 @@
     "transport_feedback_packet_loss_tracker.h",
   ]
 
-  if (!build_with_chromium && is_clang) {
-    # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-    suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-  }
-
   deps = [
     "../api:array_view",
     "../api:call_api",
     "../api:libjingle_peerconnection_api",
+    "../api:scoped_refptr",
     "../api:transport_api",
     "../api/audio:aec3_factory",
     "../api/audio:audio_frame_api",
@@ -61,7 +57,6 @@
     "../logging:rtc_stream_config",
     "../modules/audio_coding",
     "../modules/audio_coding:audio_encoder_cng",
-    "../modules/audio_coding:audio_format_conversion",
     "../modules/audio_coding:audio_network_adaptor_config",
     "../modules/audio_device",
     "../modules/audio_processing",
@@ -79,7 +74,7 @@
     "../rtc_base:rtc_base_approved",
     "../rtc_base:rtc_task_queue",
     "../rtc_base:safe_minmax",
-    "../rtc_base:stringutils",
+    "../rtc_base/experiments:audio_allocation_settings",
     "../system_wrappers",
     "../system_wrappers:field_trial",
     "../system_wrappers:metrics",
@@ -104,12 +99,8 @@
       "../system_wrappers:system_wrappers",
       "../test:test_common",
       "../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
     ]
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 
   rtc_source_set("audio_tests") {
@@ -148,6 +139,7 @@
       "../logging:rtc_event_log_api",
       "../modules/audio_device:mock_audio_device",
       "../rtc_base:rtc_base_tests_utils",
+      "../test:field_trial",
 
       # For TestAudioDeviceModule
       "../modules/audio_device:audio_device_impl",
@@ -163,6 +155,7 @@
       "../rtc_base:rtc_base_approved",
       "../rtc_base:rtc_task_queue",
       "../rtc_base:safe_compare",
+      "../rtc_base:timeutils",
       "../system_wrappers:system_wrappers",
       "../test:audio_codec_mocks",
       "../test:rtp_test_utils",
@@ -172,11 +165,6 @@
       "//testing/gtest",
       "//third_party/abseil-cpp/absl/memory",
     ]
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 
   if (rtc_enable_protobuf) {
@@ -206,11 +194,6 @@
         "../resources/voice_engine/audio_tiny16.wav",
         "../resources/voice_engine/audio_tiny48.wav",
       ]
-
-      if (!build_with_chromium && is_clang) {
-        # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163)
-        suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-      }
     }
 
     group("low_bandwidth_audio_perf_test") {
@@ -280,10 +263,5 @@
     data = [
       "//resources/voice_engine/audio_dtx16.wav",
     ]
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 }
diff --git a/audio/audio_level.h b/audio/audio_level.h
index 3bbe5fd..bb04cc0 100644
--- a/audio/audio_level.h
+++ b/audio/audio_level.h
@@ -11,7 +11,7 @@
 #ifndef AUDIO_AUDIO_LEVEL_H_
 #define AUDIO_AUDIO_LEVEL_H_
 
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc
index 8d4afe0..b7b68d0 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -17,7 +17,7 @@
 #include "api/array_view.h"
 #include "api/audio_codecs/audio_format.h"
 #include "api/call/audio_sink.h"
-#include "api/rtpparameters.h"
+#include "api/rtp_parameters.h"
 #include "audio/audio_send_stream.h"
 #include "audio/audio_state.h"
 #include "audio/channel_receive.h"
@@ -27,7 +27,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
@@ -67,6 +67,7 @@
 namespace internal {
 namespace {
 std::unique_ptr<voe::ChannelReceiveInterface> CreateChannelReceive(
+    Clock* clock,
     webrtc::AudioState* audio_state,
     ProcessThread* module_process_thread,
     const webrtc::AudioReceiveStream::Config& config,
@@ -75,33 +76,37 @@
   internal::AudioState* internal_audio_state =
       static_cast<internal::AudioState*>(audio_state);
   return voe::CreateChannelReceive(
-      module_process_thread, internal_audio_state->audio_device_module(),
+      clock, module_process_thread, internal_audio_state->audio_device_module(),
       config.media_transport, config.rtcp_send_transport, event_log,
       config.rtp.remote_ssrc, config.jitter_buffer_max_packets,
       config.jitter_buffer_fast_accelerate, config.jitter_buffer_min_delay_ms,
-      config.decoder_factory, config.codec_pair_id, config.frame_decryptor,
-      config.crypto_options);
+      config.jitter_buffer_enable_rtx_handling, config.decoder_factory,
+      config.codec_pair_id, config.frame_decryptor, config.crypto_options);
 }
 }  // namespace
 
 AudioReceiveStream::AudioReceiveStream(
+    Clock* clock,
     RtpStreamReceiverControllerInterface* receiver_controller,
     PacketRouter* packet_router,
     ProcessThread* module_process_thread,
     const webrtc::AudioReceiveStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     webrtc::RtcEventLog* event_log)
-    : AudioReceiveStream(receiver_controller,
+    : AudioReceiveStream(clock,
+                         receiver_controller,
                          packet_router,
                          config,
                          audio_state,
                          event_log,
-                         CreateChannelReceive(audio_state.get(),
+                         CreateChannelReceive(clock,
+                                              audio_state.get(),
                                               module_process_thread,
                                               config,
                                               event_log)) {}
 
 AudioReceiveStream::AudioReceiveStream(
+    Clock* clock,
     RtpStreamReceiverControllerInterface* receiver_controller,
     PacketRouter* packet_router,
     const webrtc::AudioReceiveStream::Config& config,
@@ -175,8 +180,8 @@
       channel_receive_->GetRTCPStatistics();
   // TODO(solenberg): Don't return here if we can't get the codec - return the
   //                  stats we *can* get.
-  webrtc::CodecInst codec_inst = {0};
-  if (!channel_receive_->GetRecCodec(&codec_inst)) {
+  auto receive_codec = channel_receive_->GetReceiveCodec();
+  if (!receive_codec) {
     return stats;
   }
 
@@ -185,13 +190,12 @@
   stats.packets_lost = call_stats.cumulativeLost;
   stats.fraction_lost = Q8ToFloat(call_stats.fractionLost);
   stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
-  if (codec_inst.pltype != -1) {
-    stats.codec_name = codec_inst.plname;
-    stats.codec_payload_type = codec_inst.pltype;
-  }
+  stats.codec_name = receive_codec->second.name;
+  stats.codec_payload_type = receive_codec->first;
   stats.ext_seqnum = call_stats.extendedMax;
-  if (codec_inst.plfreq / 1000 > 0) {
-    stats.jitter_ms = call_stats.jitterSamples / (codec_inst.plfreq / 1000);
+  int clockrate_khz = receive_codec->second.clockrate_hz / 1000;
+  if (clockrate_khz > 0) {
+    stats.jitter_ms = call_stats.jitterSamples / clockrate_khz;
   }
   stats.delay_estimate_ms = channel_receive_->GetDelayEstimate();
   stats.audio_level = channel_receive_->GetSpeechOutputLevelFullRange();
@@ -208,6 +212,7 @@
   stats.jitter_buffer_delay_seconds =
       static_cast<double>(ns.jitterBufferDelayMs) /
       static_cast<double>(rtc::kNumMillisecsPerSec);
+  stats.jitter_buffer_emitted_count = ns.jitterBufferEmittedCount;
   stats.expand_rate = Q14ToFloat(ns.currentExpandRate);
   stats.speech_expand_rate = Q14ToFloat(ns.currentSpeechExpandRate);
   stats.secondary_decoded_rate = Q14ToFloat(ns.currentSecondaryDecodedRate);
@@ -216,6 +221,9 @@
   stats.preemptive_expand_rate = Q14ToFloat(ns.currentPreemptiveRate);
   stats.jitter_buffer_flushes = ns.packetBufferFlushes;
   stats.delayed_packet_outage_samples = ns.delayedPacketOutageSamples;
+  stats.relative_packet_arrival_delay_seconds =
+      static_cast<double>(ns.relativePacketArrivalDelayMs) /
+      static_cast<double>(rtc::kNumMillisecsPerSec);
 
   auto ds = channel_receive_->GetDecodingCallStatistics();
   stats.decoding_calls_to_silence_generator = ds.calls_to_silence_generator;
@@ -239,6 +247,16 @@
   channel_receive_->SetChannelOutputVolumeScaling(gain);
 }
 
+bool AudioReceiveStream::SetBaseMinimumPlayoutDelayMs(int delay_ms) {
+  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  return channel_receive_->SetBaseMinimumPlayoutDelayMs(delay_ms);
+}
+
+int AudioReceiveStream::GetBaseMinimumPlayoutDelayMs() const {
+  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  return channel_receive_->GetBaseMinimumPlayoutDelayMs();
+}
+
 std::vector<RtpSource> AudioReceiveStream::GetSources() const {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   return channel_receive_->GetSources();
diff --git a/audio/audio_receive_stream.h b/audio/audio_receive_stream.h
index 86bcb1c..1745c0f 100644
--- a/audio/audio_receive_stream.h
+++ b/audio/audio_receive_stream.h
@@ -19,8 +19,9 @@
 #include "audio/audio_state.h"
 #include "call/audio_receive_stream.h"
 #include "call/syncable.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/thread_checker.h"
+#include "system_wrappers/include/clock.h"
 
 namespace webrtc {
 class PacketRouter;
@@ -41,7 +42,8 @@
                                  public AudioMixer::Source,
                                  public Syncable {
  public:
-  AudioReceiveStream(RtpStreamReceiverControllerInterface* receiver_controller,
+  AudioReceiveStream(Clock* clock,
+                     RtpStreamReceiverControllerInterface* receiver_controller,
                      PacketRouter* packet_router,
                      ProcessThread* module_process_thread,
                      const webrtc::AudioReceiveStream::Config& config,
@@ -49,6 +51,7 @@
                      webrtc::RtcEventLog* event_log);
   // For unit tests, which need to supply a mock channel receive.
   AudioReceiveStream(
+      Clock* clock,
       RtpStreamReceiverControllerInterface* receiver_controller,
       PacketRouter* packet_router,
       const webrtc::AudioReceiveStream::Config& config,
@@ -64,6 +67,8 @@
   webrtc::AudioReceiveStream::Stats GetStats() const override;
   void SetSink(AudioSinkInterface* sink) override;
   void SetGain(float gain) override;
+  bool SetBaseMinimumPlayoutDelayMs(int delay_ms) override;
+  int GetBaseMinimumPlayoutDelayMs() const override;
   std::vector<webrtc::RtpSource> GetSources() const override;
 
   // TODO(nisse): We don't formally implement RtpPacketSinkInterface, and this
diff --git a/audio/audio_receive_stream_unittest.cc b/audio/audio_receive_stream_unittest.cc
index 7422810..4594e56 100644
--- a/audio/audio_receive_stream_unittest.cc
+++ b/audio/audio_receive_stream_unittest.cc
@@ -10,6 +10,7 @@
 
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "api/test/mock_audio_mixer.h"
@@ -24,6 +25,7 @@
 #include "modules/bitrate_controller/include/mock/mock_bitrate_controller.h"
 #include "modules/pacing/packet_router.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
+#include "rtc_base/time_utils.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder_factory.h"
 #include "test/mock_transport.h"
@@ -63,10 +65,11 @@
 
 const CallReceiveStatistics kCallStats = {345, 678, 901, 234,
                                           -12, 567, 890, 123};
-const CodecInst kCodecInst = {123, "codec_name_recv", 96000, -187, 0, -103};
+const std::pair<int, SdpAudioFormat> kReceiveCodec =
+    {123, {"codec_name_recv", 96000, 0}};
 const NetworkStatistics kNetworkStats = {
-    123, 456, false, 789012, 3456, 123, 456, 0,  {}, 789, 12,
-    345, 678, 901,   0,      -1,   -1,  -1,  -1, -1, 0};
+    123, 456, false, 789012, 3456, 123, 456, 789, 0,  {}, 789,
+    12,  345, 678,   901,    0,    -1,  -1,  -1,  -1, -1, 0};
 const AudioDecodingCallStats kAudioDecodeStats = MakeAudioDecodeStatsForTest();
 
 struct ConfigHelper {
@@ -112,8 +115,8 @@
   std::unique_ptr<internal::AudioReceiveStream> CreateAudioReceiveStream() {
     return std::unique_ptr<internal::AudioReceiveStream>(
         new internal::AudioReceiveStream(
-            &rtp_stream_receiver_controller_, &packet_router_, stream_config_,
-            audio_state_, &event_log_,
+            Clock::GetRealTimeClock(), &rtp_stream_receiver_controller_,
+            &packet_router_, stream_config_, audio_state_, &event_log_,
             std::unique_ptr<voe::ChannelReceiveInterface>(channel_receive_)));
   }
 
@@ -140,8 +143,8 @@
         .WillOnce(Return(kNetworkStats));
     EXPECT_CALL(*channel_receive_, GetDecodingCallStatistics())
         .WillOnce(Return(kAudioDecodeStats));
-    EXPECT_CALL(*channel_receive_, GetRecCodec(_))
-        .WillOnce(DoAll(SetArgPointee<0>(kCodecInst), Return(true)));
+    EXPECT_CALL(*channel_receive_, GetReceiveCodec())
+        .WillOnce(Return(kReceiveCodec));
   }
 
  private:
@@ -267,10 +270,11 @@
             stats.packets_rcvd);
   EXPECT_EQ(kCallStats.cumulativeLost, stats.packets_lost);
   EXPECT_EQ(Q8ToFloat(kCallStats.fractionLost), stats.fraction_lost);
-  EXPECT_EQ(std::string(kCodecInst.plname), stats.codec_name);
+  EXPECT_EQ(kReceiveCodec.second.name, stats.codec_name);
   EXPECT_EQ(kCallStats.extendedMax, stats.ext_seqnum);
-  EXPECT_EQ(kCallStats.jitterSamples / (kCodecInst.plfreq / 1000),
-            stats.jitter_ms);
+  EXPECT_EQ(
+      kCallStats.jitterSamples / (kReceiveCodec.second.clockrate_hz / 1000),
+      stats.jitter_ms);
   EXPECT_EQ(kNetworkStats.currentBufferSize, stats.jitter_buffer_ms);
   EXPECT_EQ(kNetworkStats.preferredBufferSize,
             stats.jitter_buffer_preferred_ms);
@@ -285,6 +289,8 @@
   EXPECT_EQ(static_cast<double>(kNetworkStats.jitterBufferDelayMs) /
                 static_cast<double>(rtc::kNumMillisecsPerSec),
             stats.jitter_buffer_delay_seconds);
+  EXPECT_EQ(kNetworkStats.jitterBufferEmittedCount,
+            stats.jitter_buffer_emitted_count);
   EXPECT_EQ(Q14ToFloat(kNetworkStats.currentExpandRate), stats.expand_rate);
   EXPECT_EQ(Q14ToFloat(kNetworkStats.currentSpeechExpandRate),
             stats.speech_expand_rate);
diff --git a/audio/audio_send_stream.cc b/audio/audio_send_stream.cc
index 75e6efb..bb79149 100644
--- a/audio/audio_send_stream.cc
+++ b/audio/audio_send_stream.cc
@@ -19,7 +19,7 @@
 #include "api/audio_codecs/audio_encoder_factory.h"
 #include "api/audio_codecs/audio_format.h"
 #include "api/call/transport.h"
-#include "api/crypto/frameencryptorinterface.h"
+#include "api/crypto/frame_encryptor_interface.h"
 #include "audio/audio_state.h"
 #include "audio/channel_send.h"
 #include "audio/conversion.h"
@@ -37,7 +37,6 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/audio_format_to_string.h"
 #include "rtc_base/task_queue.h"
-#include "rtc_base/timeutils.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -48,14 +47,6 @@
 constexpr size_t kPacketLossRateMinNumAckedPackets = 50;
 constexpr size_t kRecoverablePacketLossRateMinNumAckedPairs = 40;
 
-void CallEncoder(const std::unique_ptr<voe::ChannelSendInterface>& channel_send,
-                 rtc::FunctionView<void(AudioEncoder*)> lambda) {
-  channel_send->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder_ptr) {
-    RTC_DCHECK(encoder_ptr);
-    lambda(encoder_ptr->get());
-  });
-}
-
 void UpdateEventLogStreamConfig(RtcEventLog* event_log,
                                 const AudioSendStream::Config& config,
                                 const AudioSendStream::Config* old_config) {
@@ -91,6 +82,7 @@
 }  // namespace
 
 AudioSendStream::AudioSendStream(
+    Clock* clock,
     const webrtc::AudioSendStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     rtc::TaskQueue* worker_queue,
@@ -100,7 +92,8 @@
     RtcEventLog* event_log,
     RtcpRttStats* rtcp_rtt_stats,
     const absl::optional<RtpState>& suspended_rtp_state)
-    : AudioSendStream(config,
+    : AudioSendStream(clock,
+                      config,
                       audio_state,
                       worker_queue,
                       rtp_transport,
@@ -108,9 +101,11 @@
                       event_log,
                       rtcp_rtt_stats,
                       suspended_rtp_state,
-                      voe::CreateChannelSend(worker_queue,
+                      voe::CreateChannelSend(clock,
+                                             worker_queue,
                                              module_process_thread,
                                              config.media_transport,
+                                             /*overhead_observer=*/this,
                                              config.send_transport,
                                              rtcp_rtt_stats,
                                              event_log,
@@ -120,6 +115,7 @@
                                              config.rtcp_report_interval_ms)) {}
 
 AudioSendStream::AudioSendStream(
+    Clock* clock,
     const webrtc::AudioSendStream::Config& config,
     const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
     rtc::TaskQueue* worker_queue,
@@ -129,7 +125,8 @@
     RtcpRttStats* rtcp_rtt_stats,
     const absl::optional<RtpState>& suspended_rtp_state,
     std::unique_ptr<voe::ChannelSendInterface> channel_send)
-    : worker_queue_(worker_queue),
+    : clock_(clock),
+      worker_queue_(worker_queue),
       config_(Config(/*send_transport=*/nullptr,
                      /*media_transport=*/nullptr)),
       audio_state_(audio_state),
@@ -152,7 +149,15 @@
   // should be no rtp_transport, and below check should be strengthened to XOR
   // (either rtp_transport or media_transport but not both).
   RTC_DCHECK(rtp_transport || config.media_transport);
-
+  if (config.media_transport) {
+    // TODO(sukhanov): Currently media transport audio overhead is considered
+    // constant, we will not get overhead_observer calls when using
+    // media_transport. In the future when we introduce RTP media transport we
+    // should make audio overhead interface consistent and work for both RTP and
+    // non-RTP implementations.
+    audio_overhead_per_packet_bytes_ =
+        config.media_transport->GetAudioPacketOverhead();
+  }
   rtp_rtcp_module_ = channel_send_->GetRtpRtcp();
   RTC_DCHECK(rtp_rtcp_module_);
 
@@ -197,11 +202,19 @@
       ids.transport_sequence_number = extension.id;
     } else if (extension.uri == RtpExtension::kMidUri) {
       ids.mid = extension.id;
+    } else if (extension.uri == RtpExtension::kRidUri) {
+      ids.rid = extension.id;
+    } else if (extension.uri == RtpExtension::kRepairedRidUri) {
+      ids.repaired_rid = extension.id;
     }
   }
   return ids;
 }
 
+int AudioSendStream::TransportSeqNumId(const AudioSendStream::Config& config) {
+  return FindExtensionIds(config.rtp.extensions).transport_sequence_number;
+}
+
 void AudioSendStream::ConfigureStream(
     webrtc::internal::AudioSendStream* stream,
     const webrtc::AudioSendStream::Config& new_config,
@@ -247,18 +260,16 @@
   }
   bool transport_seq_num_id_changed =
       new_ids.transport_sequence_number != old_ids.transport_sequence_number;
-  if (first_time ||
-      (transport_seq_num_id_changed &&
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-ForceNoTWCC"))) {
+  if (first_time || (transport_seq_num_id_changed &&
+                     !stream->allocation_settings_.ForceNoAudioFeedback())) {
     if (!first_time) {
       channel_send->ResetSenderCongestionControlObjects();
     }
 
     RtcpBandwidthObserver* bandwidth_observer = nullptr;
-    bool has_transport_sequence_number =
-        new_ids.transport_sequence_number != 0 &&
-        !webrtc::field_trial::IsEnabled("WebRTC-Audio-ForceNoTWCC");
-    if (has_transport_sequence_number) {
+
+    if (stream->allocation_settings_.ShouldSendTransportSequenceNumber(
+            new_ids.transport_sequence_number)) {
       channel_send->EnableSendTransportSequenceNumber(
           new_ids.transport_sequence_number);
       // Probing in application limited region is only used in combination with
@@ -281,6 +292,13 @@
     channel_send->SetMid(new_config.rtp.mid, new_ids.mid);
   }
 
+  // RID RTP header extension
+  if ((first_time || new_ids.rid != old_ids.rid ||
+       new_ids.repaired_rid != old_ids.repaired_rid ||
+       new_config.rtp.rid != old_config.rtp.rid)) {
+    channel_send->SetRid(new_config.rtp.rid, new_ids.rid, new_ids.repaired_rid);
+  }
+
   if (!ReconfigureSendCodec(stream, new_config)) {
     RTC_LOG(LS_ERROR) << "Failed to set up send codec state.";
   }
@@ -297,20 +315,13 @@
     return;
   }
 
-  bool has_transport_sequence_number =
-      FindExtensionIds(config_.rtp.extensions).transport_sequence_number != 0 &&
-      !webrtc::field_trial::IsEnabled("WebRTC-Audio-ForceNoTWCC");
-  if (config_.min_bitrate_bps != -1 && config_.max_bitrate_bps != -1 &&
-      !config_.has_dscp &&
-      (has_transport_sequence_number ||
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe") ||
-       webrtc::field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC"))) {
-    // Audio BWE is enabled.
+  if (allocation_settings_.IncludeAudioInAllocationOnStart(
+          config_.min_bitrate_bps, config_.max_bitrate_bps, config_.has_dscp,
+          TransportSeqNumId(config_))) {
     rtp_transport_->packet_sender()->SetAccountForAudioPackets(true);
     rtp_rtcp_module_->SetAsPartOfAllocation(true);
     ConfigureBitrateObserver(config_.min_bitrate_bps, config_.max_bitrate_bps,
-                             config_.bitrate_priority,
-                             has_transport_sequence_number);
+                             config_.bitrate_priority);
   } else {
     rtp_rtcp_module_->SetAsPartOfAllocation(false);
   }
@@ -448,7 +459,7 @@
     // TODO(eladalon): This function call could potentially reset the window,
     // setting both PLR and RPLR to unknown. Consider (during upcoming
     // refactoring) passing an indication of such an event.
-    packet_loss_tracker_.OnPacketAdded(seq_num, rtc::TimeMillis());
+    packet_loss_tracker_.OnPacketAdded(seq_num, clock_->TimeInMilliseconds());
   }
 }
 
@@ -474,9 +485,36 @@
   }
 }
 
-void AudioSendStream::SetTransportOverhead(int transport_overhead_per_packet) {
+void AudioSendStream::SetTransportOverhead(
+    int transport_overhead_per_packet_bytes) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  channel_send_->SetTransportOverhead(transport_overhead_per_packet);
+  rtc::CritScope cs(&overhead_per_packet_lock_);
+  transport_overhead_per_packet_bytes_ = transport_overhead_per_packet_bytes;
+  UpdateOverheadForEncoder();
+}
+
+void AudioSendStream::OnOverheadChanged(
+    size_t overhead_bytes_per_packet_bytes) {
+  rtc::CritScope cs(&overhead_per_packet_lock_);
+  audio_overhead_per_packet_bytes_ = overhead_bytes_per_packet_bytes;
+  UpdateOverheadForEncoder();
+}
+
+void AudioSendStream::UpdateOverheadForEncoder() {
+  const size_t overhead_per_packet_bytes = GetPerPacketOverheadBytes();
+  channel_send_->CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedOverhead(overhead_per_packet_bytes);
+  });
+}
+
+size_t AudioSendStream::TestOnlyGetPerPacketOverheadBytes() const {
+  rtc::CritScope cs(&overhead_per_packet_lock_);
+  return GetPerPacketOverheadBytes();
+}
+
+size_t AudioSendStream::GetPerPacketOverheadBytes() const {
+  return transport_overhead_per_packet_bytes_ +
+         audio_overhead_per_packet_bytes_;
 }
 
 RtpState AudioSendStream::GetRtpState() const {
@@ -529,16 +567,11 @@
     return false;
   }
 
-  // If other side does not support audio TWCC and WebRTC-Audio-ABWENoTWCC is
-  // not enabled, do not update target audio bitrate if we are in
-  // WebRTC-Audio-SendSideBwe-For-Video experiment
-  const bool do_not_update_target_bitrate =
-      !webrtc::field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC") &&
-      webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe-For-Video") &&
-      !FindExtensionIds(new_config.rtp.extensions).transport_sequence_number;
   // If a bitrate has been specified for the codec, use it over the
   // codec's default.
-  if (!do_not_update_target_bitrate && spec.target_bitrate_bps) {
+  if (stream->allocation_settings_.UpdateAudioTargetBitrate(
+          TransportSeqNumId(new_config)) &&
+      spec.target_bitrate_bps) {
     encoder->OnReceivedTargetAudioBitrate(*spec.target_bitrate_bps);
   }
 
@@ -567,10 +600,18 @@
         new_config.send_codec_spec->format.clockrate_hz);
   }
 
+  // Set currently known overhead (used in ANA, opus only).
+  // If overhead changes later, it will be updated in UpdateOverheadForEncoder.
+  {
+    rtc::CritScope cs(&stream->overhead_per_packet_lock_);
+    encoder->OnReceivedOverhead(stream->GetPerPacketOverheadBytes());
+  }
+
   stream->StoreEncoderProperties(encoder->SampleRateHz(),
                                  encoder->NumChannels());
   stream->channel_send_->SetEncoder(new_config.send_codec_spec->payload_type,
                                     std::move(encoder));
+
   return true;
 }
 
@@ -601,22 +642,16 @@
     return SetupSendCodec(stream, new_config);
   }
 
-  // If other side does not support audio TWCC and WebRTC-Audio-ABWENoTWCC is
-  // not enabled, do not update target audio bitrate if we are in
-  // WebRTC-Audio-SendSideBwe-For-Video experiment
-  const bool do_not_update_target_bitrate =
-      !webrtc::field_trial::IsEnabled("WebRTC-Audio-ABWENoTWCC") &&
-      webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe-For-Video") &&
-      !FindExtensionIds(new_config.rtp.extensions).transport_sequence_number;
-
   const absl::optional<int>& new_target_bitrate_bps =
       new_config.send_codec_spec->target_bitrate_bps;
   // If a bitrate has been specified for the codec, use it over the
   // codec's default.
-  if (!do_not_update_target_bitrate && new_target_bitrate_bps &&
+  if (stream->allocation_settings_.UpdateAudioTargetBitrate(
+          TransportSeqNumId(new_config)) &&
+      new_target_bitrate_bps &&
       new_target_bitrate_bps !=
           old_config.send_codec_spec->target_bitrate_bps) {
-    CallEncoder(stream->channel_send_, [&](AudioEncoder* encoder) {
+    stream->channel_send_->CallEncoder([&](AudioEncoder* encoder) {
       encoder->OnReceivedTargetAudioBitrate(*new_target_bitrate_bps);
     });
   }
@@ -624,6 +659,12 @@
   ReconfigureANA(stream, new_config);
   ReconfigureCNG(stream, new_config);
 
+  // Set currently known overhead (used in ANA, opus only).
+  {
+    rtc::CritScope cs(&stream->overhead_per_packet_lock_);
+    stream->UpdateOverheadForEncoder();
+  }
+
   return true;
 }
 
@@ -634,7 +675,7 @@
     return;
   }
   if (new_config.audio_network_adaptor_config) {
-    CallEncoder(stream->channel_send_, [&](AudioEncoder* encoder) {
+    stream->channel_send_->CallEncoder([&](AudioEncoder* encoder) {
       if (encoder->EnableAudioNetworkAdaptor(
               *new_config.audio_network_adaptor_config, stream->event_log_)) {
         RTC_DLOG(LS_INFO) << "Audio network adaptor enabled on SSRC "
@@ -644,9 +685,8 @@
       }
     });
   } else {
-    CallEncoder(stream->channel_send_, [&](AudioEncoder* encoder) {
-      encoder->DisableAudioNetworkAdaptor();
-    });
+    stream->channel_send_->CallEncoder(
+        [&](AudioEncoder* encoder) { encoder->DisableAudioNetworkAdaptor(); });
     RTC_DLOG(LS_INFO) << "Audio network adaptor disabled on SSRC "
                       << new_config.rtp.ssrc;
   }
@@ -701,26 +741,21 @@
   // allow us to configure the bitrate observer if the new config has bitrate
   // limits set, but would only have us call RemoveBitrateObserver if we were
   // previously configured with bitrate limits.
-  int new_transport_seq_num_id =
-      FindExtensionIds(new_config.rtp.extensions).transport_sequence_number;
   if (stream->config_.min_bitrate_bps == new_config.min_bitrate_bps &&
       stream->config_.max_bitrate_bps == new_config.max_bitrate_bps &&
       stream->config_.bitrate_priority == new_config.bitrate_priority &&
-      (FindExtensionIds(stream->config_.rtp.extensions)
-               .transport_sequence_number == new_transport_seq_num_id ||
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe"))) {
+      (TransportSeqNumId(stream->config_) == TransportSeqNumId(new_config) ||
+       stream->allocation_settings_.IgnoreSeqNumIdChange())) {
     return;
   }
 
-  bool has_transport_sequence_number = new_transport_seq_num_id != 0;
-  if (new_config.min_bitrate_bps != -1 && new_config.max_bitrate_bps != -1 &&
-      !new_config.has_dscp &&
-      (has_transport_sequence_number ||
-       !webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe"))) {
+  if (stream->allocation_settings_.IncludeAudioInAllocationOnReconfigure(
+          new_config.min_bitrate_bps, new_config.max_bitrate_bps,
+          new_config.has_dscp, TransportSeqNumId(new_config))) {
     stream->rtp_transport_->packet_sender()->SetAccountForAudioPackets(true);
-    stream->ConfigureBitrateObserver(
-        new_config.min_bitrate_bps, new_config.max_bitrate_bps,
-        new_config.bitrate_priority, has_transport_sequence_number);
+    stream->ConfigureBitrateObserver(new_config.min_bitrate_bps,
+                                     new_config.max_bitrate_bps,
+                                     new_config.bitrate_priority);
     stream->rtp_rtcp_module_->SetAsPartOfAllocation(true);
   } else {
     stream->rtp_transport_->packet_sender()->SetAccountForAudioPackets(false);
@@ -731,8 +766,7 @@
 
 void AudioSendStream::ConfigureBitrateObserver(int min_bitrate_bps,
                                                int max_bitrate_bps,
-                                               double bitrate_priority,
-                                               bool has_packet_feedback) {
+                                               double bitrate_priority) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
   RTC_DCHECK_GE(max_bitrate_bps, min_bitrate_bps);
   rtc::Event thread_sync_event;
@@ -746,8 +780,9 @@
     bitrate_allocator_->AddObserver(
         this, MediaStreamAllocationConfig{
                   static_cast<uint32_t>(min_bitrate_bps),
-                  static_cast<uint32_t>(max_bitrate_bps), 0, true,
-                  config_.track_id, bitrate_priority, has_packet_feedback});
+                  static_cast<uint32_t>(max_bitrate_bps), 0,
+                  allocation_settings_.DefaultPriorityBitrate().bps(), true,
+                  config_.track_id, bitrate_priority});
     thread_sync_event.Set();
   });
   thread_sync_event.Wait(rtc::Event::kForever);
@@ -765,14 +800,8 @@
 
 void AudioSendStream::RegisterCngPayloadType(int payload_type,
                                              int clockrate_hz) {
-  const CodecInst codec = {payload_type, "CN", clockrate_hz, 0, 1, 0};
-  if (rtp_rtcp_module_->RegisterSendPayload(codec) != 0) {
-    rtp_rtcp_module_->DeRegisterSendPayload(codec.pltype);
-    if (rtp_rtcp_module_->RegisterSendPayload(codec) != 0) {
-      RTC_DLOG(LS_ERROR) << "RegisterCngPayloadType() failed to register CN to "
-                            "RTP/RTCP module";
-    }
-  }
+  rtp_rtcp_module_->RegisterAudioSendPayload(payload_type, "CN", clockrate_hz,
+                                             1, 0);
 }
 }  // namespace internal
 }  // namespace webrtc
diff --git a/audio/audio_send_stream.h b/audio/audio_send_stream.h
index bf94901..c227e61 100644
--- a/audio/audio_send_stream.h
+++ b/audio/audio_send_stream.h
@@ -20,7 +20,8 @@
 #include "call/audio_state.h"
 #include "call/bitrate_allocator.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/experiments/audio_allocation_settings.h"
 #include "rtc_base/race_checker.h"
 #include "rtc_base/thread_checker.h"
 
@@ -35,9 +36,11 @@
 
 class AudioSendStream final : public webrtc::AudioSendStream,
                               public webrtc::BitrateAllocatorObserver,
-                              public webrtc::PacketFeedbackObserver {
+                              public webrtc::PacketFeedbackObserver,
+                              public webrtc::OverheadObserver {
  public:
-  AudioSendStream(const webrtc::AudioSendStream::Config& config,
+  AudioSendStream(Clock* clock,
+                  const webrtc::AudioSendStream::Config& config,
                   const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
                   rtc::TaskQueue* worker_queue,
                   ProcessThread* module_process_thread,
@@ -47,7 +50,8 @@
                   RtcpRttStats* rtcp_rtt_stats,
                   const absl::optional<RtpState>& suspended_rtp_state);
   // For unit tests, which need to supply a mock ChannelSend.
-  AudioSendStream(const webrtc::AudioSendStream::Config& config,
+  AudioSendStream(Clock* clock,
+                  const webrtc::AudioSendStream::Config& config,
                   const rtc::scoped_refptr<webrtc::AudioState>& audio_state,
                   rtc::TaskQueue* worker_queue,
                   RtpTransportControllerSendInterface* rtp_transport,
@@ -84,11 +88,19 @@
   void OnPacketFeedbackVector(
       const std::vector<PacketFeedback>& packet_feedback_vector) override;
 
-  void SetTransportOverhead(int transport_overhead_per_packet);
+  void SetTransportOverhead(int transport_overhead_per_packet_bytes);
+
+  // OverheadObserver override reports audio packetization overhead from
+  // RTP/RTCP module or Media Transport.
+  void OnOverheadChanged(size_t overhead_bytes_per_packet_bytes) override;
 
   RtpState GetRtpState() const;
   const voe::ChannelSendInterface* GetChannel() const;
 
+  // Returns combined per-packet overhead.
+  size_t TestOnlyGetPerPacketOverheadBytes() const
+      RTC_LOCKS_EXCLUDED(overhead_per_packet_lock_);
+
  private:
   class TimedTransport;
 
@@ -112,16 +124,26 @@
 
   void ConfigureBitrateObserver(int min_bitrate_bps,
                                 int max_bitrate_bps,
-                                double bitrate_priority,
-                                bool has_packet_feedback);
+                                double bitrate_priority);
   void RemoveBitrateObserver();
 
+  // Sets per-packet overhead on encoded (for ANA) based on current known values
+  // of transport and packetization overheads.
+  void UpdateOverheadForEncoder()
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
+
+  // Returns combined per-packet overhead.
+  size_t GetPerPacketOverheadBytes() const
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
+
   void RegisterCngPayloadType(int payload_type, int clockrate_hz);
+  Clock* clock_;
 
   rtc::ThreadChecker worker_thread_checker_;
   rtc::ThreadChecker pacer_thread_checker_;
   rtc::RaceChecker audio_capture_race_checker_;
   rtc::TaskQueue* worker_queue_;
+  const AudioAllocationSettings allocation_settings_;
   webrtc::AudioSendStream::Config config_;
   rtc::scoped_refptr<webrtc::AudioState> audio_state_;
   const std::unique_ptr<voe::ChannelSendInterface> channel_send_;
@@ -148,9 +170,22 @@
     int audio_level = 0;
     int transport_sequence_number = 0;
     int mid = 0;
+    int rid = 0;
+    int repaired_rid = 0;
   };
   static ExtensionIds FindExtensionIds(
       const std::vector<RtpExtension>& extensions);
+  static int TransportSeqNumId(const Config& config);
+
+  rtc::CriticalSection overhead_per_packet_lock_;
+
+  // Current transport overhead (ICE, TURN, etc.)
+  size_t transport_overhead_per_packet_bytes_
+      RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
+
+  // Current audio packetization overhead (RTP or Media Transport).
+  size_t audio_overhead_per_packet_bytes_
+      RTC_GUARDED_BY(overhead_per_packet_lock_) = 0;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(AudioSendStream);
 };
diff --git a/audio/audio_send_stream_tests.cc b/audio/audio_send_stream_tests.cc
index 7deeff3..8a83554 100644
--- a/audio/audio_send_stream_tests.cc
+++ b/audio/audio_send_stream_tests.cc
@@ -8,7 +8,12 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string>
+#include <utility>
+#include <vector>
+
 #include "test/call_test.h"
+#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/rtcp_packet_parser.h"
 
@@ -16,6 +21,11 @@
 namespace test {
 namespace {
 
+enum : int {  // The first valid value is 1.
+  kAudioLevelExtensionId = 1,
+  kTransportSequenceNumberExtensionId,
+};
+
 class AudioSendTest : public SendTest {
  public:
   AudioSendTest() : SendTest(CallTest::kDefaultTimeoutMs) {}
@@ -101,8 +111,8 @@
   class AudioLevelObserver : public AudioSendTest {
    public:
     AudioLevelObserver() : AudioSendTest() {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionAudioLevel, test::kAudioLevelExtensionId));
+      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
+                                                      kAudioLevelExtensionId));
     }
 
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
@@ -125,8 +135,8 @@
         AudioSendStream::Config* send_config,
         std::vector<AudioReceiveStream::Config>* receive_configs) override {
       send_config->rtp.extensions.clear();
-      send_config->rtp.extensions.push_back(RtpExtension(
-          RtpExtension::kAudioLevelUri, test::kAudioLevelExtensionId));
+      send_config->rtp.extensions.push_back(
+          RtpExtension(RtpExtension::kAudioLevelUri, kAudioLevelExtensionId));
     }
 
     void PerformTest() override {
@@ -137,42 +147,54 @@
   RunBaseTest(&test);
 }
 
-TEST_F(AudioSendStreamCallTest, SupportsTransportWideSequenceNumbers) {
-  static const uint8_t kExtensionId = test::kTransportSequenceNumberExtensionId;
-  class TransportWideSequenceNumberObserver : public AudioSendTest {
-   public:
-    TransportWideSequenceNumberObserver() : AudioSendTest() {
-      EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
-          kRtpExtensionTransportSequenceNumber, kExtensionId));
-    }
+class TransportWideSequenceNumberObserver : public AudioSendTest {
+ public:
+  explicit TransportWideSequenceNumberObserver(bool expect_sequence_number)
+      : AudioSendTest(), expect_sequence_number_(expect_sequence_number) {
+    EXPECT_TRUE(parser_->RegisterRtpHeaderExtension(
+        kRtpExtensionTransportSequenceNumber,
+        kTransportSequenceNumberExtensionId));
+  }
 
-   private:
-    Action OnSendRtp(const uint8_t* packet, size_t length) override {
-      RTPHeader header;
-      EXPECT_TRUE(parser_->Parse(packet, length, &header));
+ private:
+  Action OnSendRtp(const uint8_t* packet, size_t length) override {
+    RTPHeader header;
+    EXPECT_TRUE(parser_->Parse(packet, length, &header));
 
-      EXPECT_TRUE(header.extension.hasTransportSequenceNumber);
-      EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
-      EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
+    EXPECT_EQ(header.extension.hasTransportSequenceNumber,
+              expect_sequence_number_);
+    EXPECT_FALSE(header.extension.hasTransmissionTimeOffset);
+    EXPECT_FALSE(header.extension.hasAbsoluteSendTime);
 
-      observation_complete_.Set();
+    observation_complete_.Set();
 
-      return SEND_PACKET;
-    }
+    return SEND_PACKET;
+  }
 
-    void ModifyAudioConfigs(
-        AudioSendStream::Config* send_config,
-        std::vector<AudioReceiveStream::Config>* receive_configs) override {
-      send_config->rtp.extensions.clear();
-      send_config->rtp.extensions.push_back(RtpExtension(
-          RtpExtension::kTransportSequenceNumberUri, kExtensionId));
-    }
+  void ModifyAudioConfigs(
+      AudioSendStream::Config* send_config,
+      std::vector<AudioReceiveStream::Config>* receive_configs) override {
+    send_config->rtp.extensions.clear();
+    send_config->rtp.extensions.push_back(
+        RtpExtension(RtpExtension::kTransportSequenceNumberUri,
+                     kTransportSequenceNumberExtensionId));
+  }
 
-    void PerformTest() override {
-      EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
-    }
-  } test;
+  void PerformTest() override {
+    EXPECT_TRUE(Wait()) << "Timed out while waiting for a single RTP packet.";
+  }
+  const bool expect_sequence_number_;
+};
 
+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);
 }
 
diff --git a/audio/audio_send_stream_unittest.cc b/audio/audio_send_stream_unittest.cc
index e400ada..ddd8137 100644
--- a/audio/audio_send_stream_unittest.cc
+++ b/audio/audio_send_stream_unittest.cc
@@ -28,6 +28,8 @@
 #include "modules/rtp_rtcp/mocks/mock_rtcp_rtt_stats.h"
 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
 #include "rtc_base/task_queue.h"
+#include "system_wrappers/include/clock.h"
+#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/mock_audio_encoder.h"
 #include "test/mock_audio_encoder_factory.h"
@@ -61,7 +63,6 @@
 const int kTelephoneEventPayloadFrequency = 65432;
 const int kTelephoneEventCode = 45;
 const int kTelephoneEventDuration = 6789;
-const CodecInst kIsacCodec = {103, "isac", 16000, 320, 1, 32000};
 constexpr int kIsacPayloadType = 103;
 const SdpAudioFormat kIsacFormat = {"isac", 16000, 1};
 const SdpAudioFormat kOpusFormat = {"opus", 48000, 2};
@@ -73,12 +74,10 @@
 
 class MockLimitObserver : public BitrateAllocator::LimitObserver {
  public:
-  MOCK_METHOD5(OnAllocationLimitsChanged,
+  MOCK_METHOD3(OnAllocationLimitsChanged,
                void(uint32_t min_send_bitrate_bps,
                     uint32_t max_padding_bitrate_bps,
-                    uint32_t total_bitrate_bps,
-                    uint32_t allocated_without_feedback_bps,
-                    bool has_packet_feedback));
+                    uint32_t total_bitrate_bps));
 };
 
 std::unique_ptr<MockAudioEncoder> SetupAudioEncoderMock(
@@ -127,9 +126,10 @@
 
 struct ConfigHelper {
   ConfigHelper(bool audio_bwe_enabled, bool expect_set_encoder_call)
-      : stream_config_(/*send_transport=*/nullptr, /*media_transport=*/nullptr),
+      : clock_(1000000),
+        stream_config_(/*send_transport=*/nullptr, /*media_transport=*/nullptr),
         audio_processing_(new rtc::RefCountedObject<MockAudioProcessing>()),
-        bitrate_allocator_(&limit_observer_),
+        bitrate_allocator_(&clock_, &limit_observer_),
         worker_queue_("ConfigHelper_worker_queue"),
         audio_encoder_(nullptr) {
     using testing::Invoke;
@@ -163,8 +163,9 @@
   std::unique_ptr<internal::AudioSendStream> CreateAudioSendStream() {
     return std::unique_ptr<internal::AudioSendStream>(
         new internal::AudioSendStream(
-            stream_config_, audio_state_, &worker_queue_, &rtp_transport_,
-            &bitrate_allocator_, &event_log_, &rtcp_rtt_stats_, absl::nullopt,
+            Clock::GetRealTimeClock(), stream_config_, audio_state_,
+            &worker_queue_, &rtp_transport_, &bitrate_allocator_, &event_log_,
+            &rtcp_rtt_stats_, absl::nullopt,
             std::unique_ptr<voe::ChannelSendInterface>(channel_send_)));
   }
 
@@ -211,6 +212,7 @@
           .Times(1);
     }
     EXPECT_CALL(*channel_send_, ResetSenderCongestionControlObjects()).Times(1);
+    EXPECT_CALL(*channel_send_, SetRid(std::string(), 0, 0)).Times(1);
   }
 
   void SetupMockForSetupSendCodec(bool expect_set_encoder_call) {
@@ -224,15 +226,14 @@
     }
   }
 
-  void SetupMockForModifyEncoder() {
+  void SetupMockForCallEncoder() {
     // Let ModifyEncoder to invoke mock audio encoder.
-    EXPECT_CALL(*channel_send_, ModifyEncoder(_))
-        .WillRepeatedly(Invoke(
-            [this](rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
-                       modifier) {
+    EXPECT_CALL(*channel_send_, CallEncoder(_))
+        .WillRepeatedly(
+            [this](rtc::FunctionView<void(AudioEncoder*)> modifier) {
               if (this->audio_encoder_)
-                modifier(&this->audio_encoder_);
-            }));
+                modifier(this->audio_encoder_.get());
+            });
   }
 
   void SetupMockForSendTelephoneEvent() {
@@ -285,6 +286,7 @@
   }
 
  private:
+  SimulatedClock clock_;
   rtc::scoped_refptr<AudioState> audio_state_;
   AudioSendStream::Config stream_config_;
   testing::StrictMock<MockChannelSend>* channel_send_ = nullptr;
@@ -356,6 +358,7 @@
 }
 
 TEST(AudioSendStreamTest, AudioBweCorrectObjectsOnChannelProxy) {
+  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   ConfigHelper helper(true, true);
   auto send_stream = helper.CreateAudioSendStream();
 }
@@ -375,11 +378,11 @@
   EXPECT_EQ(kCallStats.packetsSent, stats.packets_sent);
   EXPECT_EQ(kReportBlock.cumulative_num_packets_lost, stats.packets_lost);
   EXPECT_EQ(Q8ToFloat(kReportBlock.fraction_lost), stats.fraction_lost);
-  EXPECT_EQ(std::string(kIsacCodec.plname), stats.codec_name);
+  EXPECT_EQ(kIsacFormat.name, stats.codec_name);
   EXPECT_EQ(static_cast<int32_t>(kReportBlock.extended_highest_sequence_number),
             stats.ext_seqnum);
   EXPECT_EQ(static_cast<int32_t>(kReportBlock.interarrival_jitter /
-                                 (kIsacCodec.plfreq / 1000)),
+                                 (kIsacFormat.clockrate_hz / 1000)),
             stats.jitter_ms);
   EXPECT_EQ(kCallStats.rttMs, stats.rtt_ms);
   EXPECT_EQ(0, stats.audio_level);
@@ -428,7 +431,7 @@
   auto stream_config = helper.config();
   stream_config.audio_network_adaptor_config = kAnaReconfigString;
 
-  helper.SetupMockForModifyEncoder();
+  helper.SetupMockForCallEncoder();
   send_stream->Reconfigure(stream_config);
 }
 
@@ -507,6 +510,7 @@
 }
 
 TEST(AudioSendStreamTest, ReconfigureTransportCcResetsFirst) {
+  ScopedFieldTrials field_trials("WebRTC-Audio-SendSideBwe/Enabled/");
   ConfigHelper helper(false, true);
   auto send_stream = helper.CreateAudioSendStream();
   auto new_config = helper.config();
@@ -522,9 +526,61 @@
                                             helper.transport(), Ne(nullptr)))
         .Times(1);
   }
+
+  // CallEncoder will be called to re-set overhead.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(1);
+
   send_stream->Reconfigure(new_config);
 }
 
+TEST(AudioSendStreamTest, OnTransportOverheadChanged) {
+  ConfigHelper helper(false, true);
+  auto send_stream = helper.CreateAudioSendStream();
+  auto new_config = helper.config();
+
+  // CallEncoder will be called on overhead change.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(1);
+
+  const size_t transport_overhead_per_packet_bytes = 333;
+  send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
+
+  EXPECT_EQ(transport_overhead_per_packet_bytes,
+            send_stream->TestOnlyGetPerPacketOverheadBytes());
+}
+
+TEST(AudioSendStreamTest, OnAudioOverheadChanged) {
+  ConfigHelper helper(false, true);
+  auto send_stream = helper.CreateAudioSendStream();
+  auto new_config = helper.config();
+
+  // CallEncoder will be called on overhead change.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(1);
+
+  const size_t audio_overhead_per_packet_bytes = 555;
+  send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
+  EXPECT_EQ(audio_overhead_per_packet_bytes,
+            send_stream->TestOnlyGetPerPacketOverheadBytes());
+}
+
+TEST(AudioSendStreamTest, OnAudioAndTransportOverheadChanged) {
+  ConfigHelper helper(false, true);
+  auto send_stream = helper.CreateAudioSendStream();
+  auto new_config = helper.config();
+
+  // CallEncoder will be called when each of overhead changes.
+  EXPECT_CALL(*helper.channel_send(), CallEncoder(testing::_)).Times(2);
+
+  const size_t transport_overhead_per_packet_bytes = 333;
+  send_stream->SetTransportOverhead(transport_overhead_per_packet_bytes);
+
+  const size_t audio_overhead_per_packet_bytes = 555;
+  send_stream->OnOverheadChanged(audio_overhead_per_packet_bytes);
+
+  EXPECT_EQ(
+      transport_overhead_per_packet_bytes + audio_overhead_per_packet_bytes,
+      send_stream->TestOnlyGetPerPacketOverheadBytes());
+}
+
 // Validates that reconfiguring the AudioSendStream with a Frame encryptor
 // correctly reconfigures on the object without crashing.
 TEST(AudioSendStreamTest, ReconfigureWithFrameEncryptor) {
diff --git a/audio/audio_state.cc b/audio/audio_state.cc
index 7d473ae..334eaed 100644
--- a/audio/audio_state.cc
+++ b/audio/audio_state.cc
@@ -17,9 +17,9 @@
 #include "absl/memory/memory.h"
 #include "audio/audio_receive_stream.h"
 #include "modules/audio_device/include/audio_device.h"
-#include "rtc_base/atomicops.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/thread.h"
 
 namespace webrtc {
@@ -168,20 +168,6 @@
   audio_transport_.SetStereoChannelSwapping(enable);
 }
 
-// Reference count; implementation copied from rtc::RefCountedObject.
-void AudioState::AddRef() const {
-  rtc::AtomicOps::Increment(&ref_count_);
-}
-
-// Reference count; implementation copied from rtc::RefCountedObject.
-rtc::RefCountReleaseStatus AudioState::Release() const {
-  if (rtc::AtomicOps::Decrement(&ref_count_) == 0) {
-    delete this;
-    return rtc::RefCountReleaseStatus::kDroppedLastRef;
-  }
-  return rtc::RefCountReleaseStatus::kOtherRefsRemained;
-}
-
 void AudioState::UpdateAudioTransportWithSendingStreams() {
   RTC_DCHECK(thread_checker_.CalledOnValidThread());
   std::vector<webrtc::AudioSendStream*> sending_streams;
@@ -199,6 +185,6 @@
 
 rtc::scoped_refptr<AudioState> AudioState::Create(
     const AudioState::Config& config) {
-  return rtc::scoped_refptr<AudioState>(new internal::AudioState(config));
+  return new rtc::RefCountedObject<internal::AudioState>(config);
 }
 }  // namespace webrtc
diff --git a/audio/audio_state.h b/audio/audio_state.h
index 9e302c4..60250da 100644
--- a/audio/audio_state.h
+++ b/audio/audio_state.h
@@ -18,9 +18,9 @@
 #include "audio/audio_transport_impl.h"
 #include "audio/null_audio_poller.h"
 #include "call/audio_state.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/refcount.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
+#include "rtc_base/ref_count.h"
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
@@ -30,7 +30,7 @@
 
 namespace internal {
 
-class AudioState final : public webrtc::AudioState {
+class AudioState : public webrtc::AudioState {
  public:
   explicit AudioState(const AudioState::Config& config);
   ~AudioState() override;
@@ -60,10 +60,6 @@
   void RemoveSendingStream(webrtc::AudioSendStream* stream);
 
  private:
-  // rtc::RefCountInterface implementation.
-  void AddRef() const override;
-  rtc::RefCountReleaseStatus Release() const override;
-
   void UpdateAudioTransportWithSendingStreams();
 
   rtc::ThreadChecker thread_checker_;
@@ -72,10 +68,6 @@
   bool recording_enabled_ = true;
   bool playout_enabled_ = true;
 
-  // Reference count; implementation copied from rtc::RefCountedObject.
-  // TODO(nisse): Use RefCountedObject or RefCountedBase instead.
-  mutable volatile int ref_count_ = 0;
-
   // Transports mixed audio from the mixer to the audio device and
   // recorded audio to the sending streams.
   AudioTransportImpl audio_transport_;
diff --git a/audio/audio_state_unittest.cc b/audio/audio_state_unittest.cc
index dc622df..75bf4e1 100644
--- a/audio/audio_state_unittest.cc
+++ b/audio/audio_state_unittest.cc
@@ -16,7 +16,7 @@
 #include "modules/audio_device/include/mock_audio_device.h"
 #include "modules/audio_mixer/audio_mixer_impl.h"
 #include "modules/audio_processing/include/mock_audio_processing.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -98,14 +98,14 @@
 
 TEST(AudioStateTest, ConstructDestruct) {
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 }
 
 TEST(AudioStateTest, RecordedAudioArrivesAtSingleStream) {
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 
   MockAudioSendStream stream;
   audio_state->AddSendingStream(&stream, 8000, 2);
@@ -142,8 +142,8 @@
 
 TEST(AudioStateTest, RecordedAudioArrivesAtMultipleStreams) {
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 
   MockAudioSendStream stream_1;
   MockAudioSendStream stream_2;
@@ -196,8 +196,9 @@
   constexpr size_t kNumChannels = 2;
 
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
+
   audio_state->SetStereoChannelSwapping(true);
 
   MockAudioSendStream stream;
@@ -227,8 +228,8 @@
   constexpr size_t kNumChannels = 1;
 
   ConfigHelper helper;
-  std::unique_ptr<internal::AudioState> audio_state(
-      new internal::AudioState(helper.config()));
+  rtc::scoped_refptr<internal::AudioState> audio_state(
+      new rtc::RefCountedObject<internal::AudioState>(helper.config()));
 
   // Push a silent buffer -> Level stats should be zeros except for duration.
   {
diff --git a/audio/audio_transport_impl.cc b/audio/audio_transport_impl.cc
index 539456e..cdbdacd 100644
--- a/audio/audio_transport_impl.cc
+++ b/audio/audio_transport_impl.cc
@@ -133,9 +133,9 @@
 
   // Typing detection (utilizes the APM/VAD decision). We let the VAD determine
   // if we're using this feature or not.
-  // TODO(solenberg): is_enabled() takes a lock. Work around that.
+  // TODO(solenberg): GetConfig() takes a lock. Work around that.
   bool typing_detected = false;
-  if (audio_processing_->voice_detection()->is_enabled()) {
+  if (audio_processing_->GetConfig().voice_detection.enabled) {
     if (audio_frame->vad_activity_ != AudioFrame::kVadUnknown) {
       bool vad_active = audio_frame->vad_activity_ == AudioFrame::kVadActive;
       typing_detected = typing_detection_.Process(key_pressed, vad_active);
@@ -214,7 +214,6 @@
                                         int64_t* ntp_time_ms) {
   RTC_DCHECK_EQ(bits_per_sample, 16);
   RTC_DCHECK_GE(number_of_channels, 1);
-  RTC_DCHECK_LE(number_of_channels, 2);
   RTC_DCHECK_GE(sample_rate, AudioProcessing::NativeRate::kSampleRate8kHz);
 
   // 100 = 1 second / data duration (10 ms).
diff --git a/audio/audio_transport_impl.h b/audio/audio_transport_impl.h
index 3a3155c..4c244a1 100644
--- a/audio/audio_transport_impl.h
+++ b/audio/audio_transport_impl.h
@@ -14,14 +14,14 @@
 #include <vector>
 
 #include "api/audio/audio_mixer.h"
+#include "api/scoped_refptr.h"
 #include "audio/audio_level.h"
 #include "common_audio/resampler/include/push_resampler.h"
 #include "modules/audio_device/include/audio_device.h"
 #include "modules/audio_processing/include/audio_processing.h"
 #include "modules/audio_processing/typing_detection.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
index 483147f..79523c8 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -33,16 +33,17 @@
 #include "modules/rtp_rtcp/source/contributing_sources.h"
 #include "modules/rtp_rtcp/source/rtp_header_extensions.h"
 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
 #include "modules/utility/include/process_thread.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/format_macros.h"
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_minmax.h"
 #include "rtc_base/race_checker.h"
 #include "rtc_base/thread_checker.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
@@ -51,50 +52,32 @@
 namespace {
 
 constexpr double kAudioSampleDurationSeconds = 0.01;
-constexpr int64_t kMaxRetransmissionWindowMs = 1000;
-constexpr int64_t kMinRetransmissionWindowMs = 30;
 
 // Video Sync.
 constexpr int kVoiceEngineMinMinPlayoutDelayMs = 0;
 constexpr int kVoiceEngineMaxMinPlayoutDelayMs = 10000;
 
-webrtc::FrameType WebrtcFrameTypeForMediaTransportFrameType(
-    MediaTransportEncodedAudioFrame::FrameType frame_type) {
-  switch (frame_type) {
-    case MediaTransportEncodedAudioFrame::FrameType::kSpeech:
-      return kAudioFrameSpeech;
-      break;
-
-    case MediaTransportEncodedAudioFrame::FrameType::
-        kDiscountinuousTransmission:
-      return kAudioFrameCN;
-      break;
-  }
-}
-
-WebRtcRTPHeader CreateWebrtcRTPHeaderForMediaTransportFrame(
+RTPHeader CreateRTPHeaderForMediaTransportFrame(
     const MediaTransportEncodedAudioFrame& frame,
     uint64_t channel_id) {
-  webrtc::WebRtcRTPHeader webrtc_header = {};
-  webrtc_header.header.payloadType = frame.payload_type();
-  webrtc_header.header.payload_type_frequency = frame.sampling_rate_hz();
-  webrtc_header.header.timestamp = frame.starting_sample_index();
-  webrtc_header.header.sequenceNumber = frame.sequence_number();
+  webrtc::RTPHeader rtp_header;
+  rtp_header.payloadType = frame.payload_type();
+  rtp_header.payload_type_frequency = frame.sampling_rate_hz();
+  rtp_header.timestamp = frame.starting_sample_index();
+  rtp_header.sequenceNumber = frame.sequence_number();
 
-  webrtc_header.frameType =
-      WebrtcFrameTypeForMediaTransportFrameType(frame.frame_type());
-
-  webrtc_header.header.ssrc = static_cast<uint32_t>(channel_id);
+  rtp_header.ssrc = static_cast<uint32_t>(channel_id);
 
   // The rest are initialized by the RTPHeader constructor.
-  return webrtc_header;
+  return rtp_header;
 }
 
 class ChannelReceive : public ChannelReceiveInterface,
                        public MediaTransportAudioSinkInterface {
  public:
   // Used for receive streams.
-  ChannelReceive(ProcessThread* module_process_thread,
+  ChannelReceive(Clock* clock,
+                 ProcessThread* module_process_thread,
                  AudioDeviceModule* audio_device_module,
                  MediaTransportInterface* media_transport,
                  Transport* rtcp_send_transport,
@@ -103,6 +86,7 @@
                  size_t jitter_buffer_max_packets,
                  bool jitter_buffer_fast_playout,
                  int jitter_buffer_min_delay_ms,
+                 bool jitter_buffer_enable_rtx_handling,
                  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                  absl::optional<AudioCodecPairId> codec_pair_id,
                  rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
@@ -119,7 +103,8 @@
   void StopPlayout() override;
 
   // Codecs
-  bool GetRecCodec(CodecInst* codec) const override;
+  absl::optional<std::pair<int, SdpAudioFormat>>
+      GetReceiveCodec() const override;
 
   bool ReceivedRTCPPacket(const uint8_t* data, size_t length) override;
 
@@ -143,6 +128,10 @@
   void SetMinimumPlayoutDelay(int delayMs) override;
   uint32_t GetPlayoutTimestamp() const override;
 
+  // Audio quality.
+  bool SetBaseMinimumPlayoutDelayMs(int delay_ms) override;
+  int GetBaseMinimumPlayoutDelayMs() const override;
+
   // Produces the transport-related timestamps; current_delay_ms is left unset.
   absl::optional<Syncable::Info> GetSyncInfo() const override;
 
@@ -184,7 +173,7 @@
 
   int32_t OnReceivedPayloadData(const uint8_t* payloadData,
                                 size_t payloadSize,
-                                const WebRtcRTPHeader* rtpHeader);
+                                const RTPHeader& rtpHeader);
 
   bool Playing() const {
     rtc::CritScope lock(&playing_lock_);
@@ -272,10 +261,9 @@
   webrtc::CryptoOptions crypto_options_;
 };
 
-int32_t ChannelReceive::OnReceivedPayloadData(
-    const uint8_t* payloadData,
-    size_t payloadSize,
-    const WebRtcRTPHeader* rtpHeader) {
+int32_t ChannelReceive::OnReceivedPayloadData(const uint8_t* payloadData,
+                                              size_t payloadSize,
+                                              const RTPHeader& rtp_header) {
   // We should not be receiving any RTP packets if media_transport is set.
   RTC_CHECK(!media_transport_);
 
@@ -286,7 +274,7 @@
   }
 
   // Push the incoming payload (parsed and ready for decoding) into the ACM
-  if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
+  if (audio_coding_->IncomingPacket(payloadData, payloadSize, rtp_header) !=
       0) {
     RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to "
                           "push data to the ACM";
@@ -319,8 +307,7 @@
   // Send encoded audio frame to Decoder / NetEq.
   if (audio_coding_->IncomingPacket(
           frame.encoded_data().data(), frame.encoded_data().size(),
-          CreateWebrtcRTPHeaderForMediaTransportFrame(frame, channel_id)) !=
-      0) {
+          CreateRTPHeaderForMediaTransportFrame(frame, channel_id)) != 0) {
     RTC_DLOG(LS_ERROR) << "ChannelReceive::OnData: unable to "
                           "push data to the ACM";
   }
@@ -442,6 +429,7 @@
 }
 
 ChannelReceive::ChannelReceive(
+    Clock* clock,
     ProcessThread* module_process_thread,
     AudioDeviceModule* audio_device_module,
     MediaTransportInterface* media_transport,
@@ -451,16 +439,16 @@
     size_t jitter_buffer_max_packets,
     bool jitter_buffer_fast_playout,
     int jitter_buffer_min_delay_ms,
+    bool jitter_buffer_enable_rtx_handling,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
     const webrtc::CryptoOptions& crypto_options)
     : event_log_(rtc_event_log),
-      rtp_receive_statistics_(
-          ReceiveStatistics::Create(Clock::GetRealTimeClock())),
+      rtp_receive_statistics_(ReceiveStatistics::Create(clock)),
       remote_ssrc_(remote_ssrc),
       _outputAudioLevel(),
-      ntp_estimator_(Clock::GetRealTimeClock()),
+      ntp_estimator_(clock),
       playout_timestamp_rtp_(0),
       playout_delay_ms_(0),
       rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
@@ -485,12 +473,15 @@
   acm_config.neteq_config.enable_fast_accelerate = jitter_buffer_fast_playout;
   acm_config.neteq_config.min_delay_ms = jitter_buffer_min_delay_ms;
   acm_config.neteq_config.enable_muted_state = true;
+  acm_config.neteq_config.enable_rtx_handling =
+      jitter_buffer_enable_rtx_handling;
   audio_coding_.reset(AudioCodingModule::Create(acm_config));
 
   _outputAudioLevel.Clear();
 
   rtp_receive_statistics_->EnableRetransmitDetection(remote_ssrc_, true);
   RtpRtcp::Configuration configuration;
+  configuration.clock = clock;
   configuration.audio = true;
   configuration.receiver_only = true;
   configuration.outgoing_transport = rtcp_send_transport;
@@ -552,9 +543,10 @@
   _outputAudioLevel.Clear();
 }
 
-bool ChannelReceive::GetRecCodec(CodecInst* codec) const {
+absl::optional<std::pair<int, SdpAudioFormat>>
+    ChannelReceive::GetReceiveCodec() const {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
-  return (audio_coding_->ReceiveCodec(codec) == 0);
+  return audio_coding_->ReceiveCodec();
 }
 
 std::vector<webrtc::RtpSource> ChannelReceive::GetSources() const {
@@ -628,8 +620,6 @@
   const uint8_t* payload = packet + header.headerLength;
   assert(packet_length >= header.headerLength);
   size_t payload_length = packet_length - header.headerLength;
-  WebRtcRTPHeader webrtc_rtp_header = {};
-  webrtc_rtp_header.header = header;
 
   size_t payload_data_length = payload_length - header.paddingLength;
 
@@ -668,11 +658,9 @@
   }
 
   if (payload_data_length == 0) {
-    webrtc_rtp_header.frameType = kEmptyFrame;
-    return OnReceivedPayloadData(nullptr, 0, &webrtc_rtp_header);
+    return OnReceivedPayloadData(nullptr, 0, header);
   }
-  return OnReceivedPayloadData(payload, payload_data_length,
-                               &webrtc_rtp_header);
+  return OnReceivedPayloadData(payload, payload_data_length, header);
 }
 
 // May be called on either worker thread or network thread.
@@ -690,13 +678,6 @@
     return true;
   }
 
-  int64_t nack_window_ms = rtt;
-  if (nack_window_ms < kMinRetransmissionWindowMs) {
-    nack_window_ms = kMinRetransmissionWindowMs;
-  } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
-    nack_window_ms = kMaxRetransmissionWindowMs;
-  }
-
   uint32_t ntp_secs = 0;
   uint32_t ntp_frac = 0;
   uint32_t rtp_timestamp = 0;
@@ -802,11 +783,14 @@
 void ChannelReceive::SetNACKStatus(bool enable, int max_packets) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
   // None of these functions can fail.
-  rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets);
-  if (enable)
+  if (enable) {
+    rtp_receive_statistics_->SetMaxReorderingThreshold(max_packets);
     audio_coding_->EnableNack(max_packets);
-  else
+  } else {
+    rtp_receive_statistics_->SetMaxReorderingThreshold(
+        kDefaultMaxReorderingThreshold);
     audio_coding_->DisableNack();
+  }
 }
 
 // Called when we are missing one or more packets.
@@ -848,12 +832,8 @@
   RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
   // Limit to range accepted by both VoE and ACM, so we're at least getting as
   // close as possible, instead of failing.
-  delay_ms = rtc::SafeClamp(delay_ms, 0, 10000);
-  if ((delay_ms < kVoiceEngineMinMinPlayoutDelayMs) ||
-      (delay_ms > kVoiceEngineMaxMinPlayoutDelayMs)) {
-    RTC_DLOG(LS_ERROR) << "SetMinimumPlayoutDelay() invalid min delay";
-    return;
-  }
+  delay_ms = rtc::SafeClamp(delay_ms, kVoiceEngineMinMinPlayoutDelayMs,
+                            kVoiceEngineMaxMinPlayoutDelayMs);
   if (audio_coding_->SetMinimumPlayoutDelay(delay_ms) != 0) {
     RTC_DLOG(LS_ERROR)
         << "SetMinimumPlayoutDelay() failed to set min playout delay";
@@ -868,6 +848,14 @@
   }
 }
 
+bool ChannelReceive::SetBaseMinimumPlayoutDelayMs(int delay_ms) {
+  return audio_coding_->SetBaseMinimumPlayoutDelayMs(delay_ms);
+}
+
+int ChannelReceive::GetBaseMinimumPlayoutDelayMs() const {
+  return audio_coding_->GetBaseMinimumPlayoutDelayMs();
+}
+
 absl::optional<Syncable::Info> ChannelReceive::GetSyncInfo() const {
   RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
   Syncable::Info info;
@@ -920,13 +908,13 @@
 }
 
 int ChannelReceive::GetRtpTimestampRateHz() const {
-  const auto format = audio_coding_->ReceiveFormat();
+  const auto decoder = audio_coding_->ReceiveCodec();
   // Default to the playout frequency if we've not gotten any packets yet.
   // TODO(ossu): Zero clockrate can only happen if we've added an external
   // decoder for a format we don't support internally. Remove once that way of
   // adding decoders is gone!
-  return (format && format->clockrate_hz != 0)
-             ? format->clockrate_hz
+  return (decoder && decoder->second.clockrate_hz != 0)
+             ? decoder->second.clockrate_hz
              : audio_coding_->PlayoutFrequency();
 }
 
@@ -973,6 +961,7 @@
 }  // namespace
 
 std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
+    Clock* clock,
     ProcessThread* module_process_thread,
     AudioDeviceModule* audio_device_module,
     MediaTransportInterface* media_transport,
@@ -982,16 +971,17 @@
     size_t jitter_buffer_max_packets,
     bool jitter_buffer_fast_playout,
     int jitter_buffer_min_delay_ms,
+    bool jitter_buffer_enable_rtx_handling,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
     const webrtc::CryptoOptions& crypto_options) {
   return absl::make_unique<ChannelReceive>(
-      module_process_thread, audio_device_module, media_transport,
+      clock, module_process_thread, audio_device_module, media_transport,
       rtcp_send_transport, rtc_event_log, remote_ssrc,
       jitter_buffer_max_packets, jitter_buffer_fast_playout,
-      jitter_buffer_min_delay_ms, decoder_factory, codec_pair_id,
-      frame_decryptor, crypto_options);
+      jitter_buffer_min_delay_ms, jitter_buffer_enable_rtx_handling,
+      decoder_factory, codec_pair_id, frame_decryptor, crypto_options);
 }
 
 }  // namespace voe
diff --git a/audio/channel_receive.h b/audio/channel_receive.h
index 9027623..b3e4f9c 100644
--- a/audio/channel_receive.h
+++ b/audio/channel_receive.h
@@ -13,6 +13,7 @@
 
 #include <map>
 #include <memory>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
@@ -20,9 +21,9 @@
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/call/audio_sink.h"
 #include "api/call/transport.h"
-#include "api/crypto/cryptooptions.h"
+#include "api/crypto/crypto_options.h"
 #include "api/media_transport_interface.h"
-#include "api/rtpreceiverinterface.h"
+#include "api/rtp_receiver_interface.h"
 #include "call/rtp_packet_sink_interface.h"
 #include "call/syncable.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
@@ -79,7 +80,9 @@
   virtual void StartPlayout() = 0;
   virtual void StopPlayout() = 0;
 
-  virtual bool GetRecCodec(CodecInst* codec) const = 0;
+  // Payload type and format of last received RTP packet, if any.
+  virtual absl::optional<std::pair<int, SdpAudioFormat>>
+      GetReceiveCodec() const = 0;
 
   virtual bool ReceivedRTCPPacket(const uint8_t* data, size_t length) = 0;
 
@@ -99,6 +102,12 @@
   virtual void SetMinimumPlayoutDelay(int delay_ms) = 0;
   virtual uint32_t GetPlayoutTimestamp() const = 0;
 
+  // Audio quality.
+  // Base minimum delay sets lower bound on minimum delay value which
+  // determines minimum delay until audio playout.
+  virtual bool SetBaseMinimumPlayoutDelayMs(int delay_ms) = 0;
+  virtual int GetBaseMinimumPlayoutDelayMs() const = 0;
+
   // Produces the transport-related timestamps; current_delay_ms is left unset.
   virtual absl::optional<Syncable::Info> GetSyncInfo() const = 0;
 
@@ -127,6 +136,7 @@
 };
 
 std::unique_ptr<ChannelReceiveInterface> CreateChannelReceive(
+    Clock* clock,
     ProcessThread* module_process_thread,
     AudioDeviceModule* audio_device_module,
     MediaTransportInterface* media_transport,
@@ -136,6 +146,7 @@
     size_t jitter_buffer_max_packets,
     bool jitter_buffer_fast_playout,
     int jitter_buffer_min_delay_ms,
+    bool jitter_buffer_enable_rtx_handling,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
     absl::optional<AudioCodecPairId> codec_pair_id,
     rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor,
diff --git a/audio/channel_send.cc b/audio/channel_send.cc
index c458fe4..0c8be1f 100644
--- a/audio/channel_send.cc
+++ b/audio/channel_send.cc
@@ -20,7 +20,7 @@
 #include "absl/memory/memory.h"
 #include "api/array_view.h"
 #include "api/call/transport.h"
-#include "api/crypto/frameencryptorinterface.h"
+#include "api/crypto/frame_encryptor_interface.h"
 #include "audio/utility/audio_frame_operations.h"
 #include "call/rtp_transport_controller_send_interface.h"
 #include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
@@ -31,7 +31,7 @@
 #include "modules/pacing/packet_router.h"
 #include "modules/utility/include/process_thread.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
 #include "rtc_base/format_macros.h"
 #include "rtc_base/location.h"
@@ -41,7 +41,8 @@
 #include "rtc_base/rate_limiter.h"
 #include "rtc_base/task_queue.h"
 #include "rtc_base/thread_checker.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
+#include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/field_trial.h"
 #include "system_wrappers/include/metrics.h"
 
@@ -78,8 +79,6 @@
 
 class ChannelSend
     : public ChannelSendInterface,
-      public Transport,
-      public OverheadObserver,
       public AudioPacketizationCallback,  // receive encoded packets from the
                                           // ACM
       public TargetTransferRateObserver {
@@ -88,9 +87,11 @@
   // declaration.
   friend class VoERtcpObserver;
 
-  ChannelSend(rtc::TaskQueue* encoder_queue,
+  ChannelSend(Clock* clock,
+              rtc::TaskQueue* encoder_queue,
               ProcessThread* module_process_thread,
               MediaTransportInterface* media_transport,
+              OverheadObserver* overhead_observer,
               Transport* rtp_transport,
               RtcpRttStats* rtcp_rtt_stats,
               RtcEventLog* rtc_event_log,
@@ -106,6 +107,7 @@
                   std::unique_ptr<AudioEncoder> encoder) override;
   void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
                          modifier) override;
+  void CallEncoder(rtc::FunctionView<void(AudioEncoder*)> modifier) override;
 
   // API methods
   void StartSend() override;
@@ -134,6 +136,9 @@
 
   // RTP+RTCP
   void SetLocalSSRC(uint32_t ssrc) override;
+  void SetRid(const std::string& rid,
+              int extension_id,
+              int repaired_extension_id) override;
   void SetMid(const std::string& mid, int extension_id) override;
   void SetExtmapAllowMixed(bool extmap_allow_mixed) override;
   void SetSendAudioLevelIndicationStatus(bool enable, int id) override;
@@ -158,8 +163,6 @@
   // packet.
   void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame) override;
 
-  void SetTransportOverhead(size_t transport_overhead_per_packet) override;
-
   // The existence of this function alongside OnUplinkPacketLossRate is
   // a compromise. We want the encoder to be agnostic of the PLR source, but
   // we also don't want it to receive conflicting information from TWCC and
@@ -186,23 +189,11 @@
                    size_t payloadSize,
                    const RTPFragmentationHeader* fragmentation) override;
 
-  // From Transport (called by the RTP/RTCP module)
-  bool SendRtp(const uint8_t* data,
-               size_t len,
-               const PacketOptions& packet_options) override;
-  bool SendRtcp(const uint8_t* data, size_t len) override;
-
-  // From OverheadObserver in the RTP/RTCP module
-  void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
-
   void OnUplinkPacketLossRate(float packet_loss_rate);
   bool InputMute() const;
 
   int SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, int id);
 
-  void UpdateOverheadForEncoder()
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
-
   int32_t SendRtpAudio(FrameType frameType,
                        uint8_t payloadType,
                        uint32_t timeStamp,
@@ -238,7 +229,6 @@
   // audio thread to another, but access is still sequential.
   rtc::RaceChecker audio_thread_race_checker_;
 
-  rtc::CriticalSection _callbackCritSect;
   rtc::CriticalSection volume_settings_critsect_;
 
   bool sending_ RTC_GUARDED_BY(&worker_thread_checker_) = false;
@@ -250,11 +240,8 @@
   std::unique_ptr<AudioCodingModule> audio_coding_;
   uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_);
 
-  uint16_t send_sequence_number_;
-
   // uses
   ProcessThread* const _moduleProcessThreadPtr;
-  Transport* const _transportPtr;  // WebRtc socket or external transport
   RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_);
   bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_);
   bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_);
@@ -262,10 +249,7 @@
   // TODO(henrika): can today be accessed on the main thread and on the
   // task queue; hence potential race.
   bool _includeAudioLevelIndication;
-  size_t transport_overhead_per_packet_
-      RTC_GUARDED_BY(overhead_per_packet_lock_);
-  size_t rtp_overhead_per_packet_ RTC_GUARDED_BY(overhead_per_packet_lock_);
-  rtc::CriticalSection overhead_per_packet_lock_;
+
   // RtcpBandwidthObserver
   const std::unique_ptr<VoERtcpObserver> rtcp_observer_;
 
@@ -416,7 +400,7 @@
  public:
   explicit VoERtcpObserver(ChannelSend* owner)
       : owner_(owner), bandwidth_observer_(nullptr) {}
-  virtual ~VoERtcpObserver() {}
+  ~VoERtcpObserver() override {}
 
   void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
     rtc::CritScope lock(&crit_);
@@ -515,6 +499,12 @@
   rtc::ArrayView<const uint8_t> payload(payloadData, payloadSize);
 
   if (media_transport() != nullptr) {
+    if (frameType == kEmptyFrame) {
+      // TODO(bugs.webrtc.org/9719): Media transport Send doesn't support
+      // sending empty frames.
+      return 0;
+    }
+
     return SendMediaTransportAudio(frameType, payloadType, timeStamp, payload,
                                    fragmentation);
   } else {
@@ -606,7 +596,7 @@
     sampling_rate_hz = media_transport_sampling_frequency_;
     channel_id = media_transport_channel_id_;
   }
-  const MediaTransportEncodedAudioFrame frame(
+  MediaTransportEncodedAudioFrame frame(
       /*sampling_rate_hz=*/sampling_rate_hz,
 
       // TODO(nisse): Timestamp and sample index are the same for all supported
@@ -641,48 +631,11 @@
   return 0;
 }
 
-bool ChannelSend::SendRtp(const uint8_t* data,
-                          size_t len,
-                          const PacketOptions& options) {
-  // We should not be sending RTP packets if media transport is available.
-  RTC_CHECK(!media_transport());
-
-  rtc::CritScope cs(&_callbackCritSect);
-
-  if (_transportPtr == NULL) {
-    RTC_DLOG(LS_ERROR)
-        << "ChannelSend::SendPacket() failed to send RTP packet due to"
-        << " invalid transport object";
-    return false;
-  }
-
-  if (!_transportPtr->SendRtp(data, len, options)) {
-    RTC_DLOG(LS_ERROR) << "ChannelSend::SendPacket() RTP transmission failed";
-    return false;
-  }
-  return true;
-}
-
-bool ChannelSend::SendRtcp(const uint8_t* data, size_t len) {
-  rtc::CritScope cs(&_callbackCritSect);
-  if (_transportPtr == NULL) {
-    RTC_DLOG(LS_ERROR)
-        << "ChannelSend::SendRtcp() failed to send RTCP packet due to"
-        << " invalid transport object";
-    return false;
-  }
-
-  int n = _transportPtr->SendRtcp(data, len);
-  if (n < 0) {
-    RTC_DLOG(LS_ERROR) << "ChannelSend::SendRtcp() transmission failed";
-    return false;
-  }
-  return true;
-}
-
-ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue,
+ChannelSend::ChannelSend(Clock* clock,
+                         rtc::TaskQueue* encoder_queue,
                          ProcessThread* module_process_thread,
                          MediaTransportInterface* media_transport,
+                         OverheadObserver* overhead_observer,
                          Transport* rtp_transport,
                          RtcpRttStats* rtcp_rtt_stats,
                          RtcEventLog* rtc_event_log,
@@ -693,20 +646,16 @@
     : event_log_(rtc_event_log),
       _timeStamp(0),  // This is just an offset, RTP module will add it's own
                       // random offset
-      send_sequence_number_(0),
       _moduleProcessThreadPtr(module_process_thread),
-      _transportPtr(rtp_transport),
       input_mute_(false),
       previous_frame_muted_(false),
       _includeAudioLevelIndication(false),
-      transport_overhead_per_packet_(0),
-      rtp_overhead_per_packet_(0),
       rtcp_observer_(new VoERtcpObserver(this)),
       feedback_observer_proxy_(new TransportFeedbackProxy()),
       seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
       rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
-      retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
-                                                   kMaxRetransmissionWindowMs)),
+      retransmission_rate_limiter_(
+          new RateLimiter(clock, kMaxRetransmissionWindowMs)),
       use_twcc_plr_for_ana_(
           webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"),
       encoder_queue_(encoder_queue),
@@ -726,13 +675,19 @@
   // RTPMediaTransport. In this case it means that overhead and bandwidth
   // observers should not be called when using media transport.
   if (!media_transport_) {
-    configuration.overhead_observer = this;
+    // TODO(sukhanov): Overhead observer is only needed for RTP path, because in
+    // media transport audio overhead is currently considered constant (see
+    // getter MediaTransportInterface::GetAudioPacketOverhead).  In the future
+    // when we introduce RTP media transport we should make audio overhead
+    // interface consistent and work for both RTP and non-RTP implementations.
+    configuration.overhead_observer = overhead_observer;
     configuration.bandwidth_callback = rtcp_observer_.get();
     configuration.transport_feedback_callback = feedback_observer_proxy_.get();
   }
 
+  configuration.clock = clock;
   configuration.audio = true;
-  configuration.outgoing_transport = this;
+  configuration.outgoing_transport = rtp_transport;
 
   configuration.paced_sender = rtp_packet_sender_proxy_.get();
   configuration.transport_sequence_number_allocator =
@@ -753,7 +708,6 @@
   if (media_transport_) {
     RTC_DLOG(LS_INFO) << "Setting media_transport_ rate observers.";
     media_transport_->AddTargetTransferRateObserver(this);
-    OnOverheadChanged(media_transport_->GetAudioPacketOverhead());
   } else {
     RTC_DLOG(LS_INFO) << "Not setting media_transport_ rate observers.";
   }
@@ -780,7 +734,6 @@
   }
 
   StopSend();
-
   int error = audio_coding_->RegisterTransportCallback(NULL);
   RTC_DCHECK_EQ(0, error);
 
@@ -793,11 +746,6 @@
   RTC_DCHECK(!sending_);
   sending_ = true;
 
-  // Resume the previous sequence number which was reset by StopSend(). This
-  // needs to be done before |sending| is set to true on the RTP/RTCP module.
-  if (send_sequence_number_) {
-    _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
-  }
   _rtpRtcpModule->SetSendingMediaStatus(true);
   int ret = _rtpRtcpModule->SetSendingStatus(true);
   RTC_DCHECK_EQ(0, ret);
@@ -833,14 +781,6 @@
   }
   flush.Wait(rtc::Event::kForever);
 
-  // Store the sequence number to be able to pick up the same sequence for
-  // the next StartSend(). This is needed for restarting device, otherwise
-  // it might cause libSRTP to complain about packets being replayed.
-  // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
-  // CL is landed. See issue
-  // https://code.google.com/p/webrtc/issues/detail?id=2111 .
-  send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
-
   // Reset sending SSRC and sequence number and triggers direct transmission
   // of RTCP BYE
   if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
@@ -854,33 +794,14 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   RTC_DCHECK_GE(payload_type, 0);
   RTC_DCHECK_LE(payload_type, 127);
-  // TODO(ossu): Make CodecInsts up, for now: one for the RTP/RTCP module and
-  // one for for us to keep track of sample rate and number of channels, etc.
 
   // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
   // as well as some other things, so we collect this info and send it along.
-  CodecInst rtp_codec;
-  rtp_codec.pltype = payload_type;
-  strncpy(rtp_codec.plname, "audio", sizeof(rtp_codec.plname));
-  rtp_codec.plname[sizeof(rtp_codec.plname) - 1] = 0;
-  // Seems unclear if it should be clock rate or sample rate. CodecInst
-  // supposedly carries the sample rate, but only clock rate seems sensible to
-  // send to the RTP/RTCP module.
-  rtp_codec.plfreq = encoder->RtpTimestampRateHz();
-  rtp_codec.pacsize = rtc::CheckedDivExact(
-      static_cast<int>(encoder->Max10MsFramesInAPacket() * rtp_codec.plfreq),
-      100);
-  rtp_codec.channels = encoder->NumChannels();
-  rtp_codec.rate = 0;
-
-  if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
-    _rtpRtcpModule->DeRegisterSendPayload(payload_type);
-    if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
-      RTC_DLOG(LS_ERROR)
-          << "SetEncoder() failed to register codec to RTP/RTCP module";
-      return false;
-    }
-  }
+  _rtpRtcpModule->RegisterAudioSendPayload(payload_type,
+                                           "audio",
+                                           encoder->RtpTimestampRateHz(),
+                                           encoder->NumChannels(),
+                                           0);
 
   if (media_transport_) {
     rtc::CritScope cs(&media_transport_lock_);
@@ -895,10 +816,22 @@
 
 void ChannelSend::ModifyEncoder(
     rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
-  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  // This method can be called on the worker thread, module process thread
+  // or network thread. Audio coding is thread safe, so we do not need to
+  // enforce the calling thread.
   audio_coding_->ModifyEncoder(modifier);
 }
 
+void ChannelSend::CallEncoder(rtc::FunctionView<void(AudioEncoder*)> modifier) {
+  ModifyEncoder([modifier](std::unique_ptr<AudioEncoder>* encoder_ptr) {
+    if (*encoder_ptr) {
+      modifier(encoder_ptr->get());
+    } else {
+      RTC_DLOG(LS_WARNING) << "Trying to call unset encoder.";
+    }
+  });
+}
+
 void ChannelSend::OnBitrateAllocation(BitrateAllocationUpdate update) {
   // This method can be called on the worker thread, module process thread
   // or on a TaskQueue via VideoSendStreamImpl::OnEncoderConfigurationChanged.
@@ -908,10 +841,8 @@
   //            module_process_thread_checker_.CalledOnValidThread());
   rtc::CritScope lock(&bitrate_crit_section_);
 
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkAllocation(update);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkAllocation(update);
   });
   retransmission_rate_limiter_->SetMaxRate(update.target_bitrate.bps());
   configured_bitrate_bps_ = update.target_bitrate.bps();
@@ -926,31 +857,25 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   if (!use_twcc_plr_for_ana_)
     return;
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
   });
 }
 
 void ChannelSend::OnRecoverableUplinkPacketLossRate(
     float recoverable_packet_loss_rate) {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkRecoverablePacketLossFraction(
-          recoverable_packet_loss_rate);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkRecoverablePacketLossFraction(
+        recoverable_packet_loss_rate);
   });
 }
 
 void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) {
   if (use_twcc_plr_for_ana_)
     return;
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
-    }
+  CallEncoder([&](AudioEncoder* encoder) {
+    encoder->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
   });
 }
 
@@ -1017,19 +942,8 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   RTC_DCHECK_LE(0, payload_type);
   RTC_DCHECK_GE(127, payload_type);
-  CodecInst codec = {0};
-  codec.pltype = payload_type;
-  codec.plfreq = payload_frequency;
-  memcpy(codec.plname, "telephone-event", 16);
-  if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
-    _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
-    if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
-      RTC_DLOG(LS_ERROR)
-          << "SetSendTelephoneEventPayloadType() failed to register "
-             "send payload type";
-      return false;
-    }
-  }
+  _rtpRtcpModule->RegisterAudioSendPayload(payload_type, "telephone-event",
+                                           payload_frequency, 0, 0);
   return true;
 }
 
@@ -1044,6 +958,23 @@
   _rtpRtcpModule->SetSSRC(ssrc);
 }
 
+void ChannelSend::SetRid(const std::string& rid,
+                         int extension_id,
+                         int repaired_extension_id) {
+  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
+  if (extension_id != 0) {
+    int ret = SetSendRtpHeaderExtension(!rid.empty(), kRtpExtensionRtpStreamId,
+                                        extension_id);
+    RTC_DCHECK_EQ(0, ret);
+  }
+  if (repaired_extension_id != 0) {
+    int ret = SetSendRtpHeaderExtension(!rid.empty(), kRtpExtensionRtpStreamId,
+                                        repaired_extension_id);
+    RTC_DCHECK_EQ(0, ret);
+  }
+  _rtpRtcpModule->SetRid(rid);
+}
+
 void ChannelSend::SetMid(const std::string& mid, int extension_id) {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   int ret = SetSendRtpHeaderExtension(true, kRtpExtensionMid, extension_id);
@@ -1220,30 +1151,6 @@
   _timeStamp += static_cast<uint32_t>(audio_input->samples_per_channel_);
 }
 
-void ChannelSend::UpdateOverheadForEncoder() {
-  size_t overhead_per_packet =
-      transport_overhead_per_packet_ + rtp_overhead_per_packet_;
-  audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
-    if (*encoder) {
-      (*encoder)->OnReceivedOverhead(overhead_per_packet);
-    }
-  });
-}
-
-void ChannelSend::SetTransportOverhead(size_t transport_overhead_per_packet) {
-  RTC_DCHECK_RUN_ON(&worker_thread_checker_);
-  rtc::CritScope cs(&overhead_per_packet_lock_);
-  transport_overhead_per_packet_ = transport_overhead_per_packet;
-  UpdateOverheadForEncoder();
-}
-
-// TODO(solenberg): Make AudioSendStream an OverheadObserver instead.
-void ChannelSend::OnOverheadChanged(size_t overhead_bytes_per_packet) {
-  rtc::CritScope cs(&overhead_per_packet_lock_);
-  rtp_overhead_per_packet_ = overhead_bytes_per_packet;
-  UpdateOverheadForEncoder();
-}
-
 ANAStats ChannelSend::GetANAStatistics() const {
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   return audio_coding_->GetANAStats();
@@ -1310,7 +1217,7 @@
   RTC_DCHECK_RUN_ON(&worker_thread_checker_);
   rtc::CritScope cs(&encoder_queue_lock_);
   if (encoder_queue_is_active_) {
-    encoder_queue_->PostTask([this, frame_encryptor]() {
+    encoder_queue_->PostTask([this, frame_encryptor]() mutable {
       this->frame_encryptor_ = std::move(frame_encryptor);
     });
   } else {
@@ -1318,6 +1225,9 @@
   }
 }
 
+// TODO(sukhanov): Consider moving TargetTransferRate observer to
+// AudioSendStream. Since AudioSendStream owns encoder and configures ANA, it
+// makes sense to consolidate all rate (and overhead) calculation there.
 void ChannelSend::OnTargetTransferRate(TargetTransferRate rate) {
   RTC_DCHECK(media_transport_);
   OnReceivedRtt(rate.network_estimate.round_trip_time.ms());
@@ -1325,20 +1235,18 @@
 
 void ChannelSend::OnReceivedRtt(int64_t rtt_ms) {
   // Invoke audio encoders OnReceivedRtt().
-  audio_coding_->ModifyEncoder(
-      [rtt_ms](std::unique_ptr<AudioEncoder>* encoder) {
-        if (*encoder) {
-          (*encoder)->OnReceivedRtt(rtt_ms);
-        }
-      });
+  CallEncoder(
+      [rtt_ms](AudioEncoder* encoder) { encoder->OnReceivedRtt(rtt_ms); });
 }
 
 }  // namespace
 
 std::unique_ptr<ChannelSendInterface> CreateChannelSend(
+    Clock* clock,
     rtc::TaskQueue* encoder_queue,
     ProcessThread* module_process_thread,
     MediaTransportInterface* media_transport,
+    OverheadObserver* overhead_observer,
     Transport* rtp_transport,
     RtcpRttStats* rtcp_rtt_stats,
     RtcEventLog* rtc_event_log,
@@ -1347,9 +1255,10 @@
     bool extmap_allow_mixed,
     int rtcp_report_interval_ms) {
   return absl::make_unique<ChannelSend>(
-      encoder_queue, module_process_thread, media_transport, rtp_transport,
-      rtcp_rtt_stats, rtc_event_log, frame_encryptor, crypto_options,
-      extmap_allow_mixed, rtcp_report_interval_ms);
+      clock, encoder_queue, module_process_thread, media_transport,
+      overhead_observer, rtp_transport, rtcp_rtt_stats, rtc_event_log,
+      frame_encryptor, crypto_options, extmap_allow_mixed,
+      rtcp_report_interval_ms);
 }
 
 }  // namespace voe
diff --git a/audio/channel_send.h b/audio/channel_send.h
index 083e9a6..4ab53c0 100644
--- a/audio/channel_send.h
+++ b/audio/channel_send.h
@@ -17,7 +17,7 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/audio_encoder.h"
-#include "api/crypto/cryptooptions.h"
+#include "api/crypto/crypto_options.h"
 #include "api/media_transport_interface.h"
 #include "modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "rtc_base/function_view.h"
@@ -63,8 +63,13 @@
                           std::unique_ptr<AudioEncoder> encoder) = 0;
   virtual void ModifyEncoder(
       rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) = 0;
+  virtual void CallEncoder(rtc::FunctionView<void(AudioEncoder*)> modifier) = 0;
 
   virtual void SetLocalSSRC(uint32_t ssrc) = 0;
+  // Use 0 to indicate that the extension should not be registered.
+  virtual void SetRid(const std::string& rid,
+                      int extension_id,
+                      int repaired_extension_id) = 0;
   virtual void SetMid(const std::string& mid, int extension_id) = 0;
   virtual void SetRTCP_CNAME(absl::string_view c_name) = 0;
   virtual void SetExtmapAllowMixed(bool extmap_allow_mixed) = 0;
@@ -85,7 +90,6 @@
 
   virtual void ProcessAndEncodeAudio(
       std::unique_ptr<AudioFrame> audio_frame) = 0;
-  virtual void SetTransportOverhead(size_t transport_overhead_per_packet) = 0;
   virtual RtpRtcp* GetRtpRtcp() const = 0;
 
   virtual void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) = 0;
@@ -111,9 +115,11 @@
 };
 
 std::unique_ptr<ChannelSendInterface> CreateChannelSend(
+    Clock* clock,
     rtc::TaskQueue* encoder_queue,
     ProcessThread* module_process_thread,
     MediaTransportInterface* media_transport,
+    OverheadObserver* overhead_observer,
     Transport* rtp_transport,
     RtcpRttStats* rtcp_rtt_stats,
     RtcEventLog* rtc_event_log,
diff --git a/audio/mock_voe_channel_proxy.h b/audio/mock_voe_channel_proxy.h
index eee25c5..a03ce7e 100644
--- a/audio/mock_voe_channel_proxy.h
+++ b/audio/mock_voe_channel_proxy.h
@@ -14,6 +14,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "api/test/mock_frame_encryptor.h"
@@ -52,7 +53,10 @@
   MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
   MOCK_CONST_METHOD0(GetSyncInfo, absl::optional<Syncable::Info>());
   MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
-  MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
+  MOCK_METHOD1(SetBaseMinimumPlayoutDelayMs, bool(int delay_ms));
+  MOCK_CONST_METHOD0(GetBaseMinimumPlayoutDelayMs, int());
+  MOCK_CONST_METHOD0(GetReceiveCodec,
+                     absl::optional<std::pair<int, SdpAudioFormat>>());
   MOCK_METHOD1(SetReceiveCodecs,
                void(const std::map<int, SdpAudioFormat>& codecs));
   MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
@@ -72,6 +76,12 @@
   MOCK_METHOD1(
       ModifyEncoder,
       void(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier));
+  MOCK_METHOD1(CallEncoder,
+               void(rtc::FunctionView<void(AudioEncoder*)> modifier));
+  MOCK_METHOD3(SetRid,
+               void(const std::string& rid,
+                    int extension_id,
+                    int repaired_extension_id));
   MOCK_METHOD2(SetMid, void(const std::string& mid, int extension_id));
   MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
   MOCK_METHOD1(SetRTCP_CNAME, void(absl::string_view c_name));
diff --git a/audio/null_audio_poller.cc b/audio/null_audio_poller.cc
index d2b1199..063a367 100644
--- a/audio/null_audio_poller.cc
+++ b/audio/null_audio_poller.cc
@@ -15,7 +15,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
 #include "rtc_base/thread.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace internal {
diff --git a/audio/null_audio_poller.h b/audio/null_audio_poller.h
index f91eb7d..9a81426 100644
--- a/audio/null_audio_poller.h
+++ b/audio/null_audio_poller.h
@@ -14,8 +14,8 @@
 #include <stdint.h>
 
 #include "modules/audio_device/include/audio_device_defines.h"
-#include "rtc_base/messagehandler.h"
-#include "rtc_base/messagequeue.h"
+#include "rtc_base/message_handler.h"
+#include "rtc_base/message_queue.h"
 #include "rtc_base/thread_checker.h"
 
 namespace webrtc {
diff --git a/audio/remix_resample.cc b/audio/remix_resample.cc
index cc59e2a..e77c386 100644
--- a/audio/remix_resample.cc
+++ b/audio/remix_resample.cc
@@ -80,7 +80,7 @@
     // The audio in dst_frame really is mono at this point; MonoToStereo will
     // set this back to stereo.
     dst_frame->num_channels_ = 1;
-    AudioFrameOperations::MonoToStereo(dst_frame);
+    AudioFrameOperations::UpmixChannels(2, dst_frame);
   }
 }
 
diff --git a/audio/transport_feedback_packet_loss_tracker_unittest.cc b/audio/transport_feedback_packet_loss_tracker_unittest.cc
index f522635..cc90651 100644
--- a/audio/transport_feedback_packet_loss_tracker_unittest.cc
+++ b/audio/transport_feedback_packet_loss_tracker_unittest.cc
@@ -561,8 +561,8 @@
 // to weed out potential bugs with wrap-around handling.
 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe};
 
-INSTANTIATE_TEST_CASE_P(_,
-                        TransportFeedbackPacketLossTrackerTest,
-                        testing::ValuesIn(kBases));
+INSTANTIATE_TEST_SUITE_P(_,
+                         TransportFeedbackPacketLossTrackerTest,
+                         testing::ValuesIn(kBases));
 
 }  // namespace webrtc
diff --git a/audio/utility/BUILD.gn b/audio/utility/BUILD.gn
index 11a65bd..f60b512 100644
--- a/audio/utility/BUILD.gn
+++ b/audio/utility/BUILD.gn
@@ -22,7 +22,9 @@
 
   deps = [
     "../../api/audio:audio_frame_api",
+    "../../common_audio",
     "../../rtc_base:checks",
+    "../../rtc_base:deprecation",
     "../../rtc_base:rtc_base_approved",
   ]
 }
@@ -40,9 +42,5 @@
       "../../test:test_support",
       "//testing/gtest",
     ]
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 }
diff --git a/audio/utility/audio_frame_operations.cc b/audio/utility/audio_frame_operations.cc
index 1a8232b..d3180a7 100644
--- a/audio/utility/audio_frame_operations.cc
+++ b/audio/utility/audio_frame_operations.cc
@@ -13,7 +13,9 @@
 #include <string.h>
 #include <algorithm>
 #include <cstdint>
+#include <utility>
 
+#include "common_audio/include/audio_util.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
 
@@ -69,60 +71,20 @@
   }
 }
 
-void AudioFrameOperations::MonoToStereo(const int16_t* src_audio,
-                                        size_t samples_per_channel,
-                                        int16_t* dst_audio) {
-  for (size_t i = 0; i < samples_per_channel; i++) {
-    dst_audio[2 * i] = src_audio[i];
-    dst_audio[2 * i + 1] = src_audio[i];
-  }
-}
-
 int AudioFrameOperations::MonoToStereo(AudioFrame* frame) {
   if (frame->num_channels_ != 1) {
     return -1;
   }
-  if ((frame->samples_per_channel_ * 2) >= AudioFrame::kMaxDataSizeSamples) {
-    // Not enough memory to expand from mono to stereo.
-    return -1;
-  }
-
-  if (!frame->muted()) {
-    // TODO(yujo): this operation can be done in place.
-    int16_t data_copy[AudioFrame::kMaxDataSizeSamples];
-    memcpy(data_copy, frame->data(),
-           sizeof(int16_t) * frame->samples_per_channel_);
-    MonoToStereo(data_copy, frame->samples_per_channel_, frame->mutable_data());
-  }
-  frame->num_channels_ = 2;
-
+  UpmixChannels(2, frame);
   return 0;
 }
 
-void AudioFrameOperations::StereoToMono(const int16_t* src_audio,
-                                        size_t samples_per_channel,
-                                        int16_t* dst_audio) {
-  for (size_t i = 0; i < samples_per_channel; i++) {
-    dst_audio[i] =
-        (static_cast<int32_t>(src_audio[2 * i]) + src_audio[2 * i + 1]) >> 1;
-  }
-}
-
 int AudioFrameOperations::StereoToMono(AudioFrame* frame) {
   if (frame->num_channels_ != 2) {
     return -1;
   }
-
-  RTC_DCHECK_LE(frame->samples_per_channel_ * 2,
-                AudioFrame::kMaxDataSizeSamples);
-
-  if (!frame->muted()) {
-    StereoToMono(frame->data(), frame->samples_per_channel_,
-                 frame->mutable_data());
-  }
-  frame->num_channels_ = 1;
-
-  return 0;
+  DownmixChannels(1, frame);
+  return frame->num_channels_ == 1 ? 0 : -1;
 }
 
 void AudioFrameOperations::QuadToStereo(const int16_t* src_audio,
@@ -154,65 +116,66 @@
   return 0;
 }
 
-void AudioFrameOperations::QuadToMono(const int16_t* src_audio,
-                                      size_t samples_per_channel,
-                                      int16_t* dst_audio) {
-  for (size_t i = 0; i < samples_per_channel; i++) {
-    dst_audio[i] =
-        (static_cast<int32_t>(src_audio[4 * i]) + src_audio[4 * i + 1] +
-         src_audio[4 * i + 2] + src_audio[4 * i + 3]) >>
-        2;
-  }
-}
-
-int AudioFrameOperations::QuadToMono(AudioFrame* frame) {
-  if (frame->num_channels_ != 4) {
-    return -1;
-  }
-
-  RTC_DCHECK_LE(frame->samples_per_channel_ * 4,
-                AudioFrame::kMaxDataSizeSamples);
-
-  if (!frame->muted()) {
-    QuadToMono(frame->data(), frame->samples_per_channel_,
-               frame->mutable_data());
-  }
-  frame->num_channels_ = 1;
-
-  return 0;
-}
-
 void AudioFrameOperations::DownmixChannels(const int16_t* src_audio,
                                            size_t src_channels,
                                            size_t samples_per_channel,
                                            size_t dst_channels,
                                            int16_t* dst_audio) {
-  if (src_channels == 2 && dst_channels == 1) {
-    StereoToMono(src_audio, samples_per_channel, dst_audio);
+  if (src_channels > 1 && dst_channels == 1) {
+    DownmixInterleavedToMono(src_audio, samples_per_channel, src_channels,
+                             dst_audio);
     return;
   } else if (src_channels == 4 && dst_channels == 2) {
     QuadToStereo(src_audio, samples_per_channel, dst_audio);
     return;
-  } else if (src_channels == 4 && dst_channels == 1) {
-    QuadToMono(src_audio, samples_per_channel, dst_audio);
-    return;
   }
 
   RTC_NOTREACHED() << "src_channels: " << src_channels
                    << ", dst_channels: " << dst_channels;
 }
 
-int AudioFrameOperations::DownmixChannels(size_t dst_channels,
-                                          AudioFrame* frame) {
-  if (frame->num_channels_ == 2 && dst_channels == 1) {
-    return StereoToMono(frame);
+void AudioFrameOperations::DownmixChannels(size_t dst_channels,
+                                           AudioFrame* frame) {
+  RTC_DCHECK_LE(frame->samples_per_channel_ * frame->num_channels_,
+                AudioFrame::kMaxDataSizeSamples);
+  if (frame->num_channels_ > 1 && dst_channels == 1) {
+    if (!frame->muted()) {
+      DownmixInterleavedToMono(frame->data(), frame->samples_per_channel_,
+                               frame->num_channels_, frame->mutable_data());
+    }
+    frame->num_channels_ = 1;
   } else if (frame->num_channels_ == 4 && dst_channels == 2) {
-    return QuadToStereo(frame);
-  } else if (frame->num_channels_ == 4 && dst_channels == 1) {
-    return QuadToMono(frame);
+    int err = QuadToStereo(frame);
+    RTC_DCHECK_EQ(err, 0);
+  } else {
+    RTC_NOTREACHED() << "src_channels: " << frame->num_channels_
+                     << ", dst_channels: " << dst_channels;
+  }
+}
+
+void AudioFrameOperations::UpmixChannels(size_t target_number_of_channels,
+                                         AudioFrame* frame) {
+  RTC_DCHECK_EQ(frame->num_channels_, 1);
+  RTC_DCHECK_LE(frame->samples_per_channel_ * target_number_of_channels,
+                AudioFrame::kMaxDataSizeSamples);
+
+  if (frame->num_channels_ != 1 ||
+      frame->samples_per_channel_ * target_number_of_channels >
+          AudioFrame::kMaxDataSizeSamples) {
+    return;
   }
 
-  return -1;
+  if (!frame->muted()) {
+    // Up-mixing done in place. Going backwards through the frame ensure nothing
+    // is irrevocably overwritten.
+    for (int i = frame->samples_per_channel_ - 1; i >= 0; i--) {
+      for (size_t j = 0; j < target_number_of_channels; ++j) {
+        frame->mutable_data()[target_number_of_channels * i + j] =
+            frame->data()[i];
+      }
+    }
+  }
+  frame->num_channels_ = target_number_of_channels;
 }
 
 void AudioFrameOperations::SwapStereoChannels(AudioFrame* frame) {
@@ -223,9 +186,7 @@
 
   int16_t* frame_data = frame->mutable_data();
   for (size_t i = 0; i < frame->samples_per_channel_ * 2; i += 2) {
-    int16_t temp_data = frame_data[i];
-    frame_data[i] = frame_data[i + 1];
-    frame_data[i + 1] = temp_data;
+    std::swap(frame_data[i], frame_data[i + 1]);
   }
 }
 
diff --git a/audio/utility/audio_frame_operations.h b/audio/utility/audio_frame_operations.h
index c1445b6..65c310c 100644
--- a/audio/utility/audio_frame_operations.h
+++ b/audio/utility/audio_frame_operations.h
@@ -15,6 +15,7 @@
 #include <stdint.h>
 
 #include "api/audio/audio_frame.h"
+#include "rtc_base/deprecation.h"
 
 namespace webrtc {
 
@@ -32,28 +33,15 @@
   // |result_frame| is empty.
   static void Add(const AudioFrame& frame_to_add, AudioFrame* result_frame);
 
-  // Upmixes mono |src_audio| to stereo |dst_audio|. This is an out-of-place
-  // operation, meaning src_audio and dst_audio must point to different
-  // buffers. It is the caller's responsibility to ensure that |dst_audio| is
-  // sufficiently large.
-  static void MonoToStereo(const int16_t* src_audio,
-                           size_t samples_per_channel,
-                           int16_t* dst_audio);
-
   // |frame.num_channels_| will be updated. This version checks for sufficient
-  // buffer size and that |num_channels_| is mono.
-  static int MonoToStereo(AudioFrame* frame);
-
-  // Downmixes stereo |src_audio| to mono |dst_audio|. This is an in-place
-  // operation, meaning |src_audio| and |dst_audio| may point to the same
-  // buffer.
-  static void StereoToMono(const int16_t* src_audio,
-                           size_t samples_per_channel,
-                           int16_t* dst_audio);
+  // buffer size and that |num_channels_| is mono. Use UpmixChannels
+  // instead. TODO(bugs.webrtc.org/8649): remove.
+  RTC_DEPRECATED static int MonoToStereo(AudioFrame* frame);
 
   // |frame.num_channels_| will be updated. This version checks that
-  // |num_channels_| is stereo.
-  static int StereoToMono(AudioFrame* frame);
+  // |num_channels_| is stereo. Use DownmixChannels
+  // instead. TODO(bugs.webrtc.org/8649): remove.
+  RTC_DEPRECATED static int StereoToMono(AudioFrame* frame);
 
   // Downmixes 4 channels |src_audio| to stereo |dst_audio|. This is an in-place
   // operation, meaning |src_audio| and |dst_audio| may point to the same
@@ -66,17 +54,6 @@
   // |num_channels_| is 4 channels.
   static int QuadToStereo(AudioFrame* frame);
 
-  // Downmixes 4 channels |src_audio| to mono |dst_audio|. This is an in-place
-  // operation, meaning |src_audio| and |dst_audio| may point to the same
-  // buffer.
-  static void QuadToMono(const int16_t* src_audio,
-                         size_t samples_per_channel,
-                         int16_t* dst_audio);
-
-  // |frame.num_channels_| will be updated. This version checks that
-  // |num_channels_| is 4 channels.
-  static int QuadToMono(AudioFrame* frame);
-
   // Downmixes |src_channels| |src_audio| to |dst_channels| |dst_audio|.
   // This is an in-place operation, meaning |src_audio| and |dst_audio|
   // may point to the same buffer. Supported channel combinations are
@@ -88,10 +65,16 @@
                               int16_t* dst_audio);
 
   // |frame.num_channels_| will be updated. This version checks that
+  // |num_channels_| and |dst_channels| are valid and performs relevant downmix.
+  // Supported channel combinations are N channels to Mono, and Quad to Stereo.
+  static void DownmixChannels(size_t dst_channels, AudioFrame* frame);
+
+  // |frame.num_channels_| will be updated. This version checks that
   // |num_channels_| and |dst_channels| are valid and performs relevant
-  // downmix.  Supported channel combinations are Stereo to Mono, Quad to Mono,
-  // and Quad to Stereo.
-  static int DownmixChannels(size_t dst_channels, AudioFrame* frame);
+  // downmix. Supported channel combinations are Mono to N
+  // channels. The single channel is replicated.
+  static void UpmixChannels(size_t target_number_of_channels,
+                            AudioFrame* frame);
 
   // Swap the left and right channels of |frame|. Fails silently if |frame| is
   // not stereo.
diff --git a/audio/utility/audio_frame_operations_unittest.cc b/audio/utility/audio_frame_operations_unittest.cc
index 76f1dcd..dd41d1a 100644
--- a/audio/utility/audio_frame_operations_unittest.cc
+++ b/audio/utility/audio_frame_operations_unittest.cc
@@ -103,19 +103,21 @@
   }
 }
 
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 TEST_F(AudioFrameOperationsTest, MonoToStereoFailsWithBadParameters) {
-  EXPECT_EQ(-1, AudioFrameOperations::MonoToStereo(&frame_));
-
+  EXPECT_DEATH(AudioFrameOperations::UpmixChannels(2, &frame_), "");
   frame_.samples_per_channel_ = AudioFrame::kMaxDataSizeSamples;
   frame_.num_channels_ = 1;
-  EXPECT_EQ(-1, AudioFrameOperations::MonoToStereo(&frame_));
+  EXPECT_DEATH(AudioFrameOperations::UpmixChannels(2, &frame_), "");
 }
+#endif
 
 TEST_F(AudioFrameOperationsTest, MonoToStereoSucceeds) {
   frame_.num_channels_ = 1;
   SetFrameData(1, &frame_);
 
-  EXPECT_EQ(0, AudioFrameOperations::MonoToStereo(&frame_));
+  AudioFrameOperations::UpmixChannels(2, &frame_);
+  EXPECT_EQ(2u, frame_.num_channels_);
 
   AudioFrame stereo_frame;
   stereo_frame.samples_per_channel_ = 320;
@@ -127,36 +129,22 @@
 TEST_F(AudioFrameOperationsTest, MonoToStereoMuted) {
   frame_.num_channels_ = 1;
   ASSERT_TRUE(frame_.muted());
-  EXPECT_EQ(0, AudioFrameOperations::MonoToStereo(&frame_));
+  AudioFrameOperations::UpmixChannels(2, &frame_);
+  EXPECT_EQ(2u, frame_.num_channels_);
   EXPECT_TRUE(frame_.muted());
 }
 
-TEST_F(AudioFrameOperationsTest, MonoToStereoBufferSucceeds) {
-  AudioFrame target_frame;
-  frame_.num_channels_ = 1;
-  SetFrameData(4, &frame_);
-
-  target_frame.num_channels_ = 2;
-  target_frame.samples_per_channel_ = frame_.samples_per_channel_;
-
-  AudioFrameOperations::MonoToStereo(frame_.data(), frame_.samples_per_channel_,
-                                     target_frame.mutable_data());
-
-  AudioFrame stereo_frame;
-  stereo_frame.samples_per_channel_ = 320;
-  stereo_frame.num_channels_ = 2;
-  SetFrameData(4, 4, &stereo_frame);
-  VerifyFramesAreEqual(stereo_frame, target_frame);
-}
-
+#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
 TEST_F(AudioFrameOperationsTest, StereoToMonoFailsWithBadParameters) {
   frame_.num_channels_ = 1;
-  EXPECT_EQ(-1, AudioFrameOperations::StereoToMono(&frame_));
+  EXPECT_DEATH(AudioFrameOperations::DownmixChannels(1, &frame_), "");
 }
+#endif
 
 TEST_F(AudioFrameOperationsTest, StereoToMonoSucceeds) {
   SetFrameData(4, 2, &frame_);
-  EXPECT_EQ(0, AudioFrameOperations::StereoToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
@@ -167,7 +155,8 @@
 
 TEST_F(AudioFrameOperationsTest, StereoToMonoMuted) {
   ASSERT_TRUE(frame_.muted());
-  EXPECT_EQ(0, AudioFrameOperations::StereoToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
   EXPECT_TRUE(frame_.muted());
 }
 
@@ -178,8 +167,9 @@
   target_frame.num_channels_ = 1;
   target_frame.samples_per_channel_ = frame_.samples_per_channel_;
 
-  AudioFrameOperations::StereoToMono(frame_.data(), frame_.samples_per_channel_,
-                                     target_frame.mutable_data());
+  AudioFrameOperations::DownmixChannels(frame_.data(), 2,
+                                        frame_.samples_per_channel_, 1,
+                                        target_frame.mutable_data());
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
@@ -190,8 +180,8 @@
 
 TEST_F(AudioFrameOperationsTest, StereoToMonoDoesNotWrapAround) {
   SetFrameData(-32768, -32768, &frame_);
-  EXPECT_EQ(0, AudioFrameOperations::StereoToMono(&frame_));
-
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
   mono_frame.num_channels_ = 1;
@@ -199,18 +189,12 @@
   VerifyFramesAreEqual(mono_frame, frame_);
 }
 
-TEST_F(AudioFrameOperationsTest, QuadToMonoFailsWithBadParameters) {
-  frame_.num_channels_ = 1;
-  EXPECT_EQ(-1, AudioFrameOperations::QuadToMono(&frame_));
-  frame_.num_channels_ = 2;
-  EXPECT_EQ(-1, AudioFrameOperations::QuadToMono(&frame_));
-}
-
 TEST_F(AudioFrameOperationsTest, QuadToMonoSucceeds) {
   frame_.num_channels_ = 4;
   SetFrameData(4, 2, 6, 8, &frame_);
 
-  EXPECT_EQ(0, AudioFrameOperations::QuadToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
@@ -222,7 +206,8 @@
 TEST_F(AudioFrameOperationsTest, QuadToMonoMuted) {
   frame_.num_channels_ = 4;
   ASSERT_TRUE(frame_.muted());
-  EXPECT_EQ(0, AudioFrameOperations::QuadToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
   EXPECT_TRUE(frame_.muted());
 }
 
@@ -234,8 +219,9 @@
   target_frame.num_channels_ = 1;
   target_frame.samples_per_channel_ = frame_.samples_per_channel_;
 
-  AudioFrameOperations::QuadToMono(frame_.data(), frame_.samples_per_channel_,
-                                   target_frame.mutable_data());
+  AudioFrameOperations::DownmixChannels(frame_.data(), 4,
+                                        frame_.samples_per_channel_, 1,
+                                        target_frame.mutable_data());
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
   mono_frame.num_channels_ = 1;
@@ -246,7 +232,8 @@
 TEST_F(AudioFrameOperationsTest, QuadToMonoDoesNotWrapAround) {
   frame_.num_channels_ = 4;
   SetFrameData(-32768, -32768, -32768, -32768, &frame_);
-  EXPECT_EQ(0, AudioFrameOperations::QuadToMono(&frame_));
+  AudioFrameOperations::DownmixChannels(1, &frame_);
+  EXPECT_EQ(1u, frame_.num_channels_);
 
   AudioFrame mono_frame;
   mono_frame.samples_per_channel_ = 320;
diff --git a/common_audio/BUILD.gn b/common_audio/BUILD.gn
index 74b0c60..f7ffa00 100644
--- a/common_audio/BUILD.gn
+++ b/common_audio/BUILD.gn
@@ -58,7 +58,7 @@
     "../system_wrappers:cpu_features_api",
     "third_party/fft4g:fft4g",
     "//third_party/abseil-cpp/absl/container:inlined_vector",
-    "//third_party/abseil-cpp/absl/memory:memory",
+    "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 
diff --git a/common_audio/audio_converter.cc b/common_audio/audio_converter.cc
index 0f97abb..c560346 100644
--- a/common_audio/audio_converter.cc
+++ b/common_audio/audio_converter.cc
@@ -31,7 +31,7 @@
                 size_t dst_channels,
                 size_t dst_frames)
       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
-  ~CopyConverter() override{};
+  ~CopyConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -52,7 +52,7 @@
                  size_t dst_channels,
                  size_t dst_frames)
       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
-  ~UpmixConverter() override{};
+  ~UpmixConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -74,7 +74,7 @@
                    size_t dst_channels,
                    size_t dst_frames)
       : AudioConverter(src_channels, src_frames, dst_channels, dst_frames) {}
-  ~DownmixConverter() override{};
+  ~DownmixConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -103,7 +103,7 @@
       resamplers_.push_back(std::unique_ptr<PushSincResampler>(
           new PushSincResampler(src_frames, dst_frames)));
   }
-  ~ResampleConverter() override{};
+  ~ResampleConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
@@ -132,7 +132,7 @@
           std::unique_ptr<ChannelBuffer<float>>(new ChannelBuffer<float>(
               (*it)->dst_frames(), (*it)->dst_channels())));
   }
-  ~CompositionConverter() override{};
+  ~CompositionConverter() override {}
 
   void Convert(const float* const* src,
                size_t src_size,
diff --git a/common_audio/audio_converter.h b/common_audio/audio_converter.h
index 24a5e72..73ad1ef 100644
--- a/common_audio/audio_converter.h
+++ b/common_audio/audio_converter.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/real_fourier_unittest.cc b/common_audio/real_fourier_unittest.cc
index 1324887..eac4fce 100644
--- a/common_audio/real_fourier_unittest.cc
+++ b/common_audio/real_fourier_unittest.cc
@@ -68,7 +68,7 @@
 };
 
 using FftTypes = ::testing::Types<RealFourierOoura>;
-TYPED_TEST_CASE(RealFourierTest, FftTypes);
+TYPED_TEST_SUITE(RealFourierTest, FftTypes);
 
 TYPED_TEST(RealFourierTest, SimpleForwardTransform) {
   this->real_buffer_[0] = 1.0f;
diff --git a/common_audio/resampler/push_sinc_resampler.h b/common_audio/resampler/push_sinc_resampler.h
index db9cdc1..b002ff7 100644
--- a/common_audio/resampler/push_sinc_resampler.h
+++ b/common_audio/resampler/push_sinc_resampler.h
@@ -16,7 +16,7 @@
 #include <memory>
 
 #include "common_audio/resampler/sinc_resampler.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/resampler/push_sinc_resampler_unittest.cc b/common_audio/resampler/push_sinc_resampler_unittest.cc
index 2f53a74..ee111c4 100644
--- a/common_audio/resampler/push_sinc_resampler_unittest.cc
+++ b/common_audio/resampler/push_sinc_resampler_unittest.cc
@@ -16,7 +16,7 @@
 #include "common_audio/include/audio_util.h"
 #include "common_audio/resampler/push_sinc_resampler.h"
 #include "common_audio/resampler/sinusoidal_linear_chirp_source.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
@@ -255,7 +255,7 @@
 
 // Thresholds chosen arbitrarily based on what each resampling reported during
 // testing.  All thresholds are in dbFS, http://en.wikipedia.org/wiki/DBFS.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     PushSincResamplerTest,
     PushSincResamplerTest,
     ::testing::Values(
diff --git a/common_audio/resampler/sinc_resampler.h b/common_audio/resampler/sinc_resampler.h
index 0be4318..ffd70d9 100644
--- a/common_audio/resampler/sinc_resampler.h
+++ b/common_audio/resampler/sinc_resampler.h
@@ -17,7 +17,7 @@
 #include <stddef.h>
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/gtest_prod_util.h"
 #include "rtc_base/memory/aligned_malloc.h"
 #include "rtc_base/system/arch.h"
diff --git a/common_audio/resampler/sinc_resampler_unittest.cc b/common_audio/resampler/sinc_resampler_unittest.cc
index eb5424d..3aedacc 100644
--- a/common_audio/resampler/sinc_resampler_unittest.cc
+++ b/common_audio/resampler/sinc_resampler_unittest.cc
@@ -24,7 +24,7 @@
 #include "common_audio/resampler/sinusoidal_linear_chirp_source.h"
 #include "rtc_base/stringize_macros.h"
 #include "rtc_base/system/arch.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/cpu_features_wrapper.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -340,7 +340,7 @@
 
 // Thresholds chosen arbitrarily based on what each resampling reported during
 // testing.  All thresholds are in dbFS, http://en.wikipedia.org/wiki/DBFS.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     SincResamplerTest,
     SincResamplerTest,
     testing::Values(
diff --git a/common_audio/resampler/sinusoidal_linear_chirp_source.h b/common_audio/resampler/sinusoidal_linear_chirp_source.h
index 71dcff5..81f6a24 100644
--- a/common_audio/resampler/sinusoidal_linear_chirp_source.h
+++ b/common_audio/resampler/sinusoidal_linear_chirp_source.h
@@ -15,7 +15,7 @@
 #define COMMON_AUDIO_RESAMPLER_SINUSOIDAL_LINEAR_CHIRP_SOURCE_H_
 
 #include "common_audio/resampler/sinc_resampler.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/smoothing_filter.cc b/common_audio/smoothing_filter.cc
index 0d5aaa4..e5ce987 100644
--- a/common_audio/smoothing_filter.cc
+++ b/common_audio/smoothing_filter.cc
@@ -13,7 +13,7 @@
 #include <cmath>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 
diff --git a/common_audio/smoothing_filter.h b/common_audio/smoothing_filter.h
index c467d85..e5f561e 100644
--- a/common_audio/smoothing_filter.h
+++ b/common_audio/smoothing_filter.h
@@ -14,7 +14,7 @@
 #include <stdint.h>
 
 #include "absl/types/optional.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/smoothing_filter_unittest.cc b/common_audio/smoothing_filter_unittest.cc
index abe4272..5f6711e 100644
--- a/common_audio/smoothing_filter_unittest.cc
+++ b/common_audio/smoothing_filter_unittest.cc
@@ -12,7 +12,7 @@
 #include <memory>
 
 #include "common_audio/smoothing_filter.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/common_audio/sparse_fir_filter.h b/common_audio/sparse_fir_filter.h
index 22bcdff..5197a8e 100644
--- a/common_audio/sparse_fir_filter.h
+++ b/common_audio/sparse_fir_filter.h
@@ -14,7 +14,7 @@
 #include <cstring>
 #include <vector>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_audio/wav_file.h b/common_audio/wav_file.h
index cbce59d..7e790e0 100644
--- a/common_audio/wav_file.h
+++ b/common_audio/wav_file.h
@@ -17,7 +17,7 @@
 #include <cstddef>
 #include <string>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/platform_file.h"
 
 namespace webrtc {
diff --git a/common_audio/wav_file_unittest.cc b/common_audio/wav_file_unittest.cc
index d40229a..b7e5d3f 100644
--- a/common_audio/wav_file_unittest.cc
+++ b/common_audio/wav_file_unittest.cc
@@ -17,7 +17,7 @@
 #include "common_audio/wav_file.h"
 #include "common_audio/wav_header.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 // WavWriterTest.CPPFileDescriptor and WavWriterTest.CPP flaky on Mac.
 // See webrtc:9247.
diff --git a/common_audio/window_generator.h b/common_audio/window_generator.h
index ad3b445..0cbe24a 100644
--- a/common_audio/window_generator.h
+++ b/common_audio/window_generator.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/common_types.h b/common_types.h
index 848b899..2b877d6 100644
--- a/common_types.h
+++ b/common_types.h
@@ -14,12 +14,8 @@
 #include <stddef.h>  // For size_t
 #include <cstdint>
 
-#include "absl/strings/match.h"
-// TODO(sprang): Remove this include when all usage includes it directly.
-#include "api/video/video_bitrate_allocation.h"
 // TODO(bugs.webrtc.org/7660): Delete include once downstream code is updated.
 #include "api/video/video_codec_type.h"
-#include "rtc_base/checks.h"
 
 #if defined(_MSC_VER)
 // Disable "new behavior: elements of array will be default initialized"
@@ -27,8 +23,6 @@
 #pragma warning(disable : 4351)
 #endif
 
-#define RTP_PAYLOAD_NAME_SIZE 32u
-
 namespace webrtc {
 
 enum FrameType {
@@ -158,29 +152,6 @@
   virtual void OnOverheadChanged(size_t overhead_bytes_per_packet) = 0;
 };
 
-// ==================================================================
-// Voice specific types
-// ==================================================================
-
-// Each codec supported can be described by this structure.
-struct CodecInst {
-  int pltype;
-  char plname[RTP_PAYLOAD_NAME_SIZE];
-  int plfreq;
-  int pacsize;
-  size_t channels;
-  int rate;  // bits/sec unlike {start,min,max}Bitrate elsewhere in this file!
-
-  bool operator==(const CodecInst& other) const {
-    return pltype == other.pltype &&
-           absl::EqualsIgnoreCase(plname, other.plname) &&
-           plfreq == other.plfreq && pacsize == other.pacsize &&
-           channels == other.channels && rate == other.rate;
-  }
-
-  bool operator!=(const CodecInst& other) const { return !(*this == other); }
-};
-
 // RTP
 enum { kRtpCsrcSize = 15 };  // RFC 3550 page 13
 
diff --git a/cras-config/aec_config.cc b/cras-config/aec_config.cc
index d0cf19b..d8fb369 100644
--- a/cras-config/aec_config.cc
+++ b/cras-config/aec_config.cc
@@ -24,8 +24,6 @@
 	if (ini == NULL)
 		return;
 
-	config->buffering.use_new_render_buffering =
-		AEC_GET_INT(ini, BUFFERING, USE_NEW_RENDER_BUFFERING);
 	config->buffering.excess_render_detection_interval_blocks =
 		AEC_GET_INT(ini, BUFFERING,
 			EXCESS_RENDER_DETECTION_INTERVAL_BLOCKS);
@@ -38,18 +36,10 @@
 		AEC_GET_INT(ini, DELAY, DOWN_SAMPLING_FACTOR);
 	config->delay.num_filters =
 		AEC_GET_INT(ini, DELAY, NUM_FILTERS);
-	config->delay.api_call_jitter_blocks =
-		AEC_GET_INT(ini, DELAY, API_CALL_JITTER_BLOCKS);
-	config->delay.min_echo_path_delay_blocks =
-		AEC_GET_INT(ini, DELAY, MIN_ECHO_PATH_DELAY_BLOCKS);
-	config->delay.delay_headroom_blocks =
-		AEC_GET_INT(ini, DELAY, DELAY_HEADROOM_BLOCKS);
-	config->delay.hysteresis_limit_1_blocks =
-		AEC_GET_INT(ini, DELAY, HYSTERESIS_LIMIT_1_BLOCKS);
-	config->delay.hysteresis_limit_2_blocks =
-		AEC_GET_INT(ini, DELAY, HYSTERESIS_LIMIT_2_BLOCKS);
-	config->delay.skew_hysteresis_blocks =
-		AEC_GET_INT(ini, DELAY, SKEW_HYSTERESIS_BLOCKS);
+	config->delay.delay_headroom_samples =
+		AEC_GET_INT(ini, DELAY, DELAY_HEADROOM_SAMPLES);
+	config->delay.hysteresis_limit_blocks =
+		AEC_GET_INT(ini, DELAY, HYSTERESIS_LIMIT_BLOCKS);
 	config->delay.fixed_capture_delay_samples =
 		AEC_GET_INT(ini, DELAY, FIXED_CAPTURE_DELAY_SAMPLES);
 	config->delay.delay_estimate_smoothing =
@@ -121,12 +111,8 @@
 	config->erle.num_sections =
 		AEC_GET_INT(ini, ERLE, NUM_SECTIONS);
 
-	config->ep_strength.lf =
-		AEC_GET_FLOAT(ini, EP_STRENGTH, LF);
-	config->ep_strength.mf =
-		AEC_GET_FLOAT(ini, EP_STRENGTH, MF);
-	config->ep_strength.hf =
-		AEC_GET_FLOAT(ini, EP_STRENGTH, HF);
+	config->ep_strength.default_gain =
+		AEC_GET_FLOAT(ini, EP_STRENGTH, DEFAULT_GAIN);
 	config->ep_strength.default_len =
 		AEC_GET_FLOAT(ini, EP_STRENGTH, DEFAULT_LEN);
 	config->ep_strength.reverb_based_on_render =
@@ -161,14 +147,6 @@
 	config->render_levels.poor_excitation_render_limit_ds8 =
 		AEC_GET_FLOAT(ini, RENDER_LEVELS, POOR_EXCITATION_RENDER_LIMIT_DS8);
 
-	config->echo_removal_control.gain_rampup.initial_gain =
-		AEC_GET_FLOAT(ini, ECHO_REMOVAL_CTL, INITIAL_GAIN);
-	config->echo_removal_control.gain_rampup.first_non_zero_gain =
-		AEC_GET_FLOAT(ini, ECHO_REMOVAL_CTL, FIRST_NON_ZERO_GAIN);
-	config->echo_removal_control.gain_rampup.non_zero_gain_blocks =
-		AEC_GET_INT(ini, ECHO_REMOVAL_CTL, NON_ZERO_GAIN_BLOCKS);
-	config->echo_removal_control.gain_rampup.full_gain_blocks =
-		AEC_GET_INT(ini, ECHO_REMOVAL_CTL, FULL_GAIN_BLOCKS);
 	config->echo_removal_control.has_clock_drift =
 		AEC_GET_INT(ini, ECHO_REMOVAL_CTL, HAS_CLOCK_DRIFT);
 	config->echo_removal_control.linear_and_stable_echo_path =
@@ -288,8 +266,6 @@
 
 	syslog(LOG_ERR, "---- aec config dump ----");
 	syslog(LOG_ERR, "Buffering:");
-	syslog(LOG_ERR, "    use_new_render_buffering %d",
-			config.buffering.use_new_render_buffering);
 	syslog(LOG_ERR, "    excess_render_detection_interval_blocks %zu",
 			config.buffering.excess_render_detection_interval_blocks);
 	syslog(LOG_ERR, "    max_allowed_excess_render_blocks %zu",
@@ -300,15 +276,9 @@
 			config.delay.default_delay,
 			config.delay.down_sampling_factor,
 			config.delay.num_filters);
-	syslog(LOG_ERR, "    api_call_jitter_blocks %zu, min_echo_path_delay_blocks %zu",
-			config.delay.api_call_jitter_blocks,
-			config.delay.min_echo_path_delay_blocks);
-	syslog(LOG_ERR, "    delay_headroom_blocks %zu, hysteresis_limit_1_blocks %zu",
-			config.delay.delay_headroom_blocks,
-			config.delay.hysteresis_limit_1_blocks);
-	syslog(LOG_ERR, "    hysteresis_limit_2_blocks %zu, skew_hysteresis_blocks %zu",
-			config.delay.hysteresis_limit_2_blocks,
-			config.delay.skew_hysteresis_blocks);
+	syslog(LOG_ERR, "    delay_headroom_samples %zu, hysteresis_limit_blocks %zu",
+			config.delay.delay_headroom_samples,
+			config.delay.hysteresis_limit_blocks);
 	syslog(LOG_ERR, "    fixed_capture_delay_samples %zu",
 			config.delay.fixed_capture_delay_samples);
 	syslog(LOG_ERR, "    delay_estimate_smoothing %f",
@@ -359,10 +329,8 @@
 	syslog(LOG_ERR, "Erle: min %f max_l %f max_h %f onset_detection %d",
 			config.erle.min, config.erle.max_l,
 			config.erle.max_h, config.erle.onset_detection);
-	syslog(LOG_ERR, "Ep strength: lf %f mf %f hf %f default_len %f",
-			config.ep_strength.lf,
-			config.ep_strength.mf,
-			config.ep_strength.hf,
+	syslog(LOG_ERR, "Ep strength: default_gain %f default_len %f",
+			config.ep_strength.default_gain,
 			config.ep_strength.default_len);
 	syslog(LOG_ERR, "    echo_can_saturate %d, bounded_erl %d,"
 			"    ep_strength.reverb_based_on_render %d",
@@ -394,12 +362,6 @@
 			config.render_levels.poor_excitation_render_limit_ds8);
 	syslog(LOG_ERR, "Echo removal control:");
 	syslog(LOG_ERR, "    gain rampup:");
-	syslog(LOG_ERR, "        initial_gain %f, first_non_zero_gain %f",
-			config.echo_removal_control.gain_rampup.initial_gain,
-			config.echo_removal_control.gain_rampup.first_non_zero_gain);
-	syslog(LOG_ERR, "        non_zero_gain_blocks %d, full_gain_blocks %d",
-			config.echo_removal_control.gain_rampup.non_zero_gain_blocks,
-			config.echo_removal_control.gain_rampup.full_gain_blocks);
 	syslog(LOG_ERR, "    has_clock_drift %d",
 			config.echo_removal_control.has_clock_drift);
 	syslog(LOG_ERR, "    linear_and_stable_echo_path %d",
diff --git a/cras-config/aec_config.h b/cras-config/aec_config.h
index 33185b3..3b6fd5d 100644
--- a/cras-config/aec_config.h
+++ b/cras-config/aec_config.h
@@ -10,8 +10,6 @@
 
 #include "api/audio/echo_canceller3_config.h"
 
-#define AEC_BUFFERING_USE_NEW_RENDER_BUFFERING "buffering:use_new_render_buffering"
-#define AEC_BUFFERING_USE_NEW_RENDER_BUFFERING_VALUE 1
 #define AEC_BUFFERING_EXCESS_RENDER_DETECTION_INTERVAL_BLOCKS \
 	"buffering:excess_render_detection_interval_blocks"
 #define AEC_BUFFERING_EXCESS_RENDER_DETECTION_INTERVAL_BLOCKS_VALUE 250
@@ -25,18 +23,10 @@
 #define AEC_DELAY_DOWN_SAMPLING_FACTOR_VALUE 4
 #define AEC_DELAY_NUM_FILTERS "delay:num_filters"
 #define AEC_DELAY_NUM_FILTERS_VALUE 5
-#define AEC_DELAY_API_CALL_JITTER_BLOCKS "delay:api_call_jitter_blocks"
-#define AEC_DELAY_API_CALL_JITTER_BLOCKS_VALUE 26
-#define AEC_DELAY_MIN_ECHO_PATH_DELAY_BLOCKS "delay:min_echo_path_delay_blocks"
-#define AEC_DELAY_MIN_ECHO_PATH_DELAY_BLOCKS_VALUE 0
-#define AEC_DELAY_DELAY_HEADROOM_BLOCKS "delay:delay_headroom_blocks"
-#define AEC_DELAY_DELAY_HEADROOM_BLOCKS_VALUE 2
-#define AEC_DELAY_HYSTERESIS_LIMIT_1_BLOCKS "delay:hysteresis_limit_1_blocks"
-#define AEC_DELAY_HYSTERESIS_LIMIT_1_BLOCKS_VALUE 1
-#define AEC_DELAY_HYSTERESIS_LIMIT_2_BLOCKS "delay:hysteresis_limit_2_blocks"
-#define AEC_DELAY_HYSTERESIS_LIMIT_2_BLOCKS_VALUE 1
-#define AEC_DELAY_SKEW_HYSTERESIS_BLOCKS "delay:skew_hysteresis_blocks"
-#define AEC_DELAY_SKEW_HYSTERESIS_BLOCKS_VALUE 3
+#define AEC_DELAY_DELAY_HEADROOM_SAMPLES "delay:delay_headroom_samples"
+#define AEC_DELAY_DELAY_HEADROOM_SAMPLES_VALUE 32
+#define AEC_DELAY_HYSTERESIS_LIMIT_BLOCKS "delay:hysteresis_limit_blocks"
+#define AEC_DELAY_HYSTERESIS_LIMIT_BLOCKS_VALUE 1
 #define AEC_DELAY_FIXED_CAPTURE_DELAY_SAMPLES \
 	"delay:fixed_capture_delay_samples"
 #define AEC_DELAY_FIXED_CAPTURE_DELAY_SAMPLES_VALUE 0
@@ -124,12 +114,8 @@
 #define AEC_ERLE_NUM_SECTIONS_VALUE 1
 
 // EpStrength
-#define AEC_EP_STRENGTH_LF "ep_strength:lf"
-#define AEC_EP_STRENGTH_LF_VALUE 1.f
-#define AEC_EP_STRENGTH_MF "ep_strength:mf"
-#define AEC_EP_STRENGTH_MF_VALUE 1.f
-#define AEC_EP_STRENGTH_HF "ep_strength:hf"
-#define AEC_EP_STRENGTH_HF_VALUE 1.f
+#define AEC_EP_STRENGTH_DEFAULT_GAIN "ep_strength:default_gain"
+#define AEC_EP_STRENGTH_DEFAULT_GAIN_VALUE 1.f
 #define AEC_EP_STRENGTH_DEFAULT_LEN "ep_strength:default_len"
 #define AEC_EP_STRENGTH_DEFAULT_LEN_VALUE 0.83f
 #define AEC_EP_STRENGTH_REVERB_BASED_ON_RENDER \
@@ -175,17 +161,6 @@
 #define AEC_RENDER_LEVELS_POOR_EXCITATION_RENDER_LIMIT_DS8_VALUE 20.f
 
 // Echo removal controls
-#define AEC_ECHO_REMOVAL_CTL_INITIAL_GAIN "echo_removal_control:initial_gain"
-#define AEC_ECHO_REMOVAL_CTL_INITIAL_GAIN_VALUE 0.0f
-#define AEC_ECHO_REMOVAL_CTL_FIRST_NON_ZERO_GAIN \
-	"echo_removal_control:first_non_zero_gain"
-#define AEC_ECHO_REMOVAL_CTL_FIRST_NON_ZERO_GAIN_VALUE 0.001f
-#define AEC_ECHO_REMOVAL_CTL_NON_ZERO_GAIN_BLOCKS \
-	"echo_removal_control:non_zero_gain_blocks"
-#define AEC_ECHO_REMOVAL_CTL_NON_ZERO_GAIN_BLOCKS_VALUE 187
-#define AEC_ECHO_REMOVAL_CTL_FULL_GAIN_BLOCKS \
-	"echo_removal_control:full_gain_blocks"
-#define AEC_ECHO_REMOVAL_CTL_FULL_GAIN_BLOCKS_VALUE 312
 #define AEC_ECHO_REMOVAL_CTL_HAS_CLOCK_DRIFT \
 	"echo_removal_control:has_clock_drift"
 #define AEC_ECHO_REMOVAL_CTL_HAS_CLOCK_DRIFT_VALUE 0
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index df4ba23..5a47245 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -8,59 +8,12 @@
 
 import("../../webrtc.gni")
 import("audio_coding.gni")
-if (!build_with_mozilla) {
+if (rtc_enable_protobuf) {
   import("//third_party/protobuf/proto_library.gni")
 }
 
 visibility = [ ":*" ]
 
-rtc_static_library("audio_format_conversion") {
-  visibility += webrtc_default_visibility
-  sources = [
-    "codecs/audio_format_conversion.cc",
-    "codecs/audio_format_conversion.h",
-  ]
-  deps = [
-    "../..:webrtc_common",
-    "../../api:array_view",
-    "../../api/audio_codecs:audio_codecs_api",
-    "../../rtc_base:checks",
-    "../../rtc_base:rtc_base_approved",
-    "../../rtc_base:sanitizer",
-    "//third_party/abseil-cpp/absl/strings",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
-}
-
-rtc_static_library("rent_a_codec") {
-  # Client code SHOULD NOT USE THIS TARGET, but for now it needs to be public
-  # because there exists client code that uses it.
-  # TODO(bugs.webrtc.org/9808): Move to private visibility as soon as that
-  # client code gets updated.
-  visibility += [ "*" ]
-
-  sources = [
-    "acm2/acm_codec_database.cc",
-    "acm2/acm_codec_database.h",
-    "acm2/rent_a_codec.cc",
-    "acm2/rent_a_codec.h",
-  ]
-  deps = [
-    ":audio_coding_module_typedefs",
-    ":neteq_decoder_enum",
-    "../..:webrtc_common",
-    "../../api:array_view",
-    "../../api/audio_codecs:audio_codecs_api",
-    "../../rtc_base:checks",
-    "../../rtc_base:protobuf_utils",
-    "../../rtc_base:rtc_base_approved",
-    "../../system_wrappers",
-    "//third_party/abseil-cpp/absl/strings",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
-  defines = audio_codec_defines
-}
-
 rtc_source_set("audio_coding_module_typedefs") {
   sources = [
     "include/audio_coding_module_typedefs.h",
@@ -89,8 +42,6 @@
   deps = [
     ":audio_coding_module_typedefs",
     ":neteq",
-    ":neteq_decoder_enum",
-    ":rent_a_codec",
     "..:module_api",
     "..:module_api_public",
     "../..:webrtc_common",
@@ -440,6 +391,7 @@
   deps = [
     ":isac_bwinfo",
     "../..:webrtc_common",
+    "../../api:scoped_refptr",
     "../../api/audio_codecs:audio_codecs_api",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
@@ -815,6 +767,7 @@
     "../../api/audio_codecs/opus:audio_encoder_opus_config",
     "../../common_audio",
     "../../rtc_base:checks",
+    "../../rtc_base:protobuf_utils",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base:rtc_numerics",
     "../../rtc_base:safe_minmax",
@@ -825,7 +778,6 @@
   ]
   public_deps = [
     ":webrtc_opus_c",
-    "../../rtc_base:protobuf_utils",
   ]
 
   defines = audio_codec_defines
@@ -948,23 +900,6 @@
       ":ana_debug_dump_proto",
     ]
   }
-
-  if (!build_with_chromium && is_clang) {
-    # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-    suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-  }
-}
-
-rtc_source_set("neteq_decoder_enum") {
-  sources = [
-    "neteq/neteq_decoder_enum.cc",
-    "neteq/neteq_decoder_enum.h",
-  ]
-  deps = [
-    "../../api/audio_codecs:audio_codecs_api",
-    "../../rtc_base:rtc_base_approved",
-    "//third_party/abseil-cpp/absl/types:optional",
-  ]
 }
 
 rtc_static_library("neteq") {
@@ -1003,6 +938,8 @@
     "neteq/expand.h",
     "neteq/expand_uma_logger.cc",
     "neteq/expand_uma_logger.h",
+    "neteq/histogram.cc",
+    "neteq/histogram.h",
     "neteq/include/neteq.h",
     "neteq/merge.cc",
     "neteq/merge.h",
@@ -1039,13 +976,13 @@
 
   deps = [
     ":audio_coding_module_typedefs",
-    ":neteq_decoder_enum",
     ":webrtc_cng",
     "..:module_api",
     "..:module_api_public",
     "../..:webrtc_common",
     "../../api:array_view",
     "../../api:libjingle_peerconnection_api",
+    "../../api:scoped_refptr",
     "../../api/audio:audio_frame_api",
     "../../api/audio_codecs:audio_codecs_api",
     "../../common_audio",
@@ -1059,6 +996,7 @@
     "../../rtc_base/system:fallthrough",
     "../../system_wrappers:field_trial",
     "../../system_wrappers:metrics",
+    "//third_party/abseil-cpp/absl/memory",
     "//third_party/abseil-cpp/absl/strings",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
@@ -1092,10 +1030,10 @@
     "../../api:neteq_simulator_api",
     "../../api/audio:audio_frame_api",
     "../../api/audio_codecs:audio_codecs_api",
-    "../../api/audio_codecs:builtin_audio_decoder_factory",
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
     "../rtp_rtcp",
+    "../rtp_rtcp:rtp_rtcp_format",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
   defines = audio_codec_defines
@@ -1120,11 +1058,6 @@
     "neteq/tools/rtp_generator.h",
   ]
 
-  if (!build_with_chromium && is_clang) {
-    # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-    suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-  }
-
   deps = [
     ":pcm16b",
     "../..:webrtc_common",
@@ -1170,11 +1103,6 @@
     "neteq/tools/neteq_stats_plotter.h",
   ]
 
-  if (!build_with_chromium && is_clang) {
-    # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-    suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-  }
-
   deps = [
     "..:module_api",
     "../..:webrtc_common",
@@ -1220,11 +1148,6 @@
       "neteq/tools/rtc_event_log_source.h",
     ]
 
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
-
     deps = [
       ":neteq_tools_minimal",
       "../../logging:rtc_event_log_parser",
@@ -1232,6 +1155,7 @@
       "../../rtc_base:rtc_base_approved",
       "../rtp_rtcp",
       "../rtp_rtcp:rtp_rtcp_format",
+      "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/types:optional",
     ]
     public_deps = [
@@ -1343,14 +1267,11 @@
       "test/opus_test.cc",
       "test/opus_test.h",
       "test/target_delay_unittest.cc",
-      "test/utility.cc",
-      "test/utility.h",
     ]
     deps = [
       ":audio_coding",
       ":audio_coding_module_typedefs",
       ":audio_encoder_cng",
-      ":audio_format_conversion",
       ":pcm16b_c",
       ":red",
       ":webrtc_opus_c",
@@ -1379,14 +1300,11 @@
       "../../system_wrappers",
       "../../test:fileutils",
       "../../test:test_support",
+      "//third_party/abseil-cpp/absl/memory",
       "//third_party/abseil-cpp/absl/strings",
       "//third_party/abseil-cpp/absl/types:optional",
     ]
     defines = audio_coding_defines
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 
   rtc_source_set("audio_coding_perf_tests") {
@@ -1402,7 +1320,6 @@
       ":neteq_test_tools",
       "../..:webrtc_common",
       "../../api/audio_codecs/opus:audio_encoder_opus",
-      "../../rtc_base:protobuf_utils",
       "../../rtc_base:rtc_base_approved",
       "../../system_wrappers",
       "../../system_wrappers:field_trial",
@@ -1410,11 +1327,6 @@
       "../../test:perf_test",
       "../../test:test_support",
     ]
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 
   rtc_source_set("acm_receive_test") {
@@ -1427,9 +1339,9 @@
     defines = audio_coding_defines
 
     deps = audio_coding_deps + [
+             "../../api:scoped_refptr",
              "..:module_api",
              ":audio_coding",
-             ":audio_format_conversion",
              "../../api/audio_codecs:audio_codecs_api",
              "../../api/audio_codecs:builtin_audio_decoder_factory",
              ":neteq_tools",
@@ -1453,7 +1365,6 @@
              "../../api/audio:audio_frame_api",
              "../../rtc_base:checks",
              ":audio_coding",
-             ":audio_format_conversion",
              ":neteq_tools",
              "../../api/audio_codecs:builtin_audio_decoder_factory",
              "../../api/audio_codecs:builtin_audio_encoder_factory",
@@ -1495,7 +1406,6 @@
              "../../api/audio_codecs:audio_codecs_api",
              "../../api/audio_codecs/opus:audio_encoder_opus",
              "../../common_audio",
-             "../../rtc_base:protobuf_utils",
              "../../rtc_base/system:arch",
              "../../test:test_main",
              "//testing/gtest",
@@ -1528,22 +1438,20 @@
       deps = [
         "../../rtc_base:checks",
         "../../test:fileutils",
+        "//third_party/abseil-cpp/absl/types:optional",
       ]
       sources = [
         "neteq/tools/neteq_test_factory.cc",
         "neteq/tools/neteq_test_factory.h",
       ]
 
-      if (!build_with_chromium && is_clang) {
-        # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-        suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-      }
-
       deps += [
         ":neteq",
         ":neteq_test_tools",
         "../..:webrtc_common",
+        "../../api/audio_codecs:builtin_audio_decoder_factory",
         "../../rtc_base:rtc_base_approved",
+        "../../test:audio_codec_mocks",
         "../../test:test_support",
         "//third_party/abseil-cpp/absl/memory",
       ]
@@ -1594,11 +1502,6 @@
       "codecs/tools/audio_codec_speed_test.h",
     ]
 
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
-
     data = audio_codec_speed_tests_resources
 
     if (is_android) {
@@ -1626,17 +1529,10 @@
   rtc_source_set("neteq_test_support") {
     testonly = true
     sources = [
-      "neteq/tools/neteq_external_decoder_test.cc",
-      "neteq/tools/neteq_external_decoder_test.h",
       "neteq/tools/neteq_performance_test.cc",
       "neteq/tools/neteq_performance_test.h",
     ]
 
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
-
     deps = [
       ":neteq",
       ":neteq_test_tools",
@@ -1661,11 +1557,6 @@
       "neteq/tools/neteq_quality_test.h",
     ]
 
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
-
     deps = [
       ":neteq",
       ":neteq_test_tools",
@@ -2033,6 +1924,7 @@
       "neteq/dtmf_buffer_unittest.cc",
       "neteq/dtmf_tone_generator_unittest.cc",
       "neteq/expand_unittest.cc",
+      "neteq/histogram_unittest.cc",
       "neteq/merge_unittest.cc",
       "neteq/mock/mock_buffer_level_filter.h",
       "neteq/mock/mock_decoder_database.h",
@@ -2041,13 +1933,12 @@
       "neteq/mock/mock_dtmf_buffer.h",
       "neteq/mock/mock_dtmf_tone_generator.h",
       "neteq/mock/mock_expand.h",
-      "neteq/mock/mock_external_decoder_pcm16b.h",
+      "neteq/mock/mock_histogram.h",
       "neteq/mock/mock_packet_buffer.h",
       "neteq/mock/mock_red_payload_splitter.h",
       "neteq/mock/mock_statistics_calculator.h",
       "neteq/nack_tracker_unittest.cc",
       "neteq/neteq_decoder_plc_unittest.cc",
-      "neteq/neteq_external_decoder_unittest.cc",
       "neteq/neteq_impl_unittest.cc",
       "neteq/neteq_network_stats_unittest.cc",
       "neteq/neteq_stereo_unittest.cc",
@@ -2072,7 +1963,6 @@
       ":audio_coding",
       ":audio_coding_module_typedefs",
       ":audio_encoder_cng",
-      ":audio_format_conversion",
       ":audio_network_adaptor",
       ":g711",
       ":ilbc",
@@ -2086,10 +1976,10 @@
       ":neteq_test_tools",
       ":pcm16b",
       ":red",
-      ":rent_a_codec",
       ":webrtc_cng",
       ":webrtc_opus",
       "..:module_api",
+      "..:module_api_public",
       "../..:webrtc_common",
       "../../api/audio:audio_frame_api",
       "../../api/audio_codecs:audio_codecs_api",
@@ -2105,11 +1995,11 @@
       "../../logging:rtc_event_log_api",
       "../../modules/rtp_rtcp:rtp_rtcp_format",
       "../../rtc_base:checks",
-      "../../rtc_base:protobuf_utils",
       "../../rtc_base:rtc_base",
       "../../rtc_base:rtc_base_approved",
       "../../rtc_base:rtc_base_tests_utils",
       "../../rtc_base:sanitizer",
+      "../../rtc_base:timeutils",
       "../../rtc_base/system:arch",
       "../../system_wrappers",
       "../../system_wrappers:cpu_features_api",
@@ -2135,11 +2025,6 @@
         ":neteq_unittest_proto",
       ]
     }
-
-    if (!build_with_chromium && is_clang) {
-      # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
-      suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
-    }
   }
 }
 
diff --git a/modules/audio_coding/acm2/acm_codec_database.cc b/modules/audio_coding/acm2/acm_codec_database.cc
deleted file mode 100644
index cada80c..0000000
--- a/modules/audio_coding/acm2/acm_codec_database.cc
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- *  Copyright (c) 2012 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.
- */
-
-/*
- * This file generates databases with information about all supported audio
- * codecs.
- */
-
-// TODO(tlegrand): Change constant input pointers in all functions to constant
-// references, where appropriate.
-#include "modules/audio_coding/acm2/acm_codec_database.h"
-
-#include "absl/strings/match.h"
-#include "api/array_view.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
-
-#if ((defined WEBRTC_CODEC_ISAC) && (defined WEBRTC_CODEC_ISACFX))
-#error iSAC and iSACFX codecs cannot be enabled at the same time
-#endif
-
-namespace webrtc {
-
-namespace acm2 {
-
-namespace {
-
-// Checks if the bitrate is valid for iSAC.
-bool IsISACRateValid(int rate) {
-  return (rate == -1) || ((rate <= 56000) && (rate >= 10000));
-}
-
-// Checks if the bitrate is valid for iLBC.
-bool IsILBCRateValid(int rate, int frame_size_samples) {
-  if (((frame_size_samples == 240) || (frame_size_samples == 480)) &&
-      (rate == 13300)) {
-    return true;
-  } else if (((frame_size_samples == 160) || (frame_size_samples == 320)) &&
-             (rate == 15200)) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-// Checks if the bitrate is valid for Opus.
-bool IsOpusRateValid(int rate) {
-  return (rate >= 6000) && (rate <= 510000);
-}
-
-}  // namespace
-
-// Not yet used payload-types.
-// 83,  82,  81, 80, 79,  78,  77,  76,  75,  74,  73,  72,  71,  70,  69, 68,
-// 67, 66, 65
-
-const CodecInst ACMCodecDB::database_[] = {
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
-    {103, "ISAC", 16000, 480, 1, 32000},
-#if (defined(WEBRTC_CODEC_ISAC))
-    {104, "ISAC", 32000, 960, 1, 56000},
-#endif
-#endif
-    // Mono
-    {107, "L16", 8000, 80, 1, 128000},
-    {108, "L16", 16000, 160, 1, 256000},
-    {109, "L16", 32000, 320, 1, 512000},
-    // Stereo
-    {111, "L16", 8000, 80, 2, 128000},
-    {112, "L16", 16000, 160, 2, 256000},
-    {113, "L16", 32000, 320, 2, 512000},
-    // G.711, PCM mu-law and A-law.
-    // Mono
-    {0, "PCMU", 8000, 160, 1, 64000},
-    {8, "PCMA", 8000, 160, 1, 64000},
-    // Stereo
-    {110, "PCMU", 8000, 160, 2, 64000},
-    {118, "PCMA", 8000, 160, 2, 64000},
-#ifdef WEBRTC_CODEC_ILBC
-    {102, "ILBC", 8000, 240, 1, 13300},
-#endif
-    // Mono
-    {9, "G722", 16000, 320, 1, 64000},
-    // Stereo
-    {119, "G722", 16000, 320, 2, 64000},
-#ifdef WEBRTC_CODEC_OPUS
-    // Opus internally supports 48, 24, 16, 12, 8 kHz.
-    // Mono and stereo.
-    {120, "opus", 48000, 960, 2, 64000},
-#endif
-    // Comfort noise for four different sampling frequencies.
-    {13, "CN", 8000, 240, 1, 0},
-    {98, "CN", 16000, 480, 1, 0},
-    {99, "CN", 32000, 960, 1, 0},
-#ifdef ENABLE_48000_HZ
-    {100, "CN", 48000, 1440, 1, 0},
-#endif
-    {106, "telephone-event", 8000, 240, 1, 0},
-    {114, "telephone-event", 16000, 240, 1, 0},
-    {115, "telephone-event", 32000, 240, 1, 0},
-    {116, "telephone-event", 48000, 240, 1, 0},
-#ifdef WEBRTC_CODEC_RED
-    {127, "red", 8000, 0, 1, 0},
-#endif
-    // To prevent compile errors due to trailing commas.
-    {-1, "Null", -1, -1, 0, -1}};
-
-// Create database with all codec settings at compile time.
-// Each entry needs the following parameters in the given order:
-// Number of allowed packet sizes, a vector with the allowed packet sizes,
-// Basic block samples, max number of channels that are supported.
-const ACMCodecDB::CodecSettings ACMCodecDB::codec_settings_[] = {
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
-    {2, {480, 960}, 0, 1},
-#if (defined(WEBRTC_CODEC_ISAC))
-    {1, {960}, 0, 1},
-#endif
-#endif
-    // Mono
-    {4, {80, 160, 240, 320}, 0, 2},
-    {4, {160, 320, 480, 640}, 0, 2},
-    {2, {320, 640}, 0, 2},
-    // Stereo
-    {4, {80, 160, 240, 320}, 0, 2},
-    {4, {160, 320, 480, 640}, 0, 2},
-    {2, {320, 640}, 0, 2},
-    // G.711, PCM mu-law and A-law.
-    // Mono
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-    // Stereo
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-    {6, {80, 160, 240, 320, 400, 480}, 0, 2},
-#ifdef WEBRTC_CODEC_ILBC
-    {4, {160, 240, 320, 480}, 0, 1},
-#endif
-    // Mono
-    {6, {160, 320, 480, 640, 800, 960}, 0, 2},
-    // Stereo
-    {6, {160, 320, 480, 640, 800, 960}, 0, 2},
-#ifdef WEBRTC_CODEC_OPUS
-// Opus supports frames shorter than 10ms,
-// but it doesn't help us to use them.
-// Mono and stereo.
-#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
-    {5, {480, 960, 1920, 2880, 5760}, 0, 2},
-#else
-    {4, {480, 960, 1920, 2880}, 0, 2},
-#endif
-#endif
-    // Comfort noise for three different sampling frequencies.
-    {1, {240}, 240, 1},
-    {1, {480}, 480, 1},
-    {1, {960}, 960, 1},
-// TODO(solenberg): What is this flag? It is never set in the build files.
-#ifdef ENABLE_48000_HZ
-    {1, {1440}, 1440, 1},
-#endif
-    {1, {240}, 240, 1},
-    {1, {240}, 240, 1},
-    {1, {240}, 240, 1},
-    {1, {240}, 240, 1},
-#ifdef WEBRTC_CODEC_RED
-    {1, {0}, 0, 1},
-#endif
-    // To prevent compile errors due to trailing commas.
-    {-1, {-1}, -1, 0}};
-
-// Create a database of all NetEQ decoders at compile time.
-const NetEqDecoder ACMCodecDB::neteq_decoders_[] = {
-#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
-    NetEqDecoder::kDecoderISAC,
-#if (defined(WEBRTC_CODEC_ISAC))
-    NetEqDecoder::kDecoderISACswb,
-#endif
-#endif
-    // Mono
-    NetEqDecoder::kDecoderPCM16B, NetEqDecoder::kDecoderPCM16Bwb,
-    NetEqDecoder::kDecoderPCM16Bswb32kHz,
-    // Stereo
-    NetEqDecoder::kDecoderPCM16B_2ch, NetEqDecoder::kDecoderPCM16Bwb_2ch,
-    NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch,
-    // G.711, PCM mu-las and A-law.
-    // Mono
-    NetEqDecoder::kDecoderPCMu, NetEqDecoder::kDecoderPCMa,
-    // Stereo
-    NetEqDecoder::kDecoderPCMu_2ch, NetEqDecoder::kDecoderPCMa_2ch,
-#ifdef WEBRTC_CODEC_ILBC
-    NetEqDecoder::kDecoderILBC,
-#endif
-    // Mono
-    NetEqDecoder::kDecoderG722,
-    // Stereo
-    NetEqDecoder::kDecoderG722_2ch,
-#ifdef WEBRTC_CODEC_OPUS
-    // Mono and stereo.
-    NetEqDecoder::kDecoderOpus,
-#endif
-    // Comfort noise for three different sampling frequencies.
-    NetEqDecoder::kDecoderCNGnb, NetEqDecoder::kDecoderCNGwb,
-    NetEqDecoder::kDecoderCNGswb32kHz,
-#ifdef ENABLE_48000_HZ
-    NetEqDecoder::kDecoderCNGswb48kHz,
-#endif
-    NetEqDecoder::kDecoderAVT, NetEqDecoder::kDecoderAVT16kHz,
-    NetEqDecoder::kDecoderAVT32kHz, NetEqDecoder::kDecoderAVT48kHz,
-#ifdef WEBRTC_CODEC_RED
-    NetEqDecoder::kDecoderRED,
-#endif
-};
-
-// Enumerator for error codes when asking for codec database id.
-enum {
-  kInvalidCodec = -10,
-  kInvalidPayloadtype = -30,
-  kInvalidPacketSize = -40,
-  kInvalidRate = -50
-};
-
-// Gets the codec id number from the database. If there is some mismatch in
-// the codec settings, the function will return an error code.
-// NOTE! The first mismatch found will generate the return value.
-int ACMCodecDB::CodecNumber(const CodecInst& codec_inst) {
-  // Look for a matching codec in the database.
-  int codec_id = CodecId(codec_inst);
-
-  // Checks if we found a matching codec.
-  if (codec_id == -1) {
-    return kInvalidCodec;
-  }
-
-  // Checks the validity of payload type
-  if (!RentACodec::IsPayloadTypeValid(codec_inst.pltype)) {
-    return kInvalidPayloadtype;
-  }
-
-  // Comfort Noise is special case, packet-size & rate is not checked.
-  if (absl::EqualsIgnoreCase(database_[codec_id].plname, "CN")) {
-    return codec_id;
-  }
-
-  // RED is special case, packet-size & rate is not checked.
-  if (absl::EqualsIgnoreCase(database_[codec_id].plname, "red")) {
-    return codec_id;
-  }
-
-  // Checks the validity of packet size.
-  if (codec_settings_[codec_id].num_packet_sizes > 0) {
-    bool packet_size_ok = false;
-    int i;
-    int packet_size_samples;
-    for (i = 0; i < codec_settings_[codec_id].num_packet_sizes; i++) {
-      packet_size_samples = codec_settings_[codec_id].packet_sizes_samples[i];
-      if (codec_inst.pacsize == packet_size_samples) {
-        packet_size_ok = true;
-        break;
-      }
-    }
-
-    if (!packet_size_ok) {
-      return kInvalidPacketSize;
-    }
-  }
-
-  if (codec_inst.pacsize < 1) {
-    return kInvalidPacketSize;
-  }
-
-  // Check the validity of rate. Codecs with multiple rates have their own
-  // function for this.
-  if (absl::EqualsIgnoreCase("isac", codec_inst.plname)) {
-    return IsISACRateValid(codec_inst.rate) ? codec_id : kInvalidRate;
-  } else if (absl::EqualsIgnoreCase("ilbc", codec_inst.plname)) {
-    return IsILBCRateValid(codec_inst.rate, codec_inst.pacsize) ? codec_id
-                                                                : kInvalidRate;
-  } else if (absl::EqualsIgnoreCase("opus", codec_inst.plname)) {
-    return IsOpusRateValid(codec_inst.rate) ? codec_id : kInvalidRate;
-  }
-
-  return database_[codec_id].rate == codec_inst.rate ? codec_id : kInvalidRate;
-}
-
-// Looks for a matching payload name, frequency, and channels in the
-// codec list. Need to check all three since some codecs have several codec
-// entries with different frequencies and/or channels.
-// Does not check other codec settings, such as payload type and packet size.
-// Returns the id of the codec, or -1 if no match is found.
-int ACMCodecDB::CodecId(const CodecInst& codec_inst) {
-  return (CodecId(codec_inst.plname, codec_inst.plfreq, codec_inst.channels));
-}
-
-int ACMCodecDB::CodecId(const char* payload_name,
-                        int frequency,
-                        size_t channels) {
-  for (const CodecInst& ci : database_) {
-    bool name_match = false;
-    bool frequency_match = false;
-    bool channels_match = false;
-
-    // Payload name, sampling frequency and number of channels need to match.
-    // NOTE! If |frequency| is -1, the frequency is not applicable, and is
-    // always treated as true, like for RED.
-    name_match = absl::EqualsIgnoreCase(ci.plname, payload_name);
-    frequency_match = (frequency == ci.plfreq) || (frequency == -1);
-    // The number of channels must match for all codecs but Opus.
-    if (!absl::EqualsIgnoreCase(payload_name, "opus")) {
-      channels_match = (channels == ci.channels);
-    } else {
-      // For opus we just check that number of channels is valid.
-      channels_match = (channels == 1 || channels == 2);
-    }
-
-    if (name_match && frequency_match && channels_match) {
-      // We have found a matching codec in the list.
-      return &ci - database_;
-    }
-  }
-
-  // We didn't find a matching codec.
-  return -1;
-}
-// Gets codec id number from database for the receiver.
-int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst) {
-  // Look for a matching codec in the database.
-  return CodecId(codec_inst);
-}
-
-}  // namespace acm2
-
-}  // namespace webrtc
diff --git a/modules/audio_coding/acm2/acm_codec_database.h b/modules/audio_coding/acm2/acm_codec_database.h
deleted file mode 100644
index ee6bb46..0000000
--- a/modules/audio_coding/acm2/acm_codec_database.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- *  Copyright (c) 2012 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.
- */
-
-/*
- * This file generates databases with information about all supported audio
- * codecs.
- */
-
-#ifndef MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_
-#define MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_
-
-#include "common_types.h"  // NOLINT(build/include)
-#include "modules/audio_coding/acm2/rent_a_codec.h"
-
-namespace webrtc {
-
-namespace acm2 {
-
-// TODO(tlegrand): replace class ACMCodecDB with a namespace.
-class ACMCodecDB {
- public:
-  // kMaxNumCodecs - Maximum number of codecs that can be activated in one
-  //                 build.
-  // kMaxNumPacketSize - Maximum number of allowed packet sizes for one codec.
-  // These might need to be increased if adding a new codec to the database
-  static const int kMaxNumCodecs = 50;
-  static const int kMaxNumPacketSize = 6;
-
-  // Codec specific settings
-  //
-  // num_packet_sizes     - number of allowed packet sizes.
-  // packet_sizes_samples - list of the allowed packet sizes.
-  // basic_block_samples  - assigned a value different from 0 if the codec
-  //                        requires to be fed with a specific number of samples
-  //                        that can be different from packet size.
-  // channel_support      - number of channels supported to encode;
-  //                        1 = mono, 2 = stereo, etc.
-  struct CodecSettings {
-    int num_packet_sizes;
-    int packet_sizes_samples[kMaxNumPacketSize];
-    int basic_block_samples;
-    size_t channel_support;
-  };
-
-  // Returns codec id from database, given the information received in the input
-  // [codec_inst].
-  // Input:
-  //   [codec_inst] - Information about the codec for which we require the
-  //                  database id.
-  // Return:
-  //   codec id if successful, otherwise < 0.
-  static int CodecNumber(const CodecInst& codec_inst);
-  static int CodecId(const CodecInst& codec_inst);
-  static int CodecId(const char* payload_name, int frequency, size_t channels);
-  static int ReceiverCodecNumber(const CodecInst& codec_inst);
-
-  // Databases with information about the supported codecs
-  // database_ - stored information about all codecs: payload type, name,
-  //             sampling frequency, packet size in samples, default channel
-  //             support, and default rate.
-  // codec_settings_ - stored codec settings: number of allowed packet sizes,
-  //                   a vector with the allowed packet sizes, basic block
-  //                   samples, and max number of channels that are supported.
-  // neteq_decoders_ - list of supported decoders in NetEQ.
-  static const CodecInst database_[kMaxNumCodecs];
-  static const CodecSettings codec_settings_[kMaxNumCodecs];
-  static const NetEqDecoder neteq_decoders_[kMaxNumCodecs];
-};
-
-}  // namespace acm2
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_ACM2_ACM_CODEC_DATABASE_H_
diff --git a/modules/audio_coding/acm2/acm_receive_test.cc b/modules/audio_coding/acm2/acm_receive_test.cc
index c149ec1..078c991 100644
--- a/modules/audio_coding/acm2/acm_receive_test.cc
+++ b/modules/audio_coding/acm2/acm_receive_test.cc
@@ -14,9 +14,7 @@
 
 #include <memory>
 
-#include "absl/strings/match.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "modules/audio_coding/codecs/audio_format_conversion.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
@@ -28,89 +26,6 @@
 namespace test {
 
 namespace {
-// Returns true if the codec should be registered, otherwise false. Changes
-// the number of channels for the Opus codec to always be 1.
-bool ModifyAndUseThisCodec(CodecInst* codec_param) {
-  if (absl::EqualsIgnoreCase(codec_param->plname, "CN") &&
-      codec_param->plfreq == 48000)
-    return false;  // Skip 48 kHz comfort noise.
-
-  if (absl::EqualsIgnoreCase(codec_param->plname, "telephone-event"))
-    return false;  // Skip DTFM.
-
-  return true;
-}
-
-// Remaps payload types from ACM's default to those used in the resource file
-// neteq_universal_new.rtp. Returns true if the codec should be registered,
-// otherwise false. The payload types are set as follows (all are mono codecs):
-// PCMu = 0;
-// PCMa = 8;
-// Comfort noise 8 kHz = 13
-// Comfort noise 16 kHz = 98
-// Comfort noise 32 kHz = 99
-// iLBC = 102
-// iSAC wideband = 103
-// iSAC super-wideband = 104
-// AVT/DTMF = 106
-// RED = 117
-// PCM16b 8 kHz = 93
-// PCM16b 16 kHz = 94
-// PCM16b 32 kHz = 95
-// G.722 = 94
-bool RemapPltypeAndUseThisCodec(const char* plname,
-                                int plfreq,
-                                size_t channels,
-                                int* pltype) {
-  if (channels != 1)
-    return false;  // Don't use non-mono codecs.
-
-  // Re-map pltypes to those used in the NetEq test files.
-  if (absl::EqualsIgnoreCase(plname, "PCMU") && plfreq == 8000) {
-    *pltype = 0;
-  } else if (absl::EqualsIgnoreCase(plname, "PCMA") && plfreq == 8000) {
-    *pltype = 8;
-  } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 8000) {
-    *pltype = 13;
-  } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 16000) {
-    *pltype = 98;
-  } else if (absl::EqualsIgnoreCase(plname, "CN") && plfreq == 32000) {
-    *pltype = 99;
-  } else if (absl::EqualsIgnoreCase(plname, "ILBC")) {
-    *pltype = 102;
-  } else if (absl::EqualsIgnoreCase(plname, "ISAC") && plfreq == 16000) {
-    *pltype = 103;
-  } else if (absl::EqualsIgnoreCase(plname, "ISAC") && plfreq == 32000) {
-    *pltype = 104;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 8000) {
-    *pltype = 106;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 16000) {
-    *pltype = 114;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 32000) {
-    *pltype = 115;
-  } else if (absl::EqualsIgnoreCase(plname, "telephone-event") &&
-             plfreq == 48000) {
-    *pltype = 116;
-  } else if (absl::EqualsIgnoreCase(plname, "red")) {
-    *pltype = 117;
-  } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 8000) {
-    *pltype = 93;
-  } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 16000) {
-    *pltype = 94;
-  } else if (absl::EqualsIgnoreCase(plname, "L16") && plfreq == 32000) {
-    *pltype = 95;
-  } else if (absl::EqualsIgnoreCase(plname, "G722")) {
-    *pltype = 9;
-  } else {
-    // Don't use any other codecs.
-    return false;
-  }
-  return true;
-}
-
 AudioCodingModule::Config MakeAcmConfig(
     Clock* clock,
     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory) {
@@ -119,7 +34,6 @@
   config.decoder_factory = std::move(decoder_factory);
   return config;
 }
-
 }  // namespace
 
 AcmReceiveTestOldApi::AcmReceiveTestOldApi(
@@ -139,36 +53,43 @@
 AcmReceiveTestOldApi::~AcmReceiveTestOldApi() = default;
 
 void AcmReceiveTestOldApi::RegisterDefaultCodecs() {
-  CodecInst my_codec_param;
-  for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
-    ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
-    if (ModifyAndUseThisCodec(&my_codec_param)) {
-      ASSERT_EQ(true,
-                acm_->RegisterReceiveCodec(my_codec_param.pltype,
-                                           CodecInstToSdp(my_codec_param)))
-          << "Couldn't register receive codec.\n";
-    }
-  }
+  acm_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
+                          {104, {"ISAC", 32000, 1}},
+                          {107, {"L16", 8000, 1}},
+                          {108, {"L16", 16000, 1}},
+                          {109, {"L16", 32000, 1}},
+                          {111, {"L16", 8000, 2}},
+                          {112, {"L16", 16000, 2}},
+                          {113, {"L16", 32000, 2}},
+                          {0, {"PCMU", 8000, 1}},
+                          {110, {"PCMU", 8000, 2}},
+                          {8, {"PCMA", 8000, 1}},
+                          {118, {"PCMA", 8000, 2}},
+                          {102, {"ILBC", 8000, 1}},
+                          {9, {"G722", 8000, 1}},
+                          {119, {"G722", 8000, 2}},
+                          {120, {"OPUS", 48000, 2, {{"stereo", "1"}}}},
+                          {13, {"CN", 8000, 1}},
+                          {98, {"CN", 16000, 1}},
+                          {99, {"CN", 32000, 1}}});
 }
 
+// Remaps payload types from ACM's default to those used in the resource file
+// neteq_universal_new.rtp.
 void AcmReceiveTestOldApi::RegisterNetEqTestCodecs() {
-  CodecInst my_codec_param;
-  for (int n = 0; n < acm_->NumberOfCodecs(); n++) {
-    ASSERT_EQ(0, acm_->Codec(n, &my_codec_param)) << "Failed to get codec.";
-    if (!ModifyAndUseThisCodec(&my_codec_param)) {
-      // Skip this codec.
-      continue;
-    }
-
-    if (RemapPltypeAndUseThisCodec(my_codec_param.plname, my_codec_param.plfreq,
-                                   my_codec_param.channels,
-                                   &my_codec_param.pltype)) {
-      ASSERT_EQ(true,
-                acm_->RegisterReceiveCodec(my_codec_param.pltype,
-                                           CodecInstToSdp(my_codec_param)))
-          << "Couldn't register receive codec.\n";
-    }
-  }
+  acm_->SetReceiveCodecs({{103, {"ISAC", 16000, 1}},
+                          {104, {"ISAC", 32000, 1}},
+                          {93, {"L16", 8000, 1}},
+                          {94, {"L16", 16000, 1}},
+                          {95, {"L16", 32000, 1}},
+                          {0, {"PCMU", 8000, 1}},
+                          {8, {"PCMA", 8000, 1}},
+                          {102, {"ILBC", 8000, 1}},
+                          {9, {"G722", 8000, 1}},
+                          {120, {"OPUS", 48000, 2}},
+                          {13, {"CN", 8000, 1}},
+                          {98, {"CN", 16000, 1}},
+                          {99, {"CN", 32000, 1}}});
 }
 
 void AcmReceiveTestOldApi::Run() {
@@ -199,18 +120,15 @@
       AfterGetAudio();
     }
 
-    // Insert packet after converting from RTPHeader to WebRtcRTPHeader.
-    WebRtcRTPHeader header;
-    header.header = packet->header();
-    header.frameType = kAudioFrameSpeech;
-    EXPECT_EQ(0,
-              acm_->IncomingPacket(
-                  packet->payload(),
-                  static_cast<int32_t>(packet->payload_length_bytes()), header))
+    EXPECT_EQ(0, acm_->IncomingPacket(
+                     packet->payload(),
+                     static_cast<int32_t>(packet->payload_length_bytes()),
+                     packet->header()))
         << "Failure when inserting packet:" << std::endl
-        << "  PT = " << static_cast<int>(header.header.payloadType) << std::endl
-        << "  TS = " << header.header.timestamp << std::endl
-        << "  SN = " << header.header.sequenceNumber;
+        << "  PT = " << static_cast<int>(packet->header().payloadType)
+        << std::endl
+        << "  TS = " << packet->header().timestamp << std::endl
+        << "  SN = " << packet->header().sequenceNumber;
   }
 }
 
diff --git a/modules/audio_coding/acm2/acm_receive_test.h b/modules/audio_coding/acm2/acm_receive_test.h
index 83ffcb3..9d004c6 100644
--- a/modules/audio_coding/acm2/acm_receive_test.h
+++ b/modules/audio_coding/acm2/acm_receive_test.h
@@ -16,14 +16,13 @@
 #include <string>
 
 #include "api/audio_codecs/audio_decoder_factory.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "api/scoped_refptr.h"
+#include "rtc_base/constructor_magic.h"
 #include "system_wrappers/include/clock.h"
 
 namespace webrtc {
 class AudioCodingModule;
 class AudioDecoder;
-struct CodecInst;
 
 namespace test {
 class AudioSink;
@@ -34,7 +33,8 @@
   enum NumOutputChannels : size_t {
     kArbitraryChannels = 0,
     kMonoOutput = 1,
-    kStereoOutput = 2
+    kStereoOutput = 2,
+    kQuadOutput = 4
   };
 
   AcmReceiveTestOldApi(PacketSource* packet_source,
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index d3af7c0..da7d621 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -20,9 +20,7 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "modules/audio_coding/acm2/acm_resampler.h"
 #include "modules/audio_coding/acm2/call_statistics.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
 #include "modules/include/module_common_types.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
@@ -60,56 +58,66 @@
   return -1;
 }
 
+bool AcmReceiver::SetBaseMinimumDelayMs(int delay_ms) {
+  return neteq_->SetBaseMinimumDelayMs(delay_ms);
+}
+
+int AcmReceiver::GetBaseMinimumDelayMs() const {
+  return neteq_->GetBaseMinimumDelayMs();
+}
+
 absl::optional<int> AcmReceiver::last_packet_sample_rate_hz() const {
   rtc::CritScope lock(&crit_sect_);
-  return last_packet_sample_rate_hz_;
+  if (!last_decoder_) {
+    return absl::nullopt;
+  }
+  return last_decoder_->second.clockrate_hz;
 }
 
 int AcmReceiver::last_output_sample_rate_hz() const {
   return neteq_->last_output_sample_rate_hz();
 }
 
-int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
+int AcmReceiver::InsertPacket(const RTPHeader& rtp_header,
                               rtc::ArrayView<const uint8_t> incoming_payload) {
-  uint32_t receive_timestamp = 0;
-  const RTPHeader* header = &rtp_header.header;  // Just a shorthand.
-
   if (incoming_payload.empty()) {
-    neteq_->InsertEmptyPacket(rtp_header.header);
+    neteq_->InsertEmptyPacket(rtp_header);
     return 0;
   }
 
+  int payload_type = rtp_header.payloadType;
+  auto format = neteq_->GetDecoderFormat(payload_type);
+  if (format && absl::EqualsIgnoreCase(format->name, "red")) {
+    // This is a RED packet. Get the format of the audio codec.
+    payload_type = incoming_payload[0] & 0x7f;
+    format = neteq_->GetDecoderFormat(payload_type);
+  }
+  if (!format) {
+    RTC_LOG_F(LS_ERROR) << "Payload-type "
+                        << payload_type
+                        << " is not registered.";
+    return -1;
+  }
+
   {
     rtc::CritScope lock(&crit_sect_);
-
-    const absl::optional<CodecInst> ci =
-        RtpHeaderToDecoder(*header, incoming_payload[0]);
-    if (!ci) {
-      RTC_LOG_F(LS_ERROR) << "Payload-type "
-                          << static_cast<int>(header->payloadType)
-                          << " is not registered.";
-      return -1;
-    }
-    receive_timestamp = NowInTimestamp(ci->plfreq);
-
-    if (absl::EqualsIgnoreCase(ci->plname, "cn")) {
-      if (last_audio_decoder_ && last_audio_decoder_->channels > 1) {
+    if (absl::EqualsIgnoreCase(format->name, "cn")) {
+      if (last_decoder_ && last_decoder_->second.num_channels > 1) {
         // This is a CNG and the audio codec is not mono, so skip pushing in
         // packets into NetEq.
         return 0;
       }
     } else {
-      last_audio_decoder_ = ci;
-      last_audio_format_ = neteq_->GetDecoderFormat(ci->pltype);
-      RTC_DCHECK(last_audio_format_);
-      last_packet_sample_rate_hz_ = ci->plfreq;
+      RTC_DCHECK(format);
+      last_decoder_ = std::make_pair(payload_type, *format);
     }
   }  // |crit_sect_| is released.
 
-  if (neteq_->InsertPacket(rtp_header.header, incoming_payload,
-                           receive_timestamp) < 0) {
+  uint32_t receive_timestamp = NowInTimestamp(format->clockrate_hz);
+  if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_timestamp) <
+      0) {
     RTC_LOG(LERROR) << "AcmReceiver::InsertPacket "
-                    << static_cast<int>(header->payloadType)
+                    << static_cast<int>(rtp_header.payloadType)
                     << " Failed to insert packet";
     return -1;
   }
@@ -186,85 +194,6 @@
   neteq_->SetCodecs(codecs);
 }
 
-int32_t AcmReceiver::AddCodec(int acm_codec_id,
-                              uint8_t payload_type,
-                              size_t channels,
-                              int /*sample_rate_hz*/,
-                              AudioDecoder* audio_decoder,
-                              const std::string& name) {
-  // TODO(kwiberg): This function has been ignoring the |sample_rate_hz|
-  // argument for a long time. Arguably, it should simply be removed.
-
-  const auto neteq_decoder = [acm_codec_id, channels]() -> NetEqDecoder {
-    if (acm_codec_id == -1)
-      return NetEqDecoder::kDecoderArbitrary;  // External decoder.
-    const absl::optional<RentACodec::CodecId> cid =
-        RentACodec::CodecIdFromIndex(acm_codec_id);
-    RTC_DCHECK(cid) << "Invalid codec index: " << acm_codec_id;
-    const absl::optional<NetEqDecoder> ned =
-        RentACodec::NetEqDecoderFromCodecId(*cid, channels);
-    RTC_DCHECK(ned) << "Invalid codec ID: " << static_cast<int>(*cid);
-    return *ned;
-  }();
-  const absl::optional<SdpAudioFormat> new_format =
-      NetEqDecoderToSdpAudioFormat(neteq_decoder);
-
-  rtc::CritScope lock(&crit_sect_);
-
-  const auto old_format = neteq_->GetDecoderFormat(payload_type);
-  if (old_format && new_format && *old_format == *new_format) {
-    // Re-registering the same codec. Do nothing and return.
-    return 0;
-  }
-
-  if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) {
-    RTC_LOG(LERROR) << "Cannot remove payload "
-                    << static_cast<int>(payload_type);
-    return -1;
-  }
-
-  int ret_val;
-  if (!audio_decoder) {
-    ret_val = neteq_->RegisterPayloadType(neteq_decoder, name, payload_type);
-  } else {
-    ret_val = neteq_->RegisterExternalDecoder(audio_decoder, neteq_decoder,
-                                              name, payload_type);
-  }
-  if (ret_val != NetEq::kOK) {
-    RTC_LOG(LERROR) << "AcmReceiver::AddCodec " << acm_codec_id
-                    << static_cast<int>(payload_type)
-                    << " channels: " << channels;
-    return -1;
-  }
-  return 0;
-}
-
-bool AcmReceiver::AddCodec(int rtp_payload_type,
-                           const SdpAudioFormat& audio_format) {
-  const auto old_format = neteq_->GetDecoderFormat(rtp_payload_type);
-  if (old_format && *old_format == audio_format) {
-    // Re-registering the same codec. Do nothing and return.
-    return true;
-  }
-
-  if (neteq_->RemovePayloadType(rtp_payload_type) != NetEq::kOK) {
-    RTC_LOG(LERROR)
-        << "AcmReceiver::AddCodec: Could not remove existing decoder"
-           " for payload type "
-        << rtp_payload_type;
-    return false;
-  }
-
-  const bool success =
-      neteq_->RegisterPayloadType(rtp_payload_type, audio_format);
-  if (!success) {
-    RTC_LOG(LERROR) << "AcmReceiver::AddCodec failed for payload type "
-                    << rtp_payload_type << ", decoder format "
-                    << rtc::ToString(audio_format);
-  }
-  return success;
-}
-
 void AcmReceiver::FlushBuffers() {
   neteq_->FlushBuffers();
 }
@@ -272,24 +201,7 @@
 void AcmReceiver::RemoveAllCodecs() {
   rtc::CritScope lock(&crit_sect_);
   neteq_->RemoveAllPayloadTypes();
-  last_audio_decoder_ = absl::nullopt;
-  last_audio_format_ = absl::nullopt;
-  last_packet_sample_rate_hz_ = absl::nullopt;
-}
-
-int AcmReceiver::RemoveCodec(uint8_t payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) {
-    RTC_LOG(LERROR) << "AcmReceiver::RemoveCodec "
-                    << static_cast<int>(payload_type);
-    return -1;
-  }
-  if (last_audio_decoder_ && payload_type == last_audio_decoder_->pltype) {
-    last_audio_decoder_ = absl::nullopt;
-    last_audio_format_ = absl::nullopt;
-    last_packet_sample_rate_hz_ = absl::nullopt;
-  }
-  return 0;
+  last_decoder_ = absl::nullopt;
 }
 
 absl::optional<uint32_t> AcmReceiver::GetPlayoutTimestamp() {
@@ -304,18 +216,14 @@
   return neteq_->TargetDelayMs();
 }
 
-int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
+absl::optional<std::pair<int, SdpAudioFormat>>
+    AcmReceiver::LastDecoder() const {
   rtc::CritScope lock(&crit_sect_);
-  if (!last_audio_decoder_) {
-    return -1;
+  if (!last_decoder_) {
+    return absl::nullopt;
   }
-  *codec = *last_audio_decoder_;
-  return 0;
-}
-
-absl::optional<SdpAudioFormat> AcmReceiver::LastAudioFormat() const {
-  rtc::CritScope lock(&crit_sect_);
-  return last_audio_format_;
+  RTC_DCHECK_NE(-1, last_decoder_->first);  // Payload type should be valid.
+  return last_decoder_;
 }
 
 void AcmReceiver::GetNetworkStatistics(NetworkStatistics* acm_stat) {
@@ -345,8 +253,12 @@
   acm_stat->concealedSamples = neteq_lifetime_stat.concealed_samples;
   acm_stat->concealmentEvents = neteq_lifetime_stat.concealment_events;
   acm_stat->jitterBufferDelayMs = neteq_lifetime_stat.jitter_buffer_delay_ms;
+  acm_stat->jitterBufferEmittedCount =
+      neteq_lifetime_stat.jitter_buffer_emitted_count;
   acm_stat->delayedPacketOutageSamples =
       neteq_lifetime_stat.delayed_packet_outage_samples;
+  acm_stat->relativePacketArrivalDelayMs =
+      neteq_lifetime_stat.relative_packet_arrival_delay_ms;
 
   NetEqOperationsAndState neteq_operations_and_state =
       neteq_->GetOperationsAndState();
@@ -354,26 +266,6 @@
       neteq_operations_and_state.packet_buffer_flushes;
 }
 
-int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
-                                      CodecInst* codec) const {
-  rtc::CritScope lock(&crit_sect_);
-  const absl::optional<CodecInst> ci = neteq_->GetDecoder(payload_type);
-  if (ci) {
-    *codec = *ci;
-    return 0;
-  } else {
-    RTC_LOG(LERROR) << "AcmReceiver::DecoderByPayloadType "
-                    << static_cast<int>(payload_type);
-    return -1;
-  }
-}
-
-absl::optional<SdpAudioFormat> AcmReceiver::DecoderByPayloadType(
-    int payload_type) const {
-  rtc::CritScope lock(&crit_sect_);
-  return neteq_->GetDecoderFormat(payload_type);
-}
-
 int AcmReceiver::EnableNack(size_t max_nack_list_size) {
   neteq_->EnableNack(max_nack_list_size);
   return 0;
@@ -393,19 +285,6 @@
   // TODO(turajs): Should NetEq Buffer be flushed?
 }
 
-const absl::optional<CodecInst> AcmReceiver::RtpHeaderToDecoder(
-    const RTPHeader& rtp_header,
-    uint8_t first_payload_byte) const {
-  const absl::optional<CodecInst> ci =
-      neteq_->GetDecoder(rtp_header.payloadType);
-  if (ci && absl::EqualsIgnoreCase(ci->plname, "red")) {
-    // This is a RED packet. Get the payload of the audio codec.
-    return neteq_->GetDecoder(first_payload_byte & 0x7f);
-  } else {
-    return ci;
-  }
-}
-
 uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const {
   // Down-cast the time to (32-6)-bit since we only care about
   // the least significant bits. (32-6) bits cover 2^(32-6) = 67108864 ms.
diff --git a/modules/audio_coding/acm2/acm_receiver.h b/modules/audio_coding/acm2/acm_receiver.h
index 8e7d839..1f449a3 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -15,6 +15,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
@@ -24,16 +25,14 @@
 #include "modules/audio_coding/acm2/acm_resampler.h"
 #include "modules/audio_coding/acm2/call_statistics.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
 
 class Clock;
-struct CodecInst;
 class NetEq;
 struct RTPHeader;
-struct WebRtcRTPHeader;
 
 namespace acm2 {
 
@@ -58,7 +57,7 @@
   // Return value             : 0 if OK.
   //                           <0 if NetEq returned an error.
   //
-  int InsertPacket(const WebRtcRTPHeader& rtp_header,
+  int InsertPacket(const RTPHeader& rtp_header,
                    rtc::ArrayView<const uint8_t> incoming_payload);
 
   //
@@ -85,43 +84,6 @@
   void SetCodecs(const std::map<int, SdpAudioFormat>& codecs);
 
   //
-  // Adds a new codec to the NetEq codec database.
-  //
-  // Input:
-  //   - acm_codec_id        : ACM codec ID; -1 means external decoder.
-  //   - payload_type        : payload type.
-  //   - sample_rate_hz      : sample rate.
-  //   - audio_decoder       : pointer to a decoder object. If it's null, then
-  //                           NetEq will internally create a decoder object
-  //                           based on the value of |acm_codec_id| (which
-  //                           mustn't be -1). Otherwise, NetEq will use the
-  //                           given decoder for the given payload type. NetEq
-  //                           won't take ownership of the decoder; it's up to
-  //                           the caller to delete it when it's no longer
-  //                           needed.
-  //
-  //                           Providing an existing decoder object here is
-  //                           necessary for external decoders, but may also be
-  //                           used for built-in decoders if NetEq doesn't have
-  //                           all the info it needs to construct them properly
-  //                           (e.g. iSAC, where the decoder needs to be paired
-  //                           with an encoder).
-  //
-  // Return value             : 0 if OK.
-  //                           <0 if NetEq returned an error.
-  //
-  int AddCodec(int acm_codec_id,
-               uint8_t payload_type,
-               size_t channels,
-               int sample_rate_hz,
-               AudioDecoder* audio_decoder,
-               const std::string& name);
-
-  // Adds a new decoder to the NetEq codec database. Returns true iff
-  // successful.
-  bool AddCodec(int rtp_payload_type, const SdpAudioFormat& audio_format);
-
-  //
   // Sets a minimum delay for packet buffer. The given delay is maintained,
   // unless channel condition dictates a higher delay.
   //
@@ -145,6 +107,16 @@
   //
   int SetMaximumDelay(int delay_ms);
 
+  // Sets a base minimum delay in milliseconds for the packet buffer.
+  // Base minimum delay sets lower bound minimum delay value which
+  // is set via SetMinimumDelay.
+  //
+  // Returns true if value was successfully set, false overwise.
+  bool SetBaseMinimumDelayMs(int delay_ms);
+
+  // Returns current value of base minimum delay in milliseconds.
+  int GetBaseMinimumDelayMs() const;
+
   //
   // Resets the initial delay to zero.
   //
@@ -173,17 +145,6 @@
   void FlushBuffers();
 
   //
-  // Removes a payload-type from the NetEq codec database.
-  //
-  // Input:
-  //   - payload_type         : the payload-type to be removed.
-  //
-  // Return value             : 0 if OK.
-  //                           -1 if an error occurred.
-  //
-  int RemoveCodec(uint8_t payload_type);
-
-  //
   // Remove all registered codecs.
   //
   void RemoveAllCodecs();
@@ -204,30 +165,10 @@
   int TargetDelayMs() const;
 
   //
-  // Get the audio codec associated with the last non-CNG/non-DTMF received
-  // payload. If no non-CNG/non-DTMF packet is received -1 is returned,
-  // otherwise return 0.
+  // Get payload type and format of the last non-CNG/non-DTMF received payload.
+  // If no non-CNG/non-DTMF packet is received absl::nullopt is returned.
   //
-  int LastAudioCodec(CodecInst* codec) const;
-
-  absl::optional<SdpAudioFormat> LastAudioFormat() const;
-
-  //
-  // Get a decoder given its registered payload-type.
-  //
-  // Input:
-  //    -payload_type         : the payload-type of the codec to be retrieved.
-  //
-  // Output:
-  //    -codec                : codec associated with the given payload-type.
-  //
-  // Return value             : 0 if succeeded.
-  //                           -1 if failed, e.g. given payload-type is not
-  //                              registered.
-  //
-  int DecoderByPayloadType(uint8_t payload_type,
-                           CodecInst* codec) const;
-  absl::optional<SdpAudioFormat> DecoderByPayloadType(int payload_type) const;
+  absl::optional<std::pair<int, SdpAudioFormat>> LastDecoder() const;
 
   //
   // Enable NACK and set the maximum size of the NACK list. If NACK is already
@@ -260,32 +201,17 @@
   void GetDecodingCallStatistics(AudioDecodingCallStats* stats) const;
 
  private:
-  struct Decoder {
-    int acm_codec_id;
-    uint8_t payload_type;
-    // This field is meaningful for codecs where both mono and
-    // stereo versions are registered under the same ID.
-    size_t channels;
-    int sample_rate_hz;
-  };
-
-  const absl::optional<CodecInst> RtpHeaderToDecoder(
-      const RTPHeader& rtp_header,
-      uint8_t first_payload_byte) const
-      RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_sect_);
-
   uint32_t NowInTimestamp(int decoder_sampling_rate) const;
 
   rtc::CriticalSection crit_sect_;
-  absl::optional<CodecInst> last_audio_decoder_ RTC_GUARDED_BY(crit_sect_);
-  absl::optional<SdpAudioFormat> last_audio_format_ RTC_GUARDED_BY(crit_sect_);
+  absl::optional<std::pair<int, SdpAudioFormat>> last_decoder_
+      RTC_GUARDED_BY(crit_sect_);
   ACMResampler resampler_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<int16_t[]> last_audio_buffer_ RTC_GUARDED_BY(crit_sect_);
   CallStatistics call_stats_ RTC_GUARDED_BY(crit_sect_);
   const std::unique_ptr<NetEq> neteq_;  // NetEq is thread-safe; no lock needed.
-  const Clock* const clock_;
+  Clock* const clock_;
   bool resampled_last_output_frame_ RTC_GUARDED_BY(crit_sect_);
-  absl::optional<int> last_packet_sample_rate_hz_ RTC_GUARDED_BY(crit_sect_);
 };
 
 }  // namespace acm2
diff --git a/modules/audio_coding/acm2/acm_receiver_unittest.cc b/modules/audio_coding/acm2/acm_receiver_unittest.cc
index 46384fe..e5a7684 100644
--- a/modules/audio_coding/acm2/acm_receiver_unittest.cc
+++ b/modules/audio_coding/acm2/acm_receiver_unittest.cc
@@ -15,7 +15,6 @@
 
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
@@ -24,7 +23,7 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "system_wrappers/include/clock.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -51,13 +50,12 @@
     acm_->InitializeReceiver();
     acm_->RegisterTransportCallback(this);
 
-    rtp_header_.header.sequenceNumber = 0;
-    rtp_header_.header.timestamp = 0;
-    rtp_header_.header.markerBit = false;
-    rtp_header_.header.ssrc = 0x12345678;  // Arbitrary.
-    rtp_header_.header.numCSRCs = 0;
-    rtp_header_.header.payloadType = 0;
-    rtp_header_.frameType = kAudioFrameSpeech;
+    rtp_header_.sequenceNumber = 0;
+    rtp_header_.timestamp = 0;
+    rtp_header_.markerBit = false;
+    rtp_header_.ssrc = 0x12345678;  // Arbitrary.
+    rtp_header_.numCSRCs = 0;
+    rtp_header_.payloadType = 0;
   }
 
   void TearDown() override {}
@@ -105,14 +103,6 @@
     return num_10ms_frames;
   }
 
-  template <size_t N>
-  void AddSetOfCodecs(rtc::ArrayView<SdpAudioFormat> formats) {
-    static int payload_type = 0;
-    for (const auto& format : formats) {
-      EXPECT_TRUE(receiver_->AddCodec(payload_type++, format));
-    }
-  }
-
   int SendData(FrameType frame_type,
                uint8_t payload_type,
                uint32_t timestamp,
@@ -122,9 +112,8 @@
     if (frame_type == kEmptyFrame)
       return 0;
 
-    rtp_header_.header.payloadType = payload_type;
-    rtp_header_.frameType = frame_type;
-    rtp_header_.header.timestamp = timestamp;
+    rtp_header_.payloadType = payload_type;
+    rtp_header_.timestamp = timestamp;
 
     int ret_val = receiver_->InsertPacket(
         rtp_header_,
@@ -133,7 +122,7 @@
       assert(false);
       return -1;
     }
-    rtp_header_.header.sequenceNumber++;
+    rtp_header_.sequenceNumber++;
     packet_sent_ = true;
     last_frame_type_ = frame_type;
     return 0;
@@ -146,7 +135,7 @@
   AudioCodingModule::Config config_;
   std::unique_ptr<AcmReceiver> receiver_;
   std::unique_ptr<AudioCodingModule> acm_;
-  WebRtcRTPHeader rtp_header_;
+  RTPHeader rtp_header_;
   uint32_t timestamp_;
   bool packet_sent_;  // Set when SendData is called reset when inserting audio.
   uint32_t last_packet_send_timestamp_;
@@ -154,111 +143,26 @@
 };
 
 #if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecGetCodec DISABLED_AddCodecGetCodec
-#else
-#define MAYBE_AddCodecGetCodec AddCodecGetCodec
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecGetCodec) {
-  const std::vector<AudioCodecSpec> codecs =
-      decoder_factory_->GetSupportedDecoders();
-
-  // Add codec.
-  for (size_t n = 0; n < codecs.size(); ++n) {
-    if (n & 0x1) {  // Just add codecs with odd index.
-      const int payload_type = rtc::checked_cast<int>(n);
-      EXPECT_TRUE(receiver_->AddCodec(payload_type, codecs[n].format));
-    }
-  }
-  // Get codec and compare.
-  for (size_t n = 0; n < codecs.size(); ++n) {
-    const int payload_type = rtc::checked_cast<int>(n);
-    if (n & 0x1) {
-      // Codecs with odd index should match the reference.
-      EXPECT_EQ(absl::make_optional(codecs[n].format),
-                receiver_->DecoderByPayloadType(payload_type));
-    } else {
-      // Codecs with even index are not registered.
-      EXPECT_EQ(absl::nullopt, receiver_->DecoderByPayloadType(payload_type));
-    }
-  }
-}
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecChangePayloadType DISABLED_AddCodecChangePayloadType
-#else
-#define MAYBE_AddCodecChangePayloadType AddCodecChangePayloadType
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecChangePayloadType) {
-  const SdpAudioFormat format("giraffe", 8000, 1);
-
-  // Register the same codec with different payloads.
-  EXPECT_EQ(true, receiver_->AddCodec(17, format));
-  EXPECT_EQ(true, receiver_->AddCodec(18, format));
-
-  // Both payload types should exist.
-  EXPECT_EQ(absl::make_optional(format), receiver_->DecoderByPayloadType(17));
-  EXPECT_EQ(absl::make_optional(format), receiver_->DecoderByPayloadType(18));
-}
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecChangeCodecId DISABLED_AddCodecChangeCodecId
-#else
-#define MAYBE_AddCodecChangeCodecId AddCodecChangeCodecId
-#endif
-TEST_F(AcmReceiverTestOldApi, AddCodecChangeCodecId) {
-  const SdpAudioFormat format1("giraffe", 8000, 1);
-  const SdpAudioFormat format2("gnu", 16000, 1);
-
-  // Register the same payload type with different codec ID.
-  EXPECT_EQ(true, receiver_->AddCodec(17, format1));
-  EXPECT_EQ(true, receiver_->AddCodec(17, format2));
-
-  // Make sure that the last codec is used.
-  EXPECT_EQ(absl::make_optional(format2), receiver_->DecoderByPayloadType(17));
-}
-
-#if defined(WEBRTC_ANDROID)
-#define MAYBE_AddCodecRemoveCodec DISABLED_AddCodecRemoveCodec
-#else
-#define MAYBE_AddCodecRemoveCodec AddCodecRemoveCodec
-#endif
-TEST_F(AcmReceiverTestOldApi, MAYBE_AddCodecRemoveCodec) {
-  EXPECT_EQ(true, receiver_->AddCodec(17, SdpAudioFormat("giraffe", 8000, 1)));
-
-  // Remove non-existing codec should not fail. ACM1 legacy.
-  EXPECT_EQ(0, receiver_->RemoveCodec(18));
-
-  // Remove an existing codec.
-  EXPECT_EQ(0, receiver_->RemoveCodec(17));
-
-  // Ask for the removed codec, must fail.
-  EXPECT_EQ(absl::nullopt, receiver_->DecoderByPayloadType(17));
-}
-
-#if defined(WEBRTC_ANDROID)
 #define MAYBE_SampleRate DISABLED_SampleRate
 #else
 #define MAYBE_SampleRate SampleRate
 #endif
 TEST_F(AcmReceiverTestOldApi, MAYBE_SampleRate) {
-  const std::vector<SdpAudioFormat> codecs = {{"ISAC", 16000, 1},
-                                              {"ISAC", 32000, 1}};
-  for (size_t i = 0; i < codecs.size(); ++i) {
-    const int payload_type = rtc::checked_cast<int>(i);
-    EXPECT_EQ(true, receiver_->AddCodec(payload_type, codecs[i]));
-  }
+  const std::map<int, SdpAudioFormat> codecs = {{0, {"ISAC", 16000, 1}},
+                                                {1, {"ISAC", 32000, 1}}};
+  receiver_->SetCodecs(codecs);
 
   constexpr int kOutSampleRateHz = 8000;  // Different than codec sample rate.
   for (size_t i = 0; i < codecs.size(); ++i) {
     const int payload_type = rtc::checked_cast<int>(i);
     const int num_10ms_frames =
-        InsertOnePacketOfSilence(SetEncoder(payload_type, codecs[i]));
+        InsertOnePacketOfSilence(SetEncoder(payload_type, codecs.at(i)));
     for (int k = 0; k < num_10ms_frames; ++k) {
       AudioFrame frame;
       bool muted;
       EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame, &muted));
     }
-    EXPECT_EQ(encoder_factory_->QueryAudioEncoder(codecs[i])->sample_rate_hz,
+    EXPECT_EQ(encoder_factory_->QueryAudioEncoder(codecs.at(i))->sample_rate_hz,
               receiver_->last_output_sample_rate_hz());
   }
 }
@@ -278,7 +182,7 @@
     EXPECT_TRUE(config_.neteq_config.for_test_no_time_stretching);
 
     constexpr int payload_type = 17;
-    EXPECT_TRUE(receiver_->AddCodec(payload_type, codec));
+    receiver_->SetCodecs({{payload_type, codec}});
 
     const AudioCodecInfo info = SetEncoder(payload_type, codec);
     const int output_sample_rate_hz = info.sample_rate_hz;
@@ -356,7 +260,7 @@
   constexpr int payload_type = 34;
   const SdpAudioFormat codec = {"L16", 16000, 1};
   const AudioCodecInfo info = SetEncoder(payload_type, codec);
-  EXPECT_TRUE(receiver_->AddCodec(payload_type, codec));
+  receiver_->SetCodecs({{payload_type, codec}});
   constexpr int kNumPackets = 5;
   AudioFrame frame;
   for (int n = 0; n < kNumPackets; ++n) {
@@ -387,7 +291,7 @@
   const SdpAudioFormat codec = {"L16", 16000, 1};
   const AudioCodecInfo info = SetEncoder(payload_type, codec);
   encoder_factory_->QueryAudioEncoder(codec).value();
-  EXPECT_TRUE(receiver_->AddCodec(payload_type, codec));
+  receiver_->SetCodecs({{payload_type, codec}});
   const int kNumPackets = 5;
   AudioFrame frame;
   for (int n = 0; n < kNumPackets; ++n) {
@@ -407,43 +311,43 @@
 #endif
 #if defined(WEBRTC_CODEC_ISAC)
 TEST_F(AcmReceiverTestOldApi, MAYBE_LastAudioCodec) {
-  const std::vector<SdpAudioFormat> codecs = {{"ISAC", 16000, 1},
-                                              {"PCMA", 8000, 1},
-                                              {"ISAC", 32000, 1},
-                                              {"L16", 32000, 1}};
-  for (size_t i = 0; i < codecs.size(); ++i) {
-    const int payload_type = rtc::checked_cast<int>(i);
-    EXPECT_TRUE(receiver_->AddCodec(payload_type, codecs[i]));
-  }
-
-  const std::map<int, int> cng_payload_types = {
-      {8000, 100}, {16000, 101}, {32000, 102}};
-  for (const auto& x : cng_payload_types) {
-    const int sample_rate_hz = x.first;
-    const int payload_type = x.second;
-    EXPECT_TRUE(receiver_->AddCodec(payload_type, {"CN", sample_rate_hz, 1}));
+  const std::map<int, SdpAudioFormat> codecs = {{0, {"ISAC", 16000, 1}},
+                                                {1, {"PCMA", 8000, 1}},
+                                                {2, {"ISAC", 32000, 1}},
+                                                {3, {"L16", 32000, 1}}};
+  const std::map<int, int> cng_payload_types = {{8000, 100},
+                                                {16000, 101},
+                                                {32000, 102}};
+  {
+    std::map<int, SdpAudioFormat> receive_codecs = codecs;
+    for (const auto& cng_type : cng_payload_types) {
+      receive_codecs.emplace(
+          std::make_pair(cng_type.second, SdpAudioFormat("CN", cng_type.first, 1)));
+    }
+    receiver_->SetCodecs(receive_codecs);
   }
 
   // No audio payload is received.
-  EXPECT_EQ(absl::nullopt, receiver_->LastAudioFormat());
+  EXPECT_EQ(absl::nullopt, receiver_->LastDecoder());
 
   // Start with sending DTX.
   packet_sent_ = false;
   InsertOnePacketOfSilence(
-      SetEncoder(0, codecs[0], cng_payload_types));  // Enough to test
+      SetEncoder(0, codecs.at(0), cng_payload_types));  // Enough to test
                                                      // with one codec.
   ASSERT_TRUE(packet_sent_);
   EXPECT_EQ(kAudioFrameCN, last_frame_type_);
 
   // Has received, only, DTX. Last Audio codec is undefined.
-  EXPECT_EQ(absl::nullopt, receiver_->LastAudioFormat());
-  EXPECT_FALSE(receiver_->last_packet_sample_rate_hz());
+  EXPECT_EQ(absl::nullopt, receiver_->LastDecoder());
+  EXPECT_EQ(absl::nullopt, receiver_->last_packet_sample_rate_hz());
 
   for (size_t i = 0; i < codecs.size(); ++i) {
     // Set DTX off to send audio payload.
     packet_sent_ = false;
     const int payload_type = rtc::checked_cast<int>(i);
-    const AudioCodecInfo info_without_cng = SetEncoder(payload_type, codecs[i]);
+    const AudioCodecInfo info_without_cng =
+        SetEncoder(payload_type, codecs.at(i));
     InsertOnePacketOfSilence(info_without_cng);
 
     // Sanity check if Actually an audio payload received, and it should be
@@ -456,7 +360,7 @@
     // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
     // the expected codec. Encode repeatedly until a DTX is sent.
     const AudioCodecInfo info_with_cng =
-        SetEncoder(payload_type, codecs[i], cng_payload_types);
+        SetEncoder(payload_type, codecs.at(i), cng_payload_types);
     while (last_frame_type_ != kAudioFrameCN) {
       packet_sent_ = false;
       InsertOnePacketOfSilence(info_with_cng);
@@ -464,7 +368,7 @@
     }
     EXPECT_EQ(info_with_cng.sample_rate_hz,
               receiver_->last_packet_sample_rate_hz());
-    EXPECT_EQ(codecs[i], receiver_->LastAudioFormat());
+    EXPECT_EQ(codecs.at(i), receiver_->LastDecoder()->second);
   }
 }
 #endif
diff --git a/modules/audio_coding/acm2/acm_send_test.cc b/modules/audio_coding/acm2/acm_send_test.cc
index c5e010c..b6110b6 100644
--- a/modules/audio_coding/acm2/acm_send_test.cc
+++ b/modules/audio_coding/acm2/acm_send_test.cc
@@ -14,15 +14,15 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "absl/strings/match.h"
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
-#include "modules/audio_coding/codecs/audio_format_conversion.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -59,23 +59,28 @@
 AcmSendTestOldApi::~AcmSendTestOldApi() = default;
 
 bool AcmSendTestOldApi::RegisterCodec(const char* payload_name,
-                                      int sampling_freq_hz,
-                                      int channels,
+                                      int clockrate_hz,
+                                      int num_channels,
                                       int payload_type,
                                       int frame_size_samples) {
-  CodecInst codec;
-  RTC_CHECK_EQ(0, AudioCodingModule::Codec(payload_name, &codec,
-                                           sampling_freq_hz, channels));
-  codec.pltype = payload_type;
-  codec.pacsize = frame_size_samples;
-  auto factory = CreateBuiltinAudioEncoderFactory();
-  SdpAudioFormat format = CodecInstToSdp(codec);
+  SdpAudioFormat format(payload_name, clockrate_hz, num_channels);
+  if (absl::EqualsIgnoreCase(payload_name, "g722")) {
+    RTC_CHECK_EQ(16000, clockrate_hz);
+    format.clockrate_hz = 8000;
+  } else if (absl::EqualsIgnoreCase(payload_name, "opus")) {
+    RTC_CHECK(num_channels == 1 || num_channels == 2);
+    if (num_channels == 2) {
+      format.parameters["stereo"] = "1";
+    }
+    format.num_channels = 2;
+  }
   format.parameters["ptime"] = rtc::ToString(rtc::CheckedDivExact(
-      frame_size_samples, rtc::CheckedDivExact(sampling_freq_hz, 1000)));
+      frame_size_samples, rtc::CheckedDivExact(clockrate_hz, 1000)));
+  auto factory = CreateBuiltinAudioEncoderFactory();
   acm_->SetEncoder(
       factory->MakeAudioEncoder(payload_type, format, absl::nullopt));
   codec_registered_ = true;
-  input_frame_.num_channels_ = channels;
+  input_frame_.num_channels_ = num_channels;
   assert(input_block_size_samples_ * input_frame_.num_channels_ <=
          AudioFrame::kMaxDataSizeSamples);
   return codec_registered_;
@@ -101,13 +106,9 @@
   // Insert audio and process until one packet is produced.
   while (clock_.TimeInMilliseconds() < test_duration_ms_) {
     clock_.AdvanceTimeMilliseconds(kBlockSizeMs);
-    RTC_CHECK(audio_source_->Read(input_block_size_samples_,
-                                  input_frame_.mutable_data()));
-    if (input_frame_.num_channels_ > 1) {
-      InputAudioFile::DuplicateInterleaved(
-          input_frame_.data(), input_block_size_samples_,
-          input_frame_.num_channels_, input_frame_.mutable_data());
-    }
+    RTC_CHECK(audio_source_->Read(
+        input_block_size_samples_ * input_frame_.num_channels_,
+        input_frame_.mutable_data()));
     data_to_send_ = false;
     RTC_CHECK_GE(acm_->Add10MsData(input_frame_), 0);
     input_frame_.timestamp_ += static_cast<uint32_t>(input_block_size_samples_);
diff --git a/modules/audio_coding/acm2/acm_send_test.h b/modules/audio_coding/acm2/acm_send_test.h
index 3479de0..24d230b 100644
--- a/modules/audio_coding/acm2/acm_send_test.h
+++ b/modules/audio_coding/acm2/acm_send_test.h
@@ -17,7 +17,7 @@
 #include "api/audio/audio_frame.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/packet_source.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "system_wrappers/include/clock.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/acm2/audio_coding_module.cc b/modules/audio_coding/acm2/audio_coding_module.cc
index c0aab3a..1547b37 100644
--- a/modules/audio_coding/acm2/audio_coding_module.cc
+++ b/modules/audio_coding/acm2/audio_coding_module.cc
@@ -18,12 +18,11 @@
 #include "api/array_view.h"
 #include "modules/audio_coding/acm2/acm_receiver.h"
 #include "modules/audio_coding/acm2/acm_resampler.h"
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "modules/include/module_common_types.h"
 #include "modules/include/module_common_types_public.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/thread_annotations.h"
@@ -45,9 +44,6 @@
   void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
                          modifier) override;
 
-  // Get current send codec.
-  absl::optional<CodecInst> SendCodec() const override;
-
   // Sets the bitrate to the specified value in bits/sec. In case the codec does
   // not support the requested value it will choose an appropriate value
   // instead.
@@ -90,24 +86,13 @@
 
   void SetReceiveCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
 
-  bool RegisterReceiveCodec(int rtp_payload_type,
-                            const SdpAudioFormat& audio_format) override;
-
-  int RegisterExternalReceiveCodec(int rtp_payload_type,
-                                   AudioDecoder* external_decoder,
-                                   int sample_rate_hz,
-                                   int num_channels,
-                                   const std::string& name) override;
-
   // Get current received codec.
-  int ReceiveCodec(CodecInst* current_codec) const override;
-
-  absl::optional<SdpAudioFormat> ReceiveFormat() const override;
+  absl::optional<std::pair<int, SdpAudioFormat>> ReceiveCodec() const override;
 
   // Incoming packet from network parsed and ready for decode.
   int IncomingPacket(const uint8_t* incoming_payload,
                      const size_t payload_length,
-                     const WebRtcRTPHeader& rtp_info) override;
+                     const RTPHeader& rtp_info) override;
 
   // Minimum playout delay.
   int SetMinimumPlayoutDelay(int time_ms) override;
@@ -115,6 +100,10 @@
   // Maximum playout delay.
   int SetMaximumPlayoutDelay(int time_ms) override;
 
+  bool SetBaseMinimumPlayoutDelayMs(int delay_ms) override;
+
+  int GetBaseMinimumPlayoutDelayMs() const override;
+
   absl::optional<uint32_t> PlayoutTimestamp() override;
 
   int FilteredCurrentDelayMs() const override;
@@ -141,8 +130,6 @@
 
   int DisableOpusDtx() override;
 
-  int UnregisterReceiveCodec(uint8_t payload_type) override;
-
   int EnableNack(size_t max_nack_list_size) override;
 
   void DisableNack() override;
@@ -317,42 +304,6 @@
   }
 }
 
-// Wraps a raw AudioEncoder pointer. The idea is that you can put one of these
-// in a unique_ptr, to protect the contained raw pointer from being deleted
-// when the unique_ptr expires. (This is of course a bad idea in general, but
-// backwards compatibility.)
-class RawAudioEncoderWrapper final : public AudioEncoder {
- public:
-  RawAudioEncoderWrapper(AudioEncoder* enc) : enc_(enc) {}
-  int SampleRateHz() const override { return enc_->SampleRateHz(); }
-  size_t NumChannels() const override { return enc_->NumChannels(); }
-  int RtpTimestampRateHz() const override { return enc_->RtpTimestampRateHz(); }
-  size_t Num10MsFramesInNextPacket() const override {
-    return enc_->Num10MsFramesInNextPacket();
-  }
-  size_t Max10MsFramesInAPacket() const override {
-    return enc_->Max10MsFramesInAPacket();
-  }
-  int GetTargetBitrate() const override { return enc_->GetTargetBitrate(); }
-  EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
-                         rtc::ArrayView<const int16_t> audio,
-                         rtc::Buffer* encoded) override {
-    return enc_->Encode(rtp_timestamp, audio, encoded);
-  }
-  void Reset() override { return enc_->Reset(); }
-  bool SetFec(bool enable) override { return enc_->SetFec(enable); }
-  bool SetDtx(bool enable) override { return enc_->SetDtx(enable); }
-  bool SetApplication(Application application) override {
-    return enc_->SetApplication(application);
-  }
-  void SetMaxPlaybackRate(int frequency_hz) override {
-    return enc_->SetMaxPlaybackRate(frequency_hz);
-  }
-
- private:
-  AudioEncoder* enc_;
-};
-
 void AudioCodingModuleImpl::ChangeLogger::MaybeLog(int value) {
   if (value != last_value_ || first_time_) {
     first_time_ = false;
@@ -480,26 +431,6 @@
   modifier(&encoder_stack_);
 }
 
-// Get current send codec.
-absl::optional<CodecInst> AudioCodingModuleImpl::SendCodec() const {
-  rtc::CritScope lock(&acm_crit_sect_);
-  if (encoder_stack_) {
-    CodecInst ci;
-    ci.channels = encoder_stack_->NumChannels();
-    ci.plfreq = encoder_stack_->SampleRateHz();
-    ci.pacsize = rtc::CheckedDivExact(
-        static_cast<int>(encoder_stack_->Max10MsFramesInAPacket() * ci.plfreq),
-        100);
-    ci.pltype = -1;  // Not valid.
-    ci.rate = -1;    // Not valid.
-    static const char kName[] = "external";
-    memcpy(ci.plname, kName, sizeof(kName));
-    return ci;
-  } else {
-    return absl::nullopt;
-  }
-}
-
 void AudioCodingModuleImpl::SetBitRate(int bitrate_bps) {
   rtc::CritScope lock(&acm_crit_sect_);
   if (encoder_stack_) {
@@ -546,7 +477,9 @@
     return -1;
   }
 
-  if (audio_frame.num_channels_ != 1 && audio_frame.num_channels_ != 2) {
+  if (audio_frame.num_channels_ != 1 && audio_frame.num_channels_ != 2 &&
+      audio_frame.num_channels_ != 4 && audio_frame.num_channels_ != 6 &&
+      audio_frame.num_channels_ != 8) {
     RTC_LOG(LS_ERROR) << "Cannot Add 10 ms audio, invalid number of channels.";
     return -1;
   }
@@ -721,9 +654,6 @@
   // start-up.
   if (receiver_initialized_)
     receiver_.RemoveAllCodecs();
-  receiver_.ResetInitialDelay();
-  receiver_.SetMinimumDelay(0);
-  receiver_.SetMaximumDelay(0);
   receiver_.FlushBuffers();
 
   receiver_initialized_ = true;
@@ -748,60 +678,16 @@
   receiver_.SetCodecs(codecs);
 }
 
-bool AudioCodingModuleImpl::RegisterReceiveCodec(
-    int rtp_payload_type,
-    const SdpAudioFormat& audio_format) {
+absl::optional<std::pair<int, SdpAudioFormat>>
+    AudioCodingModuleImpl::ReceiveCodec() const {
   rtc::CritScope lock(&acm_crit_sect_);
-  RTC_DCHECK(receiver_initialized_);
-
-  if (!acm2::RentACodec::IsPayloadTypeValid(rtp_payload_type)) {
-    RTC_LOG_F(LS_ERROR) << "Invalid payload-type " << rtp_payload_type
-                        << " for decoder.";
-    return false;
-  }
-
-  return receiver_.AddCodec(rtp_payload_type, audio_format);
-}
-
-int AudioCodingModuleImpl::RegisterExternalReceiveCodec(
-    int rtp_payload_type,
-    AudioDecoder* external_decoder,
-    int sample_rate_hz,
-    int num_channels,
-    const std::string& name) {
-  rtc::CritScope lock(&acm_crit_sect_);
-  RTC_DCHECK(receiver_initialized_);
-  if (num_channels > 2 || num_channels < 0) {
-    RTC_LOG_F(LS_ERROR) << "Unsupported number of channels: " << num_channels;
-    return -1;
-  }
-
-  // Check if the payload-type is valid.
-  if (!acm2::RentACodec::IsPayloadTypeValid(rtp_payload_type)) {
-    RTC_LOG_F(LS_ERROR) << "Invalid payload-type " << rtp_payload_type
-                        << " for external decoder.";
-    return -1;
-  }
-
-  return receiver_.AddCodec(-1 /* external */, rtp_payload_type, num_channels,
-                            sample_rate_hz, external_decoder, name);
-}
-
-// Get current received codec.
-int AudioCodingModuleImpl::ReceiveCodec(CodecInst* current_codec) const {
-  rtc::CritScope lock(&acm_crit_sect_);
-  return receiver_.LastAudioCodec(current_codec);
-}
-
-absl::optional<SdpAudioFormat> AudioCodingModuleImpl::ReceiveFormat() const {
-  rtc::CritScope lock(&acm_crit_sect_);
-  return receiver_.LastAudioFormat();
+  return receiver_.LastDecoder();
 }
 
 // Incoming packet from network parsed and ready for decode.
 int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
                                           const size_t payload_length,
-                                          const WebRtcRTPHeader& rtp_header) {
+                                          const RTPHeader& rtp_header) {
   RTC_DCHECK_EQ(payload_length == 0, incoming_payload == nullptr);
   return receiver_.InsertPacket(
       rtp_header,
@@ -825,6 +711,15 @@
   return receiver_.SetMaximumDelay(time_ms);
 }
 
+bool AudioCodingModuleImpl::SetBaseMinimumPlayoutDelayMs(int delay_ms) {
+  // All necessary validation happens on NetEq level.
+  return receiver_.SetBaseMinimumDelayMs(delay_ms);
+}
+
+int AudioCodingModuleImpl::GetBaseMinimumPlayoutDelayMs() const {
+  return receiver_.GetBaseMinimumDelayMs();
+}
+
 // Get 10 milliseconds of raw audio data to play out.
 // Automatic resample to the requested frequency.
 int AudioCodingModuleImpl::PlayoutData10Ms(int desired_freq_hz,
@@ -902,10 +797,6 @@
   return true;
 }
 
-int AudioCodingModuleImpl::UnregisterReceiveCodec(uint8_t payload_type) {
-  return receiver_.RemoveCodec(payload_type);
-}
-
 int AudioCodingModuleImpl::EnableNack(size_t max_nack_list_size) {
   return receiver_.EnableNack(max_nack_list_size);
 }
@@ -951,52 +842,4 @@
   return new AudioCodingModuleImpl(config);
 }
 
-int AudioCodingModule::NumberOfCodecs() {
-  return static_cast<int>(acm2::RentACodec::NumberOfCodecs());
-}
-
-int AudioCodingModule::Codec(int list_id, CodecInst* codec) {
-  auto codec_id = acm2::RentACodec::CodecIdFromIndex(list_id);
-  if (!codec_id)
-    return -1;
-  auto ci = acm2::RentACodec::CodecInstById(*codec_id);
-  if (!ci)
-    return -1;
-  *codec = *ci;
-  return 0;
-}
-
-int AudioCodingModule::Codec(const char* payload_name,
-                             CodecInst* codec,
-                             int sampling_freq_hz,
-                             size_t channels) {
-  absl::optional<CodecInst> ci = acm2::RentACodec::CodecInstByParams(
-      payload_name, sampling_freq_hz, channels);
-  if (ci) {
-    *codec = *ci;
-    return 0;
-  } else {
-    // We couldn't find a matching codec, so set the parameters to unacceptable
-    // values and return.
-    codec->plname[0] = '\0';
-    codec->pltype = -1;
-    codec->pacsize = 0;
-    codec->rate = 0;
-    codec->plfreq = 0;
-    return -1;
-  }
-}
-
-int AudioCodingModule::Codec(const char* payload_name,
-                             int sampling_freq_hz,
-                             size_t channels) {
-  absl::optional<acm2::RentACodec::CodecId> ci =
-      acm2::RentACodec::CodecIdByParams(payload_name, sampling_freq_hz,
-                                        channels);
-  if (!ci)
-    return -1;
-  absl::optional<int> i = acm2::RentACodec::CodecIndexFromId(*ci);
-  return i ? *i : -1;
-}
-
 }  // namespace webrtc
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index 4e262f7..4ee9add 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -13,17 +13,20 @@
 #include <memory>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
+#include "api/audio_codecs/opus/audio_decoder_opus.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/acm2/acm_receive_test.h"
 #include "modules/audio_coding/acm2/acm_send_test.h"
-#include "modules/audio_coding/codecs/audio_format_conversion.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/codecs/g711/audio_decoder_pcm.h"
 #include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
 #include "modules/audio_coding/codecs/isac/main/include/audio_encoder_isac.h"
+#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
+#include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
 #include "modules/audio_coding/neteq/tools/audio_checksum.h"
@@ -34,20 +37,21 @@
 #include "modules/audio_coding/neteq/tools/output_wav_file.h"
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/event.h"
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/platform_thread.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "rtc_base/system/arch.h"
 #include "rtc_base/thread_annotations.h"
 #include "system_wrappers/include/clock.h"
 #include "system_wrappers/include/sleep.h"
+#include "test/audio_decoder_proxy_factory.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder.h"
 #include "test/mock_audio_encoder.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using ::testing::AtLeast;
 using ::testing::Invoke;
@@ -71,21 +75,20 @@
 
   virtual ~RtpUtility() {}
 
-  void Populate(WebRtcRTPHeader* rtp_header) {
-    rtp_header->header.sequenceNumber = 0xABCD;
-    rtp_header->header.timestamp = 0xABCDEF01;
-    rtp_header->header.payloadType = payload_type_;
-    rtp_header->header.markerBit = false;
-    rtp_header->header.ssrc = 0x1234;
-    rtp_header->header.numCSRCs = 0;
-    rtp_header->frameType = kAudioFrameSpeech;
+  void Populate(RTPHeader* rtp_header) {
+    rtp_header->sequenceNumber = 0xABCD;
+    rtp_header->timestamp = 0xABCDEF01;
+    rtp_header->payloadType = payload_type_;
+    rtp_header->markerBit = false;
+    rtp_header->ssrc = 0x1234;
+    rtp_header->numCSRCs = 0;
 
-    rtp_header->header.payload_type_frequency = kSampleRateHz;
+    rtp_header->payload_type_frequency = kSampleRateHz;
   }
 
-  void Forward(WebRtcRTPHeader* rtp_header) {
-    ++rtp_header->header.sequenceNumber;
-    rtp_header->header.timestamp += samples_per_packet_;
+  void Forward(RTPHeader* rtp_header) {
+    ++rtp_header->sequenceNumber;
+    rtp_header->timestamp += samples_per_packet_;
   }
 
  private:
@@ -190,12 +193,11 @@
   // Set up L16 codec.
   virtual void SetUpL16Codec() {
     audio_format_ = SdpAudioFormat("L16", kSampleRateHz, 1);
-    ASSERT_EQ(0, AudioCodingModule::Codec("L16", &codec_, kSampleRateHz, 1));
-    codec_.pltype = kPayloadType;
+    pac_size_ = 160;
   }
 
   virtual void RegisterCodec() {
-    EXPECT_EQ(true, acm_->RegisterReceiveCodec(kPayloadType, *audio_format_));
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_}});
     acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
         kPayloadType, *audio_format_, absl::nullopt));
   }
@@ -226,7 +228,7 @@
 
   virtual void VerifyEncoding() {
     int last_length = packet_cb_.last_payload_len_bytes();
-    EXPECT_TRUE(last_length == 2 * codec_.pacsize || last_length == 0)
+    EXPECT_TRUE(last_length == 2 * pac_size_ || last_length == 0)
         << "Last encoded packet was " << last_length << " bytes.";
   }
 
@@ -238,13 +240,11 @@
   std::unique_ptr<RtpUtility> rtp_utility_;
   std::unique_ptr<AudioCodingModule> acm_;
   PacketizationCallbackStubOldApi packet_cb_;
-  WebRtcRTPHeader rtp_header_;
+  RTPHeader rtp_header_;
   AudioFrame input_frame_;
 
-  // These two have to be kept in sync for now. In the future, we'll be able to
-  // eliminate the CodecInst and keep only the SdpAudioFormat.
   absl::optional<SdpAudioFormat> audio_format_;
-  CodecInst codec_;
+  int pac_size_ = -1;
 
   Clock* clock_;
 };
@@ -343,7 +343,7 @@
 // Also checks that the frame type is kAudioFrameSpeech.
 TEST_F(AudioCodingModuleTestOldApi, TransportCallbackIsInvokedForEachPacket) {
   const int k10MsBlocksPerPacket = 3;
-  codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
+  pac_size_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
   audio_format_->parameters["ptime"] = "30";
   RegisterCodec();
   const int kLoops = 10;
@@ -363,7 +363,7 @@
 TEST_F(AudioCodingModuleTestOldApi, TimestampSeriesContinuesWhenCodecChanges) {
   RegisterCodec();  // This registers the default codec.
   uint32_t expected_ts = input_frame_.timestamp_;
-  int blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
+  int blocks_per_packet = pac_size_ / (kSampleRateHz / 100);
   // Encode 5 packets of the first codec type.
   const int kNumPackets1 = 5;
   for (int j = 0; j < kNumPackets1; ++j) {
@@ -373,14 +373,14 @@
     }
     EXPECT_EQ(j + 1, packet_cb_.num_calls());
     EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
-    expected_ts += codec_.pacsize;
+    expected_ts += pac_size_;
   }
 
   // Change codec.
-  ASSERT_EQ(0, AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1));
   audio_format_ = SdpAudioFormat("ISAC", kSampleRateHz, 1);
+  pac_size_ = 480;
   RegisterCodec();
-  blocks_per_packet = codec_.pacsize / (kSampleRateHz / 100);
+  blocks_per_packet = pac_size_ / (kSampleRateHz / 100);
   // Encode another 5 packets.
   const int kNumPackets2 = 5;
   for (int j = 0; j < kNumPackets2; ++j) {
@@ -390,7 +390,7 @@
     }
     EXPECT_EQ(kNumPackets1 + j + 1, packet_cb_.num_calls());
     EXPECT_EQ(expected_ts, packet_cb_.last_timestamp());
-    expected_ts += codec_.pacsize;
+    expected_ts += pac_size_;
   }
 }
 #endif
@@ -404,9 +404,8 @@
     : public AudioCodingModuleTestOldApi {
  protected:
   void RegisterCngCodec(int rtp_payload_type) {
-    EXPECT_EQ(true,
-              acm_->RegisterReceiveCodec(
-                  rtp_payload_type, SdpAudioFormat("cn", kSampleRateHz, 1)));
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_},
+                            {rtp_payload_type, {"cn", kSampleRateHz, 1}}});
     acm_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* enc) {
       AudioEncoderCngConfig config;
       config.speech_encoder = std::move(*enc);
@@ -461,7 +460,7 @@
 TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi,
        TransportCallbackTestForComfortNoiseRegisterCngLast) {
   const int k10MsBlocksPerPacket = 3;
-  codec_.pacsize = k10MsBlocksPerPacket * kSampleRateHz / 100;
+  pac_size_ = k10MsBlocksPerPacket * kSampleRateHz / 100;
   audio_format_->parameters["ptime"] = "30";
   RegisterCodec();
   const int kCngPayloadType = 105;
@@ -650,12 +649,11 @@
   void RegisterCodec() override {
     static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
     audio_format_ = SdpAudioFormat("isac", kSampleRateHz, 1);
-    AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
-    codec_.pltype = kPayloadType;
+    pac_size_ = 480;
 
     // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
     // registered in AudioCodingModuleTestOldApi::SetUp();
-    EXPECT_EQ(true, acm_->RegisterReceiveCodec(kPayloadType, *audio_format_));
+    acm_->SetReceiveCodecs({{kPayloadType, *audio_format_}});
     acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->MakeAudioEncoder(
         kPayloadType, *audio_format_, absl::nullopt));
   }
@@ -755,15 +753,11 @@
   }
 
   void RegisterCodec() override {
-    static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
-    AudioCodingModule::Codec("ISAC", &codec_, kSampleRateHz, 1);
-    codec_.pltype = kPayloadType;
-
     // Register iSAC codec in ACM, effectively unregistering the PCM16B codec
     // registered in AudioCodingModuleTestOldApi::SetUp();
     // Only register the decoder for now. The encoder is registered later.
-    ASSERT_EQ(true, acm_->RegisterReceiveCodec(codec_.pltype,
-                                               CodecInstToSdp(codec_)));
+    static_assert(kSampleRateHz == 16000, "test designed for iSAC 16 kHz");
+    acm_->SetReceiveCodecs({{kPayloadType, {"ISAC", kSampleRateHz, 1}}});
   }
 
   void StartThreads() {
@@ -801,16 +795,15 @@
       ++receive_packet_count_;
 
       // Encode new frame.
-      uint32_t input_timestamp = rtp_header_.header.timestamp;
+      uint32_t input_timestamp = rtp_header_.timestamp;
       while (info.encoded_bytes == 0) {
         info = isac_encoder_->Encode(input_timestamp,
                                      audio_loop_.GetNextBlock(), &encoded);
         input_timestamp += 160;  // 10 ms at 16 kHz.
       }
-      EXPECT_EQ(rtp_header_.header.timestamp + kPacketSizeSamples,
-                input_timestamp);
-      EXPECT_EQ(rtp_header_.header.timestamp, info.encoded_timestamp);
-      EXPECT_EQ(rtp_header_.header.payloadType, info.payload_type);
+      EXPECT_EQ(rtp_header_.timestamp + kPacketSizeSamples, input_timestamp);
+      EXPECT_EQ(rtp_header_.timestamp, info.encoded_timestamp);
+      EXPECT_EQ(rtp_header_.payloadType, info.payload_type);
     }
     // Now we're not holding the crit sect when calling ACM.
 
@@ -946,7 +939,7 @@
             ->test_case_name() +
         "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
         "_output.wav";
-    test::OutputWavFile output_file(output_file_name, output_freq_hz);
+    test::OutputWavFile output_file(output_file_name, output_freq_hz, 1);
     test::AudioSinkFork output(&checksum, &output_file);
 
     test::AcmReceiveTestOldApi test(
@@ -968,35 +961,35 @@
 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
     defined(WEBRTC_CODEC_ILBC)
 TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
-  Run(8000, PlatformChecksum("7294941b62293e143d6d6c84955923fd",
-                             "f26b8c9aa8257c7185925fa5b102f46a",
-                             "65e5ef5c3de9c2abf3c8d0989772e9fc",
+  Run(8000, PlatformChecksum("bcfbe2e89b4317b22e29557168edf187",
+                             "af15addb648cf7f032d6415672365fb3",
+                             "54a0008eb79537dee1d8fdaa5bc29f4b",
                              "4598140b5e4f7ee66c5adad609e65a3e",
-                             "04a1d3e735730b6d7dbd5df10f717d27"));
+                             "3155d7f2593a3276986f36221a61783c"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
-  Run(16000, PlatformChecksum("de8143dd3cc23241f1e1d5cf14e04b8a",
-                              "eada3f321120d8d5afffbe4170a55d2f",
-                              "135d8c3c7b92aa13d45cad7c91068e3e",
+  Run(16000, PlatformChecksum("1737deef193e6c90e139ce82b7361ae4",
+                              "9e2a9f7728c71d6559ce3a32d2b10a5d",
+                              "114958862099142ac78b12100c21cb8d",
                               "f2aad418af974a3b1694d5ae5cc2c3c7",
-                              "728b69068332efade35b1a9c32029e1b"));
+                              "af2889a5ca84fb40c9aa209b9318ee7a"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
-  Run(32000, PlatformChecksum("521d336237bdcc9ab44050e9da8917fc",
-                              "73d44a7bedb6dfa7c70cf997223d8c10",
-                              "f3ee2f14b03fb8e98f526f82583f84d9",
+  Run(32000, PlatformChecksum("1bf40ff024c6aa5b832d1d242c29cb3b",
+                              "3c9690cd136e9ecd1b26a22f70fe1d5c",
+                              "a1a3a01d8e25fcd11f1cedcd02e968b8",
                               "100869c8dcde51346c2073e52a272d98",
-                              "5f338b4bc38707d0a14d75a357e1546e"));
+                              "33695077e9ec6bca80819ce2ba263a78"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
-  Run(48000, PlatformChecksum("5955e31373828969de7fb308fb58a84e",
-                              "83c0eca235b1a806426ff6ca8655cdf7",
-                              "1126a8c03d1ebc6aa7348b9c541e2082",
+  Run(48000, PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
+                              "c37b110ab50d87620972daee5d1eaf31",
+                              "5d55b68be7bcf39b60fcc74519363fb4",
                               "bd44bf97e7899186532f91235cef444d",
-                              "9d092dbc96e7ef6870b78c1056e87315"));
+                              "32eec738698ffe62b9777d6a349cd596"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
@@ -1079,13 +1072,23 @@
   rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
       new rtc::RefCountedObject<ADFactory>);
   Run(48000,
-      PlatformChecksum("5955e31373828969de7fb308fb58a84e",
-                       "83c0eca235b1a806426ff6ca8655cdf7",
-                       "1126a8c03d1ebc6aa7348b9c541e2082",
+      PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
+                       "c37b110ab50d87620972daee5d1eaf31",
+                       "5d55b68be7bcf39b60fcc74519363fb4",
                        "bd44bf97e7899186532f91235cef444d",
-                       "9d092dbc96e7ef6870b78c1056e87315"),
+                       "32eec738698ffe62b9777d6a349cd596"),
       factory, [](AudioCodingModule* acm) {
-        acm->RegisterReceiveCodec(0, {"MockPCMu", 8000, 1});
+        acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}},
+                               {103, {"ISAC", 16000, 1}},
+                               {104, {"ISAC", 32000, 1}},
+                               {93, {"L16", 8000, 1}},
+                               {94, {"L16", 16000, 1}},
+                               {95, {"L16", 32000, 1}},
+                               {8, {"PCMA", 8000, 1}},
+                               {102, {"ILBC", 8000, 1}},
+                               {13, {"CN", 8000, 1}},
+                               {98, {"CN", 16000, 1}},
+                               {99, {"CN", 32000, 1}}});
       });
 }
 #endif
@@ -1117,15 +1120,12 @@
 
   // Sets up the test::AcmSendTest object. Returns true on success, otherwise
   // false.
-  bool SetUpSender() {
-    const std::string input_file_name =
-        webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+  bool SetUpSender(std::string input_file_name, int source_rate) {
     // Note that |audio_source_| will loop forever. The test duration is set
     // explicitly by |kTestDurationMs|.
     audio_source_.reset(new test::InputAudioFile(input_file_name));
-    static const int kSourceRateHz = 32000;
-    send_test_.reset(new test::AcmSendTestOldApi(
-        audio_source_.get(), kSourceRateHz, kTestDurationMs));
+    send_test_.reset(new test::AcmSendTestOldApi(audio_source_.get(),
+                                                 source_rate, kTestDurationMs));
     return send_test_.get() != NULL;
   }
 
@@ -1158,7 +1158,11 @@
   void Run(const std::string& audio_checksum_ref,
            const std::string& payload_checksum_ref,
            int expected_packets,
-           test::AcmReceiveTestOldApi::NumOutputChannels expected_channels) {
+           test::AcmReceiveTestOldApi::NumOutputChannels expected_channels,
+           rtc::scoped_refptr<AudioDecoderFactory> decoder_factory = nullptr) {
+    if (!decoder_factory) {
+      decoder_factory = CreateBuiltinAudioDecoderFactory();
+    }
     // Set up the receiver used to decode the packets and verify the decoded
     // output.
     test::AudioChecksum audio_checksum;
@@ -1170,12 +1174,12 @@
         "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
         "_output.wav";
     const int kOutputFreqHz = 8000;
-    test::OutputWavFile output_file(output_file_name, kOutputFreqHz);
+    test::OutputWavFile output_file(output_file_name, kOutputFreqHz,
+                                    expected_channels);
     // Have the output audio sent both to file and to the checksum calculator.
     test::AudioSinkFork output(&audio_checksum, &output_file);
     test::AcmReceiveTestOldApi receive_test(this, &output, kOutputFreqHz,
-                                            expected_channels,
-                                            CreateBuiltinAudioDecoderFactory());
+                                            expected_channels, decoder_factory);
     ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
 
     // This is where the actual test is executed.
@@ -1251,7 +1255,8 @@
                  int payload_type,
                  int codec_frame_size_samples,
                  int codec_frame_size_rtp_timestamps) {
-    ASSERT_TRUE(SetUpSender());
+    ASSERT_TRUE(SetUpSender(
+        channels == 1 ? kTestFileMono32kHz : kTestFileFakeStereo32kHz, 32000));
     ASSERT_TRUE(RegisterSendCodec(codec_name, codec_sample_rate_hz, channels,
                                   payload_type, codec_frame_size_samples,
                                   codec_frame_size_rtp_timestamps));
@@ -1260,7 +1265,7 @@
   void SetUpTestExternalEncoder(
       std::unique_ptr<AudioEncoder> external_speech_encoder,
       int payload_type) {
-    ASSERT_TRUE(SetUpSender());
+    ASSERT_TRUE(send_test_);
     RegisterExternalSendCodec(std::move(external_speech_encoder), payload_type);
   }
 
@@ -1272,6 +1277,14 @@
   uint16_t last_sequence_number_;
   uint32_t last_timestamp_;
   std::unique_ptr<rtc::MessageDigest> payload_checksum_;
+  const std::string kTestFileMono32kHz =
+      webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
+  const std::string kTestFileFakeStereo32kHz =
+      webrtc::test::ResourcePath("audio_coding/testfile_fake_stereo_32kHz",
+                                 "pcm");
+  const std::string kTestFileQuad48kHz = webrtc::test::ResourcePath(
+      "audio_coding/speech_4_channels_48k_one_second",
+      "wav");
 };
 
 class AcmSenderBitExactnessNewApi : public AcmSenderBitExactnessOldApi {};
@@ -1471,7 +1484,7 @@
         "ab88b1a049c36bdfeb7e8b057ef6982a",
         "27fef7b799393347ec3b5694369a1c36",
         "27fef7b799393347ec3b5694369a1c36");
-};  // namespace
+}  // namespace
 
 TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960));
@@ -1482,17 +1495,59 @@
 TEST_F(AcmSenderBitExactnessNewApi, MAYBE_OpusFromFormat_stereo_20ms) {
   const auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
+  ASSERT_TRUE(SetUpSender(kTestFileFakeStereo32kHz, 32000));
   ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
       AudioEncoderOpus::MakeAudioEncoder(*config, 120), 120));
   Run(audio_checksum, payload_checksum, 50,
       test::AcmReceiveTestOldApi::kStereoOutput);
 }
 
+TEST_F(AcmSenderBitExactnessNewApi, OpusManyChannels) {
+  constexpr int kNumChannels = 4;
+  constexpr int kOpusPayloadType = 120;
+  constexpr int kBitrateBps = 128000;
+
+  // Read a 4 channel file at 48kHz.
+  ASSERT_TRUE(SetUpSender(kTestFileQuad48kHz, 48000));
+
+  // TODO(webrtc:8649): change to higher level
+  // AudioEncoderOpus::MakeAudioEncoder once a multistream encoder can be set up
+  // from SDP.
+  AudioEncoderOpusConfig config = *AudioEncoderOpus::SdpToConfig(
+      SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
+  config.num_channels = kNumChannels;
+  config.bitrate_bps = kBitrateBps;
+
+  ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
+      absl::make_unique<AudioEncoderOpusImpl>(config, kOpusPayloadType),
+      kOpusPayloadType));
+
+  AudioDecoderOpusImpl opus_decoder(kNumChannels);
+
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&opus_decoder);
+
+  // Set up an EXTERNAL DECODER to parse 4 channels.
+  Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(  // audio checksum
+          "b70470884d9a8613eff019b0d1c8876e|d0a73d377e0ca1be6b06e989e0ad2c35",
+          "d0a73d377e0ca1be6b06e989e0ad2c35",
+          "b45d2ce5fc4723e9eb41350af9c68f56", "android arm64 audio checksum",
+          "1c9a3c9dacdd4b8fc9ff608227e531f2"),
+      // payload_checksum,
+      AcmReceiverBitExactnessOldApi::PlatformChecksum(  // payload checksum
+          "c2e7d40f8269ef754bd86d6be9623fa7|76de0f4992e3937ca60d35bbb0d308d6",
+          "76de0f4992e3937ca60d35bbb0d308d6",
+          "2a310aca965c16c2dfd61a9f9fc0c877", "android arm64 payload checksum",
+          "2294f4b61fb8f174f5196776a0a49be7"),
+      50, test::AcmReceiveTestOldApi::kQuadOutput, decoder_factory);
+}
+
 TEST_F(AcmSenderBitExactnessNewApi, OpusFromFormat_stereo_20ms_voip) {
   auto config = AudioEncoderOpus::SdpToConfig(
       SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}}));
   // If not set, default will be kAudio in case of stereo.
   config->application = AudioEncoderOpusConfig::ApplicationMode::kVoip;
+  ASSERT_TRUE(SetUpSender(kTestFileFakeStereo32kHz, 32000));
   ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder(
       AudioEncoderOpus::MakeAudioEncoder(*config, 120), 120));
   // Checksum depends on libopus being compiled with or without SSE.
@@ -1746,11 +1801,11 @@
 }
 
 TEST_F(AcmSenderBitExactnessOldApi, External_Pcmu_20ms) {
-  CodecInst codec_inst;
-  codec_inst.channels = 1;
-  codec_inst.pacsize = 160;
-  codec_inst.pltype = 0;
-  AudioEncoderPcmU encoder(codec_inst);
+  AudioEncoderPcmU::Config config;
+  config.frame_size_ms = 20;
+  config.num_channels = 1;
+  config.payload_type = 0;
+  AudioEncoderPcmU encoder(config);
   auto mock_encoder = absl::make_unique<MockAudioEncoder>();
   // Set expectations on the mock encoder and also delegate the calls to the
   // real encoder.
@@ -1776,8 +1831,9 @@
           &encoder, static_cast<AudioEncoder::EncodedInfo (AudioEncoder::*)(
                         uint32_t, rtc::ArrayView<const int16_t>, rtc::Buffer*)>(
                         &AudioEncoderPcmU::Encode)));
+  ASSERT_TRUE(SetUpSender(kTestFileMono32kHz, 32000));
   ASSERT_NO_FATAL_FAILURE(
-      SetUpTestExternalEncoder(std::move(mock_encoder), codec_inst.pltype));
+      SetUpTestExternalEncoder(std::move(mock_encoder), config.payload_type));
   Run("81a9d4c0bb72e9becc43aef124c981e9", "8f9b8750bd80fe26b6cbf6659b89f0f9",
       50, test::AcmReceiveTestOldApi::kMonoOutput);
 }
diff --git a/modules/audio_coding/acm2/rent_a_codec.cc b/modules/audio_coding/acm2/rent_a_codec.cc
deleted file mode 100644
index bfddc42b..0000000
--- a/modules/audio_coding/acm2/rent_a_codec.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *  Copyright (c) 2015 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_coding/acm2/rent_a_codec.h"
-
-#include <memory>
-#include <utility>
-
-#include "rtc_base/logging.h"
-#include "modules/audio_coding/acm2/acm_codec_database.h"
-
-namespace webrtc {
-namespace acm2 {
-
-absl::optional<RentACodec::CodecId> RentACodec::CodecIdByParams(
-    const char* payload_name,
-    int sampling_freq_hz,
-    size_t channels) {
-  return CodecIdFromIndex(
-      ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels));
-}
-
-absl::optional<CodecInst> RentACodec::CodecInstById(CodecId codec_id) {
-  absl::optional<int> mi = CodecIndexFromId(codec_id);
-  return mi ? absl::optional<CodecInst>(ACMCodecDB::database_[*mi])
-            : absl::nullopt;
-}
-
-absl::optional<RentACodec::CodecId> RentACodec::CodecIdByInst(
-    const CodecInst& codec_inst) {
-  return CodecIdFromIndex(ACMCodecDB::CodecNumber(codec_inst));
-}
-
-absl::optional<CodecInst> RentACodec::CodecInstByParams(
-    const char* payload_name,
-    int sampling_freq_hz,
-    size_t channels) {
-  absl::optional<CodecId> codec_id =
-      CodecIdByParams(payload_name, sampling_freq_hz, channels);
-  if (!codec_id)
-    return absl::nullopt;
-  absl::optional<CodecInst> ci = CodecInstById(*codec_id);
-  RTC_DCHECK(ci);
-
-  // Keep the number of channels from the function call. For most codecs it
-  // will be the same value as in default codec settings, but not for all.
-  ci->channels = channels;
-
-  return ci;
-}
-
-absl::optional<NetEqDecoder> RentACodec::NetEqDecoderFromCodecId(
-    CodecId codec_id,
-    size_t num_channels) {
-  absl::optional<int> i = CodecIndexFromId(codec_id);
-  if (!i)
-    return absl::nullopt;
-  const NetEqDecoder ned = ACMCodecDB::neteq_decoders_[*i];
-  return (ned == NetEqDecoder::kDecoderOpus && num_channels == 2)
-             ? NetEqDecoder::kDecoderOpus_2ch
-             : ned;
-}
-
-}  // namespace acm2
-}  // namespace webrtc
diff --git a/modules/audio_coding/acm2/rent_a_codec.h b/modules/audio_coding/acm2/rent_a_codec.h
deleted file mode 100644
index 2cf1c6e..0000000
--- a/modules/audio_coding/acm2/rent_a_codec.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *  Copyright (c) 2015 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_CODING_ACM2_RENT_A_CODEC_H_
-#define MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
-
-#include <stddef.h>
-#include <map>
-#include <memory>
-
-#include "absl/types/optional.h"
-#include "api/array_view.h"
-#include "api/audio_codecs/audio_decoder.h"
-#include "api/audio_codecs/audio_encoder.h"
-#include "modules/audio_coding/include/audio_coding_module_typedefs.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
-
-namespace webrtc {
-
-struct CodecInst;
-class LockedIsacBandwidthInfo;
-
-namespace acm2 {
-
-struct RentACodec {
-  enum class CodecId {
-#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
-    kISAC,
-#endif
-#ifdef WEBRTC_CODEC_ISAC
-    kISACSWB,
-#endif
-    // Mono
-    kPCM16B,
-    kPCM16Bwb,
-    kPCM16Bswb32kHz,
-    // Stereo
-    kPCM16B_2ch,
-    kPCM16Bwb_2ch,
-    kPCM16Bswb32kHz_2ch,
-    // Mono
-    kPCMU,
-    kPCMA,
-    // Stereo
-    kPCMU_2ch,
-    kPCMA_2ch,
-#ifdef WEBRTC_CODEC_ILBC
-    kILBC,
-#endif
-    kG722,      // Mono
-    kG722_2ch,  // Stereo
-#ifdef WEBRTC_CODEC_OPUS
-    kOpus,  // Mono and stereo
-#endif
-    kCNNB,
-    kCNWB,
-    kCNSWB,
-#ifdef ENABLE_48000_HZ
-    kCNFB,
-#endif
-    kAVT,
-    kAVT16kHz,
-    kAVT32kHz,
-    kAVT48kHz,
-#ifdef WEBRTC_CODEC_RED
-    kRED,
-#endif
-    kNumCodecs,  // Implementation detail. Don't use.
-
-// Set unsupported codecs to -1.
-#if !defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX)
-    kISAC = -1,
-#endif
-#ifndef WEBRTC_CODEC_ISAC
-    kISACSWB = -1,
-#endif
-    // 48 kHz not supported, always set to -1.
-    kPCM16Bswb48kHz = -1,
-#ifndef WEBRTC_CODEC_ILBC
-    kILBC = -1,
-#endif
-#ifndef WEBRTC_CODEC_OPUS
-    kOpus = -1,  // Mono and stereo
-#endif
-#ifndef WEBRTC_CODEC_RED
-    kRED = -1,
-#endif
-#ifndef ENABLE_48000_HZ
-    kCNFB = -1,
-#endif
-
-    kNone = -1
-  };
-
-  static inline size_t NumberOfCodecs() {
-    return static_cast<size_t>(CodecId::kNumCodecs);
-  }
-
-  static inline absl::optional<int> CodecIndexFromId(CodecId codec_id) {
-    const int i = static_cast<int>(codec_id);
-    return i >= 0 && i < static_cast<int>(NumberOfCodecs())
-               ? absl::optional<int>(i)
-               : absl::nullopt;
-  }
-
-  static inline absl::optional<CodecId> CodecIdFromIndex(int codec_index) {
-    return static_cast<size_t>(codec_index) < NumberOfCodecs()
-               ? absl::optional<RentACodec::CodecId>(
-                     static_cast<RentACodec::CodecId>(codec_index))
-               : absl::nullopt;
-  }
-
-  static absl::optional<CodecId> CodecIdByParams(const char* payload_name,
-                                                 int sampling_freq_hz,
-                                                 size_t channels);
-  static absl::optional<CodecInst> CodecInstById(CodecId codec_id);
-  static absl::optional<CodecId> CodecIdByInst(const CodecInst& codec_inst);
-  static absl::optional<CodecInst> CodecInstByParams(const char* payload_name,
-                                                     int sampling_freq_hz,
-                                                     size_t channels);
-
-  static inline bool IsPayloadTypeValid(int payload_type) {
-    return payload_type >= 0 && payload_type <= 127;
-  }
-
-  static absl::optional<NetEqDecoder> NetEqDecoderFromCodecId(
-      CodecId codec_id,
-      size_t num_channels);
-};
-
-}  // namespace acm2
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_ACM2_RENT_A_CODEC_H_
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
index 9e47a06..ff6ac01 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
 #include "modules/audio_coding/audio_network_adaptor/event_log_writer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -29,7 +29,7 @@
 constexpr float kEventLogMinPacketLossChangeFraction = 0.5;
 }  // namespace
 
-AudioNetworkAdaptorImpl::Config::Config() : event_log(nullptr){};
+AudioNetworkAdaptorImpl::Config::Config() : event_log(nullptr) {}
 
 AudioNetworkAdaptorImpl::Config::~Config() = default;
 
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
index 4c1c19b..fc2358b 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
@@ -20,7 +20,7 @@
 #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
index be9550a..76531d0 100644
--- a/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
@@ -18,7 +18,7 @@
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
 
diff --git a/modules/audio_coding/audio_network_adaptor/bitrate_controller.h b/modules/audio_coding/audio_network_adaptor/bitrate_controller.h
index 6b6330b..41bfbd1 100644
--- a/modules/audio_coding/audio_network_adaptor/bitrate_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/bitrate_controller.h
@@ -16,7 +16,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace audio_network_adaptor {
diff --git a/modules/audio_coding/audio_network_adaptor/channel_controller.h b/modules/audio_coding/audio_network_adaptor/channel_controller.h
index 0d775b1..f211f40 100644
--- a/modules/audio_coding/audio_network_adaptor/channel_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/channel_controller.h
@@ -16,7 +16,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager.cc b/modules/audio_coding/audio_network_adaptor/controller_manager.cc
index 32f9fcb..4c0e61c 100644
--- a/modules/audio_coding/audio_network_adaptor/controller_manager.cc
+++ b/modules/audio_coding/audio_network_adaptor/controller_manager.cc
@@ -11,6 +11,7 @@
 #include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
 
 #include <cmath>
+#include <string>
 #include <utility>
 
 #include "modules/audio_coding/audio_network_adaptor/bitrate_controller.h"
@@ -22,7 +23,7 @@
 #include "modules/audio_coding/audio_network_adaptor/frame_length_controller.h"
 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
 #include "rtc_base/ignore_wundef.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 #if WEBRTC_ENABLE_PROTOBUF
 RTC_PUSH_IGNORING_WUNDEF()
@@ -147,13 +148,13 @@
   }
 
   FrameLengthController::Config ctor_config(
-      std::vector<int>(), initial_frame_length_ms, min_encoder_bitrate_bps,
+      std::set<int>(), initial_frame_length_ms, min_encoder_bitrate_bps,
       config.fl_increasing_packet_loss_fraction(),
       config.fl_decreasing_packet_loss_fraction(), fl_increase_overhead_offset,
       fl_decrease_overhead_offset, std::move(fl_changing_bandwidths_bps));
 
   for (auto frame_length : encoder_frame_lengths_ms)
-    ctor_config.encoder_frame_lengths_ms.push_back(frame_length);
+    ctor_config.encoder_frame_lengths_ms.insert(frame_length);
 
   return std::unique_ptr<FrameLengthController>(
       new FrameLengthController(ctor_config));
@@ -213,7 +214,7 @@
 ControllerManagerImpl::Config::~Config() = default;
 
 std::unique_ptr<ControllerManager> ControllerManagerImpl::Create(
-    const ProtoString& config_string,
+    const std::string& config_string,
     size_t num_encoder_channels,
     rtc::ArrayView<const int> encoder_frame_lengths_ms,
     int min_encoder_bitrate_bps,
@@ -229,7 +230,7 @@
 }
 
 std::unique_ptr<ControllerManager> ControllerManagerImpl::Create(
-    const ProtoString& config_string,
+    const std::string& config_string,
     size_t num_encoder_channels,
     rtc::ArrayView<const int> encoder_frame_lengths_ms,
     int min_encoder_bitrate_bps,
diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager.h b/modules/audio_coding/audio_network_adaptor/controller_manager.h
index 1ff9bbf..f46450d 100644
--- a/modules/audio_coding/audio_network_adaptor/controller_manager.h
+++ b/modules/audio_coding/audio_network_adaptor/controller_manager.h
@@ -13,11 +13,11 @@
 
 #include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/protobuf_utils.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -47,7 +47,7 @@
   };
 
   static std::unique_ptr<ControllerManager> Create(
-      const ProtoString& config_string,
+      const std::string& config_string,
       size_t num_encoder_channels,
       rtc::ArrayView<const int> encoder_frame_lengths_ms,
       int min_encoder_bitrate_bps,
@@ -58,7 +58,7 @@
       bool initial_dtx_enabled);
 
   static std::unique_ptr<ControllerManager> Create(
-      const ProtoString& config_string,
+      const std::string& config_string,
       size_t num_encoder_channels,
       rtc::ArrayView<const int> encoder_frame_lengths_ms,
       int min_encoder_bitrate_bps,
diff --git a/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc b/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc
index 061e4aa..ce47699 100644
--- a/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/controller_manager_unittest.cc
@@ -8,14 +8,14 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include <string>
 #include <utility>
 
 #include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "rtc_base/ignore_wundef.h"
-#include "rtc_base/protobuf_utils.h"
 #include "test/gtest.h"
 
 #if WEBRTC_ENABLE_PROTOBUF
@@ -266,7 +266,7 @@
 constexpr int kMinBitrateBps = 6000;
 
 ControllerManagerStates CreateControllerManager(
-    const ProtoString& config_string) {
+    const std::string& config_string) {
   ControllerManagerStates states;
   constexpr size_t kNumEncoderChannels = 2;
   const std::vector<int> encoder_frame_lengths_ms = {20, 60};
@@ -319,8 +319,8 @@
 }
 
 MATCHER_P(ControllerManagerEqual, value, "") {
-  ProtoString value_string;
-  ProtoString arg_string;
+  std::string value_string;
+  std::string arg_string;
   EXPECT_TRUE(arg.SerializeToString(&arg_string));
   EXPECT_TRUE(value.SerializeToString(&value_string));
   return arg_string == value_string;
@@ -339,7 +339,7 @@
   AddFrameLengthControllerConfig(&config);
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   constexpr size_t kNumEncoderChannels = 2;
@@ -373,7 +373,7 @@
   AddFrameLengthControllerConfig(&config);
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   auto states = CreateControllerManager(config_string);
@@ -395,7 +395,7 @@
   AddDtxControllerConfig(&config);
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   auto states = CreateControllerManager(config_string);
@@ -426,7 +426,7 @@
 
   AddBitrateControllerConfig(&config);
 
-  ProtoString config_string;
+  std::string config_string;
   config.SerializeToString(&config_string);
 
   auto states = CreateControllerManager(config_string);
diff --git a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
index 8e04e8e..805df0a 100644
--- a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
+++ b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.cc
@@ -10,11 +10,12 @@
 
 #include "modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
 
+#include <string>
+
 #include "absl/types/optional.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/protobuf_utils.h"
 #include "rtc_base/system/file_wrapper.h"
 
 #if WEBRTC_ENABLE_PROTOBUF
@@ -38,7 +39,7 @@
 
 void DumpEventToFile(const Event& event, FileWrapper* dump_file) {
   RTC_CHECK(dump_file->is_open());
-  ProtoString dump_data;
+  std::string dump_data;
   event.SerializeToString(&dump_data);
   int32_t size = rtc::checked_cast<int32_t>(event.ByteSizeLong());
   dump_file->Write(&size, sizeof(size));
@@ -67,14 +68,13 @@
 #endif
 
  private:
-  std::unique_ptr<FileWrapper> dump_file_;
+  FileWrapper dump_file_;
 };
 
-DebugDumpWriterImpl::DebugDumpWriterImpl(FILE* file_handle)
-    : dump_file_(FileWrapper::Create()) {
+DebugDumpWriterImpl::DebugDumpWriterImpl(FILE* file_handle) {
 #if WEBRTC_ENABLE_PROTOBUF
-  dump_file_->OpenFromFileHandle(file_handle);
-  RTC_CHECK(dump_file_->is_open());
+  dump_file_ = FileWrapper(file_handle);
+  RTC_CHECK(dump_file_.is_open());
 #else
   RTC_NOTREACHED();
 #endif
@@ -110,7 +110,7 @@
         *metrics.uplink_recoverable_packet_loss_fraction);
   }
 
-  DumpEventToFile(event, dump_file_.get());
+  DumpEventToFile(event, &dump_file_);
 #endif  // WEBRTC_ENABLE_PROTOBUF
 }
 
@@ -143,7 +143,7 @@
   if (config.num_channels)
     dump_config->set_num_channels(*config.num_channels);
 
-  DumpEventToFile(event, dump_file_.get());
+  DumpEventToFile(event, &dump_file_);
 #endif  // WEBRTC_ENABLE_PROTOBUF
 }
 
@@ -157,7 +157,7 @@
   event.set_type(Event::CONTROLLER_MANAGER_CONFIG);
   event.mutable_controller_manager_config()->CopyFrom(
       controller_manager_config);
-  DumpEventToFile(event, dump_file_.get());
+  DumpEventToFile(event, &dump_file_);
 }
 #endif  // WEBRTC_ENABLE_PROTOBUF
 
diff --git a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h
index b464eb6..367f659 100644
--- a/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h
+++ b/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h
@@ -15,7 +15,7 @@
 
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/system/file_wrapper.h"
 #if WEBRTC_ENABLE_PROTOBUF
diff --git a/modules/audio_coding/audio_network_adaptor/dtx_controller.h b/modules/audio_coding/audio_network_adaptor/dtx_controller.h
index d3334ec..83fdf3d 100644
--- a/modules/audio_coding/audio_network_adaptor/dtx_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/dtx_controller.h
@@ -14,7 +14,7 @@
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/event_log_writer.h b/modules/audio_coding/audio_network_adaptor/event_log_writer.h
index 72b5245..c5e57e6 100644
--- a/modules/audio_coding/audio_network_adaptor/event_log_writer.h
+++ b/modules/audio_coding/audio_network_adaptor/event_log_writer.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_
 
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 class RtcEventLog;
diff --git a/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc b/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
index 42189c3..b1e3313 100644
--- a/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
@@ -13,6 +13,7 @@
 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
 #include "modules/audio_coding/audio_network_adaptor/event_log_writer.h"
+#include "rtc_base/checks.h"
 #include "test/gtest.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h
index b7d3d56..87afe2e 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based.h
@@ -18,7 +18,7 @@
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
index de66717..d3f54ee 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_plr_based_unittest.cc
@@ -422,7 +422,7 @@
 
   // Test that FEC is turned on whenever we're on the curve or above it,
   // independent of the starting FEC state.
-  for (std::vector<NetworkState> states_list : {on, above}) {
+  for (const std::vector<NetworkState>& states_list : {on, above}) {
     for (NetworkState net_state : states_list) {
       for (bool initial_fec_enabled : {false, true}) {
         auto states =
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h
index 421cb70..c547bff 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based.h
@@ -15,7 +15,7 @@
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
 #include "modules/audio_coding/audio_network_adaptor/util/threshold_curve.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
index 8e8704e..4438a23 100644
--- a/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/fec_controller_rplr_based_unittest.cc
@@ -462,7 +462,7 @@
 
   // Test that FEC is turned on whenever we're on the curve or above it,
   // independent of the starting FEC state.
-  for (std::vector<NetworkState> states_list : {on, above}) {
+  for (const std::vector<NetworkState>& states_list : {on, above}) {
     for (NetworkState net_state : states_list) {
       for (bool initial_fec_enabled : {false, true}) {
         FecControllerRplrBased controller(
diff --git a/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc b/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc
index b123c7c..3cb91fd 100644
--- a/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc
+++ b/modules/audio_coding/audio_network_adaptor/frame_length_controller.cc
@@ -28,7 +28,7 @@
 }  // namespace
 
 FrameLengthController::Config::Config(
-    const std::vector<int>& encoder_frame_lengths_ms,
+    const std::set<int>& encoder_frame_lengths_ms,
     int initial_frame_length_ms,
     int min_encoder_bitrate_bps,
     float fl_increasing_packet_loss_fraction,
diff --git a/modules/audio_coding/audio_network_adaptor/frame_length_controller.h b/modules/audio_coding/audio_network_adaptor/frame_length_controller.h
index f0a5aab..e182247 100644
--- a/modules/audio_coding/audio_network_adaptor/frame_length_controller.h
+++ b/modules/audio_coding/audio_network_adaptor/frame_length_controller.h
@@ -13,12 +13,12 @@
 
 #include <stddef.h>
 #include <map>
-#include <vector>
+#include <set>
 
 #include "absl/types/optional.h"
 #include "modules/audio_coding/audio_network_adaptor/controller.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -33,7 +33,7 @@
       int from_frame_length_ms;
       int to_frame_length_ms;
     };
-    Config(const std::vector<int>& encoder_frame_lengths_ms,
+    Config(const std::set<int>& encoder_frame_lengths_ms,
            int initial_frame_length_ms,
            int min_encoder_bitrate_bps,
            float fl_increasing_packet_loss_fraction,
@@ -43,7 +43,7 @@
            std::map<FrameLengthChange, int> fl_changing_bandwidths_bps);
     Config(const Config& other);
     ~Config();
-    std::vector<int> encoder_frame_lengths_ms;
+    std::set<int> encoder_frame_lengths_ms;
     int initial_frame_length_ms;
     int min_encoder_bitrate_bps;
     // Uplink packet loss fraction below which frame length can increase.
@@ -74,7 +74,7 @@
 
   const Config config_;
 
-  std::vector<int>::const_iterator frame_length_ms_;
+  std::set<int>::const_iterator frame_length_ms_;
 
   absl::optional<int> uplink_bandwidth_bps_;
 
diff --git a/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc b/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
index f97ad4f..8d6d815 100644
--- a/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
+++ b/modules/audio_coding/audio_network_adaptor/frame_length_controller_unittest.cc
@@ -42,7 +42,7 @@
 std::unique_ptr<FrameLengthController> CreateController(
     const std::map<FrameLengthController::Config::FrameLengthChange, int>&
         frame_length_change_criteria,
-    const std::vector<int>& encoder_frame_lengths_ms,
+    const std::set<int>& encoder_frame_lengths_ms,
     int initial_frame_length_ms) {
   std::unique_ptr<FrameLengthController> controller(
       new FrameLengthController(FrameLengthController::Config(
diff --git a/modules/audio_coding/codecs/audio_format_conversion.cc b/modules/audio_coding/codecs/audio_format_conversion.cc
deleted file mode 100644
index f068301..0000000
--- a/modules/audio_coding/codecs/audio_format_conversion.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- *  Copyright (c) 2016 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_coding/codecs/audio_format_conversion.h"
-
-#include <string.h>
-#include <string>
-#include <utility>
-
-#include "absl/strings/match.h"
-#include "api/array_view.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/sanitizer.h"
-
-namespace webrtc {
-
-namespace {
-
-CodecInst MakeCodecInst(int payload_type,
-                        const char* name,
-                        int sample_rate,
-                        size_t num_channels) {
-  // Create a CodecInst with some fields set. The remaining fields are zeroed,
-  // but we tell MSan to consider them uninitialized.
-  CodecInst ci = {0};
-  rtc::MsanMarkUninitialized(rtc::MakeArrayView(&ci, 1));
-  ci.pltype = payload_type;
-  strncpy(ci.plname, name, sizeof(ci.plname));
-  ci.plname[sizeof(ci.plname) - 1] = '\0';
-  ci.plfreq = sample_rate;
-  ci.channels = num_channels;
-  return ci;
-}
-
-}  // namespace
-
-SdpAudioFormat CodecInstToSdp(const CodecInst& ci) {
-  if (absl::EqualsIgnoreCase(ci.plname, "g722")) {
-    RTC_CHECK_EQ(16000, ci.plfreq);
-    RTC_CHECK(ci.channels == 1 || ci.channels == 2);
-    return {"g722", 8000, ci.channels};
-  } else if (absl::EqualsIgnoreCase(ci.plname, "opus")) {
-    RTC_CHECK_EQ(48000, ci.plfreq);
-    RTC_CHECK(ci.channels == 1 || ci.channels == 2);
-    return ci.channels == 1
-               ? SdpAudioFormat("opus", 48000, 2)
-               : SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}});
-  } else {
-    return {ci.plname, ci.plfreq, ci.channels};
-  }
-}
-
-CodecInst SdpToCodecInst(int payload_type, const SdpAudioFormat& audio_format) {
-  if (absl::EqualsIgnoreCase(audio_format.name, "g722")) {
-    RTC_CHECK_EQ(8000, audio_format.clockrate_hz);
-    RTC_CHECK(audio_format.num_channels == 1 || audio_format.num_channels == 2);
-    return MakeCodecInst(payload_type, "g722", 16000,
-                         audio_format.num_channels);
-  } else if (absl::EqualsIgnoreCase(audio_format.name, "opus")) {
-    RTC_CHECK_EQ(48000, audio_format.clockrate_hz);
-    RTC_CHECK_EQ(2, audio_format.num_channels);
-    const int num_channels = [&] {
-      auto stereo = audio_format.parameters.find("stereo");
-      if (stereo != audio_format.parameters.end()) {
-        if (stereo->second == "0") {
-          return 1;
-        } else if (stereo->second == "1") {
-          return 2;
-        } else {
-          RTC_CHECK(false);  // Bad stereo parameter.
-        }
-      }
-      return 1;  // Default to mono.
-    }();
-    return MakeCodecInst(payload_type, "opus", 48000, num_channels);
-  } else {
-    return MakeCodecInst(payload_type, audio_format.name.c_str(),
-                         audio_format.clockrate_hz, audio_format.num_channels);
-  }
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_coding/codecs/audio_format_conversion.h b/modules/audio_coding/codecs/audio_format_conversion.h
deleted file mode 100644
index d981741..0000000
--- a/modules/audio_coding/codecs/audio_format_conversion.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- *  Copyright (c) 2016 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_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_
-#define MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_
-
-#include "api/audio_codecs/audio_format.h"
-#include "common_types.h"  // NOLINT(build/include)
-
-namespace webrtc {
-
-SdpAudioFormat CodecInstToSdp(const CodecInst& codec_inst);
-CodecInst SdpToCodecInst(int payload_type, const SdpAudioFormat& audio_format);
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_CODECS_AUDIO_FORMAT_CONVERSION_H_
diff --git a/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc b/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
index 64f0159..a548be8 100644
--- a/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
+++ b/modules/audio_coding/codecs/builtin_audio_encoder_factory_unittest.cc
@@ -103,9 +103,9 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(BuiltinAudioEncoderFactoryTest,
-                        AudioEncoderFactoryTest,
-                        ::testing::Values(CreateBuiltinAudioEncoderFactory()));
+INSTANTIATE_TEST_SUITE_P(BuiltinAudioEncoderFactoryTest,
+                         AudioEncoderFactoryTest,
+                         ::testing::Values(CreateBuiltinAudioEncoderFactory()));
 
 TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
   using ::testing::ElementsAreArray;
@@ -116,6 +116,7 @@
 
   const std::vector<SdpAudioFormat> supported_formats = [&specs] {
     std::vector<SdpAudioFormat> formats;
+    formats.reserve(specs.size());
     for (const auto& spec : specs) {
       formats.push_back(spec.format);
     }
diff --git a/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc b/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
index e3655b4..3ecefd4 100644
--- a/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
+++ b/modules/audio_coding/codecs/cng/audio_encoder_cng_unittest.cc
@@ -13,7 +13,7 @@
 
 #include "common_audio/vad/mock/mock_vad.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
 #include "test/mock_audio_encoder.h"
diff --git a/modules/audio_coding/codecs/cng/cng_unittest.cc b/modules/audio_coding/codecs/cng/cng_unittest.cc
index 81688b1..80349e2 100644
--- a/modules/audio_coding/codecs/cng/cng_unittest.cc
+++ b/modules/audio_coding/codecs/cng/cng_unittest.cc
@@ -12,7 +12,7 @@
 
 #include "modules/audio_coding/codecs/cng/webrtc_cng.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/g711/audio_decoder_pcm.h b/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
index 9a01b8a..8fae71c 100644
--- a/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
+++ b/modules/audio_coding/codecs/g711/audio_decoder_pcm.h
@@ -18,7 +18,7 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "rtc_base/buffer.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
index dce1635..fd560e4 100644
--- a/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
+++ b/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
@@ -12,25 +12,11 @@
 
 #include <cstdint>
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/g711/g711_interface.h"
 #include "rtc_base/checks.h"
 
 namespace webrtc {
 
-namespace {
-
-template <typename T>
-typename T::Config CreateConfig(const CodecInst& codec_inst) {
-  typename T::Config config;
-  config.frame_size_ms = codec_inst.pacsize / 8;
-  config.num_channels = codec_inst.channels;
-  config.payload_type = codec_inst.pltype;
-  return config;
-}
-
-}  // namespace
-
 bool AudioEncoderPcm::Config::IsOk() const {
   return (frame_size_ms % 10 == 0) && (num_channels >= 1);
 }
@@ -103,9 +89,6 @@
   speech_buffer_.clear();
 }
 
-AudioEncoderPcmA::AudioEncoderPcmA(const CodecInst& codec_inst)
-    : AudioEncoderPcmA(CreateConfig<AudioEncoderPcmA>(codec_inst)) {}
-
 size_t AudioEncoderPcmA::EncodeCall(const int16_t* audio,
                                     size_t input_len,
                                     uint8_t* encoded) {
@@ -120,9 +103,6 @@
   return AudioEncoder::CodecType::kPcmA;
 }
 
-AudioEncoderPcmU::AudioEncoderPcmU(const CodecInst& codec_inst)
-    : AudioEncoderPcmU(CreateConfig<AudioEncoderPcmU>(codec_inst)) {}
-
 size_t AudioEncoderPcmU::EncodeCall(const int16_t* audio,
                                     size_t input_len,
                                     uint8_t* encoded) {
diff --git a/modules/audio_coding/codecs/g711/audio_encoder_pcm.h b/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
index 37b67cf..e41c2a3 100644
--- a/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
+++ b/modules/audio_coding/codecs/g711/audio_encoder_pcm.h
@@ -14,7 +14,7 @@
 #include <vector>
 
 #include "api/audio_codecs/audio_encoder.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -69,8 +69,6 @@
   uint32_t first_timestamp_in_buffer_;
 };
 
-struct CodecInst;
-
 class AudioEncoderPcmA final : public AudioEncoderPcm {
  public:
   struct Config : public AudioEncoderPcm::Config {
@@ -79,7 +77,6 @@
 
   explicit AudioEncoderPcmA(const Config& config)
       : AudioEncoderPcm(config, kSampleRateHz) {}
-  explicit AudioEncoderPcmA(const CodecInst& codec_inst);
 
  protected:
   size_t EncodeCall(const int16_t* audio,
@@ -103,7 +100,6 @@
 
   explicit AudioEncoderPcmU(const Config& config)
       : AudioEncoderPcm(config, kSampleRateHz) {}
-  explicit AudioEncoderPcmU(const CodecInst& codec_inst);
 
  protected:
   size_t EncodeCall(const int16_t* audio,
diff --git a/modules/audio_coding/codecs/g722/audio_decoder_g722.h b/modules/audio_coding/codecs/g722/audio_decoder_g722.h
index 3240448..6911e0b 100644
--- a/modules/audio_coding/codecs/g722/audio_decoder_g722.h
+++ b/modules/audio_coding/codecs/g722/audio_decoder_g722.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_CODECS_G722_AUDIO_DECODER_G722_H_
 
 #include "api/audio_codecs/audio_decoder.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 typedef struct WebRtcG722DecInst G722DecInst;
 
diff --git a/modules/audio_coding/codecs/g722/audio_encoder_g722.cc b/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
index e63d590..d293163 100644
--- a/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
+++ b/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
@@ -12,7 +12,6 @@
 
 #include <cstdint>
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/g722/g722_interface.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
@@ -23,13 +22,6 @@
 
 const size_t kSampleRateHz = 16000;
 
-AudioEncoderG722Config CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderG722Config config;
-  config.num_channels = rtc::dchecked_cast<int>(codec_inst.channels);
-  config.frame_size_ms = codec_inst.pacsize / 16;
-  return config;
-}
-
 }  // namespace
 
 AudioEncoderG722Impl::AudioEncoderG722Impl(const AudioEncoderG722Config& config,
@@ -52,9 +44,6 @@
   Reset();
 }
 
-AudioEncoderG722Impl::AudioEncoderG722Impl(const CodecInst& codec_inst)
-    : AudioEncoderG722Impl(CreateConfig(codec_inst), codec_inst.pltype) {}
-
 AudioEncoderG722Impl::~AudioEncoderG722Impl() = default;
 
 int AudioEncoderG722Impl::SampleRateHz() const {
diff --git a/modules/audio_coding/codecs/g722/audio_encoder_g722.h b/modules/audio_coding/codecs/g722/audio_encoder_g722.h
index 3cf1439..cf45fb5 100644
--- a/modules/audio_coding/codecs/g722/audio_encoder_g722.h
+++ b/modules/audio_coding/codecs/g722/audio_encoder_g722.h
@@ -17,16 +17,13 @@
 #include "api/audio_codecs/g722/audio_encoder_g722_config.h"
 #include "modules/audio_coding/codecs/g722/g722_interface.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 class AudioEncoderG722Impl final : public AudioEncoder {
  public:
   AudioEncoderG722Impl(const AudioEncoderG722Config& config, int payload_type);
-  explicit AudioEncoderG722Impl(const CodecInst& codec_inst);
   ~AudioEncoderG722Impl() override;
 
   int SampleRateHz() const override;
diff --git a/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h b/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
index fcb2074..d73ef0d 100644
--- a/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h
@@ -17,7 +17,7 @@
 
 #include "api/audio_codecs/audio_decoder.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 typedef struct iLBC_decinst_t_ IlbcDecoderInstance;
 
diff --git a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
index 8801fd5..ac9214b 100644
--- a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
+++ b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
@@ -13,7 +13,6 @@
 #include <algorithm>
 #include <cstdint>
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/ilbc/ilbc.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
@@ -24,12 +23,6 @@
 
 const int kSampleRateHz = 8000;
 
-AudioEncoderIlbcConfig CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderIlbcConfig config;
-  config.frame_size_ms = codec_inst.pacsize / 8;
-  return config;
-}
-
 int GetIlbcBitrate(int ptime) {
   switch (ptime) {
     case 20:
@@ -58,9 +51,6 @@
   Reset();
 }
 
-AudioEncoderIlbcImpl::AudioEncoderIlbcImpl(const CodecInst& codec_inst)
-    : AudioEncoderIlbcImpl(CreateConfig(codec_inst), codec_inst.pltype) {}
-
 AudioEncoderIlbcImpl::~AudioEncoderIlbcImpl() {
   RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
 }
diff --git a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
index a238689..ada613b 100644
--- a/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
+++ b/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h
@@ -14,16 +14,13 @@
 #include "api/audio_codecs/audio_encoder.h"
 #include "api/audio_codecs/ilbc/audio_encoder_ilbc_config.h"
 #include "modules/audio_coding/codecs/ilbc/ilbc.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 class AudioEncoderIlbcImpl final : public AudioEncoder {
  public:
   AudioEncoderIlbcImpl(const AudioEncoderIlbcConfig& config, int payload_type);
-  explicit AudioEncoderIlbcImpl(const CodecInst& codec_inst);
   ~AudioEncoderIlbcImpl() override;
 
   int SampleRateHz() const override;
diff --git a/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc b/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
index 5ec1219..689292f 100644
--- a/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
+++ b/modules/audio_coding/codecs/ilbc/ilbc_unittest.cc
@@ -103,7 +103,7 @@
 // Also test the maximum number of frames in one packet for 20 and 30 ms.
 // The maximum is defined by the largest payload length that can be uniquely
 // resolved to a frame size of either 38 bytes (20 ms) or 50 bytes (30 ms).
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     IlbcTest,
     SplitIlbcTest,
     ::testing::Values(std::pair<int, int>(1, 20),  // 1 frame, 20 ms.
diff --git a/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
index f840ffa..7cadd91 100644
--- a/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
+++ b/modules/audio_coding/codecs/isac/audio_decoder_isac_t.h
@@ -15,9 +15,9 @@
 
 #include "absl/types/optional.h"
 #include "api/audio_codecs/audio_decoder.h"
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
index 541b90c..c6ef795 100644
--- a/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
@@ -14,14 +14,12 @@
 #include <vector>
 
 #include "api/audio_codecs/audio_encoder.h"
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/codecs/isac/locked_bandwidth_info.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 template <typename T>
 class AudioEncoderIsacT final : public AudioEncoder {
  public:
@@ -52,9 +50,6 @@
   };
 
   explicit AudioEncoderIsacT(const Config& config);
-  explicit AudioEncoderIsacT(
-      const CodecInst& codec_inst,
-      const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo);
   ~AudioEncoderIsacT() override;
 
   int SampleRateHz() const override;
diff --git a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
index cbf15fc..3448139 100644
--- a/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
+++ b/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h
@@ -11,28 +11,11 @@
 #ifndef MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
 #define MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_IMPL_H_
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "rtc_base/checks.h"
 
 namespace webrtc {
 
 template <typename T>
-typename AudioEncoderIsacT<T>::Config CreateIsacConfig(
-    const CodecInst& codec_inst,
-    const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo) {
-  typename AudioEncoderIsacT<T>::Config config;
-  config.bwinfo = bwinfo;
-  config.payload_type = codec_inst.pltype;
-  config.sample_rate_hz = codec_inst.plfreq;
-  config.frame_size_ms =
-      rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
-  config.adaptive_mode = (codec_inst.rate == -1);
-  if (codec_inst.rate != -1)
-    config.bit_rate = codec_inst.rate;
-  return config;
-}
-
-template <typename T>
 bool AudioEncoderIsacT<T>::Config::IsOk() const {
   if (max_bit_rate < 32000 && max_bit_rate != -1)
     return false;
@@ -67,12 +50,6 @@
 }
 
 template <typename T>
-AudioEncoderIsacT<T>::AudioEncoderIsacT(
-    const CodecInst& codec_inst,
-    const rtc::scoped_refptr<LockedIsacBandwidthInfo>& bwinfo)
-    : AudioEncoderIsacT(CreateIsacConfig<T>(codec_inst, bwinfo)) {}
-
-template <typename T>
 AudioEncoderIsacT<T>::~AudioEncoderIsacT() {
   RTC_CHECK_EQ(0, T::Free(isac_state_));
 }
diff --git a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
index e565e85..7355330 100644
--- a/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
+++ b/modules/audio_coding/codecs/isac/fix/source/pitch_filter.c
@@ -9,7 +9,6 @@
  */
 
 #include "modules/audio_coding/codecs/isac/fix/source/pitch_estimator.h"
-
 #include "common_audio/signal_processing/include/signal_processing_library.h"
 #include "modules/audio_coding/codecs/isac/fix/source/settings.h"
 #include "modules/audio_coding/codecs/isac/fix/source/structs.h"
@@ -55,7 +54,8 @@
   const int16_t Gain = 21299;     // 1.3 in Q14
   int16_t oldLagQ7;
   int16_t oldGainQ12, lagdeltaQ7, curLagQ7, gaindeltaQ12, curGainQ12;
-  size_t indW32 = 0, frcQQ = 0;
+  size_t frcQQ = 0;
+  int32_t indW32 = 0;
   const int16_t* fracoeffQQ = NULL;
 
   // Assumptions in ARM assembly for WebRtcIsacfix_PitchFilterCoreARM().
diff --git a/modules/audio_coding/codecs/isac/locked_bandwidth_info.h b/modules/audio_coding/codecs/isac/locked_bandwidth_info.h
index 37074f8..0b1bc7d 100644
--- a/modules/audio_coding/codecs/isac/locked_bandwidth_info.h
+++ b/modules/audio_coding/codecs/isac/locked_bandwidth_info.h
@@ -12,8 +12,8 @@
 #define MODULES_AUDIO_CODING_CODECS_ISAC_LOCKED_BANDWIDTH_INFO_H_
 
 #include "modules/audio_coding/codecs/isac/bandwidth_info.h"
-#include "rtc_base/atomicops.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/atomic_ops.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc b/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
index 3ec28cc..6d9b013 100644
--- a/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
+++ b/modules/audio_coding/codecs/isac/main/source/isac_unittest.cc
@@ -11,7 +11,7 @@
 
 #include "modules/audio_coding/codecs/isac/main/include/isac.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 struct WebRtcISACStruct;
 
diff --git a/modules/audio_coding/codecs/isac/unittest.cc b/modules/audio_coding/codecs/isac/unittest.cc
index 5855d56..076510b 100644
--- a/modules/audio_coding/codecs/isac/unittest.cc
+++ b/modules/audio_coding/codecs/isac/unittest.cc
@@ -19,7 +19,7 @@
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -252,6 +252,6 @@
   return cases;
 }
 
-INSTANTIATE_TEST_CASE_P(, IsacCommonTest, testing::ValuesIn(TestCases()));
+INSTANTIATE_TEST_SUITE_P(, IsacCommonTest, testing::ValuesIn(TestCases()));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc b/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
index 9079bcd..2ca1d4c 100644
--- a/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
+++ b/modules/audio_coding/codecs/legacy_encoded_audio_frame_unittest.cc
@@ -10,12 +10,28 @@
 
 #include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
 
-#include "modules/audio_coding/acm2/rent_a_codec.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 
+enum class NetEqDecoder {
+  kDecoderPCMu,
+  kDecoderPCMa,
+  kDecoderPCMu_2ch,
+  kDecoderPCMa_2ch,
+  kDecoderPCM16B,
+  kDecoderPCM16Bwb,
+  kDecoderPCM16Bswb32kHz,
+  kDecoderPCM16Bswb48kHz,
+  kDecoderPCM16B_2ch,
+  kDecoderPCM16Bwb_2ch,
+  kDecoderPCM16Bswb32kHz_2ch,
+  kDecoderPCM16Bswb48kHz_2ch,
+  kDecoderPCM16B_5ch,
+  kDecoderG722,
+};
+
 class SplitBySamplesTest : public ::testing::TestWithParam<NetEqDecoder> {
  protected:
   virtual void SetUp() {
@@ -144,7 +160,7 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
     LegacyEncodedAudioFrame,
     SplitBySamplesTest,
     ::testing::Values(NetEqDecoder::kDecoderPCMu,
diff --git a/modules/audio_coding/codecs/opus/audio_decoder_opus.cc b/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
index 357cb1a..b6eada9 100644
--- a/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
+++ b/modules/audio_coding/codecs/opus/audio_decoder_opus.cc
@@ -71,8 +71,10 @@
 
 AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels)
     : channels_(num_channels) {
-  RTC_DCHECK(num_channels == 1 || num_channels == 2);
-  WebRtcOpus_DecoderCreate(&dec_state_, channels_);
+  RTC_DCHECK(num_channels == 1 || num_channels == 2 || num_channels == 4 ||
+             num_channels == 6 || num_channels == 8);
+  const int error = WebRtcOpus_DecoderCreate(&dec_state_, channels_);
+  RTC_DCHECK(error == 0);
   WebRtcOpus_DecoderInit(dec_state_);
 }
 
diff --git a/modules/audio_coding/codecs/opus/audio_decoder_opus.h b/modules/audio_coding/codecs/opus/audio_decoder_opus.h
index 8043425..d8cc5c1 100644
--- a/modules/audio_coding/codecs/opus/audio_decoder_opus.h
+++ b/modules/audio_coding/codecs/opus/audio_decoder_opus.h
@@ -18,7 +18,7 @@
 #include "api/audio_codecs/audio_decoder.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
index 1a88acf..69aa8b9 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -12,11 +12,11 @@
 
 #include <algorithm>
 #include <iterator>
+#include <string>
 #include <utility>
 
 #include "absl/memory/memory.h"
 #include "absl/strings/match.h"
-#include "common_types.h"
 #include "modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
 #include "modules/audio_coding/audio_network_adaptor/controller_manager.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
@@ -26,9 +26,8 @@
 #include "rtc_base/numerics/exp_filter.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "rtc_base/numerics/safe_minmax.h"
-#include "rtc_base/protobuf_utils.h"
 #include "rtc_base/string_to_number.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace webrtc {
@@ -334,19 +333,6 @@
   return absl::nullopt;
 }
 
-AudioEncoderOpusConfig AudioEncoderOpusImpl::CreateConfig(
-    const CodecInst& codec_inst) {
-  AudioEncoderOpusConfig config;
-  config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
-  config.num_channels = codec_inst.channels;
-  config.bitrate_bps = codec_inst.rate;
-  config.application = config.num_channels == 1
-                           ? AudioEncoderOpusConfig::ApplicationMode::kVoip
-                           : AudioEncoderOpusConfig::ApplicationMode::kAudio;
-  config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
-  return config;
-}
-
 absl::optional<AudioEncoderOpusConfig> AudioEncoderOpusImpl::SdpToConfig(
     const SdpAudioFormat& format) {
   if (!absl::EqualsIgnoreCase(format.name, "opus") ||
@@ -457,7 +443,7 @@
     : AudioEncoderOpusImpl(
           config,
           payload_type,
-          [this](const ProtoString& config_string, RtcEventLog* event_log) {
+          [this](const std::string& config_string, RtcEventLog* event_log) {
             return DefaultAudioNetworkAdaptorCreator(config_string, event_log);
           },
           // We choose 5sec as initial time constant due to empirical data.
@@ -494,9 +480,6 @@
   SetProjectedPacketLossRate(packet_loss_rate_);
 }
 
-AudioEncoderOpusImpl::AudioEncoderOpusImpl(const CodecInst& codec_inst)
-    : AudioEncoderOpusImpl(CreateConfig(codec_inst), codec_inst.pltype) {}
-
 AudioEncoderOpusImpl::AudioEncoderOpusImpl(int payload_type,
                                            const SdpAudioFormat& format)
     : AudioEncoderOpusImpl(*SdpToConfig(format), payload_type) {}
@@ -784,7 +767,9 @@
                               AudioEncoderOpusConfig::ApplicationMode::kVoip
                           ? 0
                           : 1));
-  RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, GetBitrateBps(config)));
+  const int bitrate = GetBitrateBps(config);
+  RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
+  RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
   if (config.fec_enabled) {
     RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
   } else {
@@ -847,17 +832,23 @@
 }
 
 void AudioEncoderOpusImpl::SetTargetBitrate(int bits_per_second) {
-  config_.bitrate_bps = rtc::SafeClamp<int>(
+  const int new_bitrate = rtc::SafeClamp<int>(
       bits_per_second, AudioEncoderOpusConfig::kMinBitrateBps,
       AudioEncoderOpusConfig::kMaxBitrateBps);
-  RTC_DCHECK(config_.IsOk());
-  RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, GetBitrateBps(config_)));
+  if (config_.bitrate_bps && *config_.bitrate_bps != new_bitrate) {
+    config_.bitrate_bps = new_bitrate;
+    RTC_DCHECK(config_.IsOk());
+    const int bitrate = GetBitrateBps(config_);
+    RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, bitrate));
+    RTC_LOG(LS_INFO) << "Set Opus bitrate to " << bitrate << " bps.";
+    bitrate_changed_ = true;
+  }
+
   const auto new_complexity = GetNewComplexity(config_);
   if (new_complexity && complexity_ != *new_complexity) {
     complexity_ = *new_complexity;
     RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
   }
-  bitrate_changed_ = true;
 }
 
 void AudioEncoderOpusImpl::ApplyAudioNetworkAdaptor() {
@@ -879,7 +870,7 @@
 
 std::unique_ptr<AudioNetworkAdaptor>
 AudioEncoderOpusImpl::DefaultAudioNetworkAdaptorCreator(
-    const ProtoString& config_string,
+    const std::string& config_string,
     RtcEventLog* event_log) const {
   AudioNetworkAdaptorImpl::Config config;
   config.event_log = event_log;
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus.h b/modules/audio_coding/codecs/opus/audio_encoder_opus.h
index 150423f..dc14620 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus.h
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus.h
@@ -23,15 +23,12 @@
 #include "common_audio/smoothing_filter.h"
 #include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/protobuf_utils.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
 class RtcEventLog;
 
-struct CodecInst;
-
 class AudioEncoderOpusImpl final : public AudioEncoder {
  public:
   class NewPacketLossRateOptimizer {
@@ -43,9 +40,9 @@
     float OptimizePacketLossRate(float packet_loss_rate) const;
 
     // Getters for testing.
-    float min_packet_loss_rate() const { return min_packet_loss_rate_; };
-    float max_packet_loss_rate() const { return max_packet_loss_rate_; };
-    float slope() const { return slope_; };
+    float min_packet_loss_rate() const { return min_packet_loss_rate_; }
+    float max_packet_loss_rate() const { return max_packet_loss_rate_; }
+    float slope() const { return slope_; }
 
    private:
     const float min_packet_loss_rate_;
@@ -54,8 +51,6 @@
     RTC_DISALLOW_COPY_AND_ASSIGN(NewPacketLossRateOptimizer);
   };
 
-  static AudioEncoderOpusConfig CreateConfig(const CodecInst& codec_inst);
-
   // Returns empty if the current bitrate falls within the hysteresis window,
   // defined by complexity_threshold_bps +/- complexity_threshold_window_bps.
   // Otherwise, returns the current complexity depending on whether the
@@ -83,7 +78,6 @@
       const AudioNetworkAdaptorCreator& audio_network_adaptor_creator,
       std::unique_ptr<SmoothingFilter> bitrate_smoother);
 
-  explicit AudioEncoderOpusImpl(const CodecInst& codec_inst);
   AudioEncoderOpusImpl(int payload_type, const SdpAudioFormat& format);
   ~AudioEncoderOpusImpl() override;
 
@@ -176,7 +170,7 @@
 
   void ApplyAudioNetworkAdaptor();
   std::unique_ptr<AudioNetworkAdaptor> DefaultAudioNetworkAdaptorCreator(
-      const ProtoString& config_string,
+      const std::string& config_string,
       RtcEventLog* event_log) const;
 
   void MaybeUpdateUplinkBandwidth();
diff --git a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
index d5c2c84..b3b531f 100644
--- a/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/audio_encoder_opus_unittest.cc
@@ -15,17 +15,16 @@
 #include "absl/memory/memory.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "common_audio/mocks/mock_smoothing_filter.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h"
 #include "modules/audio_coding/codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/fakeclock.h"
+#include "rtc_base/fake_clock.h"
 #include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 using ::testing::NiceMock;
@@ -33,21 +32,11 @@
 
 namespace {
 
-const CodecInst kDefaultOpusSettings = {105, "opus", 48000, 960, 1, 32000};
+constexpr int kDefaultOpusPayloadType = 105;
+constexpr int kDefaultOpusRate = 32000;
+constexpr int kDefaultOpusPacSize = 960;
 constexpr int64_t kInitialTimeUs = 12345678;
 
-AudioEncoderOpusConfig CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderOpusConfig config;
-  config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
-  config.num_channels = codec_inst.channels;
-  config.bitrate_bps = codec_inst.rate;
-  config.application = config.num_channels == 1
-                           ? AudioEncoderOpusConfig::ApplicationMode::kVoip
-                           : AudioEncoderOpusConfig::ApplicationMode::kAudio;
-  config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
-  return config;
-}
-
 AudioEncoderOpusConfig CreateConfigWithParameters(
     const SdpAudioFormat::Parameters& params) {
   const SdpAudioFormat format("opus", 48000, 2, params);
@@ -79,16 +68,23 @@
         return adaptor;
       };
 
-  CodecInst codec_inst = kDefaultOpusSettings;
-  codec_inst.channels = num_channels;
-  states->config = CreateConfig(codec_inst);
+  AudioEncoderOpusConfig config;
+  config.frame_size_ms = rtc::CheckedDivExact(kDefaultOpusPacSize, 48);
+  config.num_channels = num_channels;
+  config.bitrate_bps = kDefaultOpusRate;
+  config.application = num_channels == 1
+                           ? AudioEncoderOpusConfig::ApplicationMode::kVoip
+                           : AudioEncoderOpusConfig::ApplicationMode::kAudio;
+  config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
+  states->config = config;
+
   std::unique_ptr<MockSmoothingFilter> bitrate_smoother(
       new MockSmoothingFilter());
   states->mock_bitrate_smoother = bitrate_smoother.get();
 
-  states->encoder.reset(new AudioEncoderOpusImpl(
-      states->config, codec_inst.pltype, std::move(creator),
-      std::move(bitrate_smoother)));
+  states->encoder.reset(
+      new AudioEncoderOpusImpl(states->config, kDefaultOpusPayloadType, creator,
+                               std::move(bitrate_smoother)));
   return states;
 }
 
@@ -436,12 +432,12 @@
 
   auto states = CreateCodec(2);
 
-  states->encoder->OnReceivedUplinkBandwidth(kDefaultOpusSettings.rate * 2,
+  states->encoder->OnReceivedUplinkBandwidth(kDefaultOpusRate * 2,
                                              absl::nullopt);
 
   // Since |OnReceivedOverhead| has not been called, the codec bitrate should
   // not change.
-  EXPECT_EQ(kDefaultOpusSettings.rate, states->encoder->GetTargetBitrate());
+  EXPECT_EQ(kDefaultOpusRate, states->encoder->GetTargetBitrate());
 }
 
 TEST(AudioEncoderOpusTest, OverheadRemovedFromTargetAudioBitrate) {
@@ -456,7 +452,7 @@
   constexpr int kTargetBitrateBps = 40000;
   states->encoder->OnReceivedUplinkBandwidth(kTargetBitrateBps, absl::nullopt);
 
-  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusSettings.pacsize);
+  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusPacSize);
   EXPECT_EQ(kTargetBitrateBps -
                 8 * static_cast<int>(kOverheadBytesPerPacket) * packet_rate,
             states->encoder->GetTargetBitrate());
@@ -474,7 +470,7 @@
   constexpr size_t kOverheadBytesPerPacket = 64;
   states->encoder->OnReceivedOverhead(kOverheadBytesPerPacket);
 
-  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusSettings.pacsize);
+  int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusPacSize);
 
   // Set a target rate that is smaller than |kMinBitrateBps| when overhead is
   // subtracted. The eventual codec rate should be bounded by |kMinBitrateBps|.
diff --git a/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc b/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
index 7e6b626..2c8edf0 100644
--- a/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_bandwidth_unittest.cc
@@ -16,7 +16,7 @@
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace {
diff --git a/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc b/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
index 4c9174d..84bad33 100644
--- a/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_complexity_unittest.cc
@@ -11,9 +11,9 @@
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "rtc_base/format_macros.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 #include "test/testsupport/perf_test.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/codecs/opus/opus_fec_test.cc b/modules/audio_coding/codecs/opus/opus_fec_test.cc
index 4fab8a7..7552c20 100644
--- a/modules/audio_coding/codecs/opus/opus_fec_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_fec_test.cc
@@ -13,7 +13,7 @@
 #include "modules/audio_coding/codecs/opus/opus_interface.h"
 #include "rtc_base/format_macros.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using std::string;
 using std::tuple;
@@ -238,6 +238,6 @@
                     string("pcm"))};
 
 // 64 kbps, stereo
-INSTANTIATE_TEST_CASE_P(AllTest, OpusFecTest, ::testing::ValuesIn(param_set));
+INSTANTIATE_TEST_SUITE_P(AllTest, OpusFecTest, ::testing::ValuesIn(param_set));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/opus/opus_inst.h b/modules/audio_coding/codecs/opus/opus_inst.h
index 2473a5c..0b31181 100644
--- a/modules/audio_coding/codecs/opus/opus_inst.h
+++ b/modules/audio_coding/codecs/opus/opus_inst.h
@@ -17,16 +17,23 @@
 
 RTC_PUSH_IGNORING_WUNDEF()
 #include "opus.h"
+#include "opus_multistream.h"
 RTC_POP_IGNORING_WUNDEF()
 
 struct WebRtcOpusEncInst {
-  OpusEncoder* encoder;
+  union {
+    OpusEncoder* encoder;
+    OpusMSEncoder* multistream_encoder;
+  } encoder;
   size_t channels;
   int in_dtx_mode;
 };
 
 struct WebRtcOpusDecInst {
-  OpusDecoder* decoder;
+  union {
+    OpusDecoder* decoder;
+    OpusMSDecoder* multistream_decoder;
+  } decoder;
   int prev_decoded_samples;
   size_t channels;
   int in_dtx_mode;
diff --git a/modules/audio_coding/codecs/opus/opus_interface.c b/modules/audio_coding/codecs/opus/opus_interface.c
index d219098..3369f8e 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.c
+++ b/modules/audio_coding/codecs/opus/opus_interface.c
@@ -37,6 +37,40 @@
   kWebRtcOpusDefaultFrameSize = 960,
 };
 
+int16_t GetSurroundParameters(int channels,
+                              int *streams,
+                              int *coupled_streams,
+                              unsigned char *mapping) {
+  int opus_error;
+  int ret = 0;
+  // Use 'surround encoder create' to get values for 'coupled_streams',
+  // 'streams' and 'mapping'.
+  OpusMSEncoder* ms_encoder_ptr = opus_multistream_surround_encoder_create(
+      48000,
+      channels,
+      /* mapping family */ channels <= 2 ? 0 : 1,
+      streams,
+      coupled_streams,
+      mapping,
+      OPUS_APPLICATION_VOIP, // Application type shouldn't affect
+                             // streams/mapping values.
+      &opus_error);
+
+  // This shouldn't fail; if it fails,
+  // signal an error and return invalid values.
+  if (opus_error != OPUS_OK || ms_encoder_ptr == NULL) {
+    ret = -1;
+    *streams = -1;
+    *coupled_streams = -1;
+  }
+
+  // We don't need the encoder.
+  if (ms_encoder_ptr != NULL) {
+    opus_multistream_encoder_destroy(ms_encoder_ptr);
+  }
+  return ret;
+}
+
 int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
                                  size_t channels,
                                  int32_t application) {
@@ -55,13 +89,34 @@
       return -1;
   }
 
-  OpusEncInst* state = calloc(1, sizeof(OpusEncInst));
+  OpusEncInst* state = (OpusEncInst*)calloc(1, sizeof(OpusEncInst));
   RTC_DCHECK(state);
 
   int error;
-  state->encoder = opus_encoder_create(48000, (int)channels, opus_app,
-                                       &error);
-  if (error != OPUS_OK || !state->encoder) {
+  if (channels <= 2) {
+    state->encoder.encoder = opus_encoder_create(48000, (int)channels, opus_app,
+                                         &error);
+
+  } else {
+    unsigned char mapping[255];
+    memset(mapping, 0, 255);
+    int streams = -1;
+    int coupled_streams = -1;
+
+    state->encoder.multistream_encoder =
+        opus_multistream_surround_encoder_create(
+        48000,
+        channels,
+        /* mapping family */ 1,
+        &streams,
+        &coupled_streams,
+        mapping,
+        opus_app,
+        &error);
+  }
+
+  if (error != OPUS_OK || (!state->encoder.encoder &&
+                           !state->encoder.multistream_encoder)) {
     WebRtcOpus_EncoderFree(state);
     return -1;
   }
@@ -75,7 +130,11 @@
 
 int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
   if (inst) {
-    opus_encoder_destroy(inst->encoder);
+    if (inst->channels <= 2) {
+      opus_encoder_destroy(inst->encoder.encoder);
+    } else {
+      opus_multistream_encoder_destroy(inst->encoder.multistream_encoder);
+    }
     free(inst);
     return 0;
   } else {
@@ -94,11 +153,19 @@
     return -1;
   }
 
-  res = opus_encode(inst->encoder,
-                    (const opus_int16*)audio_in,
-                    (int)samples,
-                    encoded,
-                    (opus_int32)length_encoded_buffer);
+  if (inst->channels <= 2) {
+    res = opus_encode(inst->encoder.encoder,
+                      (const opus_int16*)audio_in,
+                      (int)samples,
+                      encoded,
+                      (opus_int32)length_encoded_buffer);
+  } else {
+    res = opus_multistream_encode(inst->encoder.multistream_encoder,
+                                  (const opus_int16*)audio_in,
+                                  (int)samples,
+                                  encoded,
+                                  (opus_int32)length_encoded_buffer);
+  }
 
   if (res <= 0) {
     return -1;
@@ -120,9 +187,15 @@
   return res;
 }
 
+#define ENCODER_CTL(inst, vargs) (                                      \
+    inst->channels <= 2 ?                                               \
+    opus_encoder_ctl(inst->encoder.encoder, vargs)                      \
+    : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs))
+
+
 int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
+    return ENCODER_CTL(inst, OPUS_SET_BITRATE(rate));
   } else {
     return -1;
   }
@@ -130,8 +203,7 @@
 
 int16_t WebRtcOpus_SetPacketLossRate(OpusEncInst* inst, int32_t loss_rate) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder,
-                            OPUS_SET_PACKET_LOSS_PERC(loss_rate));
+    return ENCODER_CTL(inst, OPUS_SET_PACKET_LOSS_PERC(loss_rate));
   } else {
     return -1;
   }
@@ -154,13 +226,52 @@
   } else {
     set_bandwidth = OPUS_BANDWIDTH_FULLBAND;
   }
-  return opus_encoder_ctl(inst->encoder,
-                          OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
+  return ENCODER_CTL(inst, OPUS_SET_MAX_BANDWIDTH(set_bandwidth));
+}
+
+int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
+                                      int32_t* result_hz) {
+  if (inst->channels <= 2) {
+    if (opus_encoder_ctl(
+            inst->encoder.encoder,
+            OPUS_GET_MAX_BANDWIDTH(result_hz)) == OPUS_OK) {
+      return 0;
+    }
+    return -1;
+  }
+
+  opus_int32 max_bandwidth;
+  int s;
+  int ret;
+
+  max_bandwidth = 0;
+  ret = OPUS_OK;
+  s = 0;
+  while (ret == OPUS_OK) {
+    OpusEncoder *enc;
+    opus_int32 bandwidth;
+
+    ret = ENCODER_CTL(inst, OPUS_MULTISTREAM_GET_ENCODER_STATE(s, &enc));
+    if (ret == OPUS_BAD_ARG)
+      break;
+    if (ret != OPUS_OK)
+      return -1;
+    if (opus_encoder_ctl(enc, OPUS_GET_MAX_BANDWIDTH(&bandwidth)) != OPUS_OK)
+      return -1;
+
+    if (max_bandwidth != 0 && max_bandwidth != bandwidth)
+      return -1;
+
+    max_bandwidth = bandwidth;
+    s++;
+  }
+  *result_hz = max_bandwidth;
+  return 0;
 }
 
 int16_t WebRtcOpus_EnableFec(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(1));
+    return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(1));
   } else {
     return -1;
   }
@@ -168,7 +279,7 @@
 
 int16_t WebRtcOpus_DisableFec(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_INBAND_FEC(0));
+    return ENCODER_CTL(inst, OPUS_SET_INBAND_FEC(0));
   } else {
     return -1;
   }
@@ -184,21 +295,21 @@
   // last long during a pure silence, if the signal type is not forced.
   // TODO(minyue): Remove the signal type forcing when Opus DTX works properly
   // without it.
-  int ret = opus_encoder_ctl(inst->encoder,
-                             OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
+  int ret = ENCODER_CTL(inst,
+                        OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
   if (ret != OPUS_OK)
     return ret;
 
-  return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(1));
+  return ENCODER_CTL(inst, OPUS_SET_DTX(1));
 }
 
 int16_t WebRtcOpus_DisableDtx(OpusEncInst* inst) {
   if (inst) {
-    int ret = opus_encoder_ctl(inst->encoder,
-                               OPUS_SET_SIGNAL(OPUS_AUTO));
+    int ret = ENCODER_CTL(inst,
+                          OPUS_SET_SIGNAL(OPUS_AUTO));
     if (ret != OPUS_OK)
       return ret;
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_DTX(0));
+    return ENCODER_CTL(inst, OPUS_SET_DTX(0));
   } else {
     return -1;
   }
@@ -206,7 +317,7 @@
 
 int16_t WebRtcOpus_EnableCbr(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(0));
+    return ENCODER_CTL(inst, OPUS_SET_VBR(0));
   } else {
     return -1;
   }
@@ -214,7 +325,7 @@
 
 int16_t WebRtcOpus_DisableCbr(OpusEncInst* inst) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_VBR(1));
+    return ENCODER_CTL(inst, OPUS_SET_VBR(1));
   } else {
     return -1;
   }
@@ -222,7 +333,8 @@
 
 int16_t WebRtcOpus_SetComplexity(OpusEncInst* inst, int32_t complexity) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_COMPLEXITY(complexity));
+    return ENCODER_CTL(inst,
+                       OPUS_SET_COMPLEXITY(complexity));
   } else {
     return -1;
   }
@@ -233,7 +345,8 @@
     return -1;
   }
   int32_t bandwidth;
-  if (opus_encoder_ctl(inst->encoder, OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
+  if (ENCODER_CTL(inst,
+                  OPUS_GET_BANDWIDTH(&bandwidth)) == 0) {
     return bandwidth;
   } else {
     return -1;
@@ -243,7 +356,8 @@
 
 int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth) {
   if (inst) {
-    return opus_encoder_ctl(inst->encoder, OPUS_SET_BANDWIDTH(bandwidth));
+    return ENCODER_CTL(inst,
+                       OPUS_SET_BANDWIDTH(bandwidth));
   } else {
     return -1;
   }
@@ -253,11 +367,11 @@
   if (!inst)
     return -1;
   if (num_channels == 0) {
-    return opus_encoder_ctl(inst->encoder,
+    return ENCODER_CTL(inst,
                             OPUS_SET_FORCE_CHANNELS(OPUS_AUTO));
   } else if (num_channels == 1 || num_channels == 2) {
-    return opus_encoder_ctl(inst->encoder,
-                            OPUS_SET_FORCE_CHANNELS(num_channels));
+    return ENCODER_CTL(inst,
+                       OPUS_SET_FORCE_CHANNELS(num_channels));
   } else {
     return -1;
   }
@@ -268,16 +382,37 @@
   OpusDecInst* state;
 
   if (inst != NULL) {
-    /* Create Opus decoder state. */
+    // Create Opus decoder state.
     state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
     if (state == NULL) {
       return -1;
     }
 
-    /* Create new memory, always at 48000 Hz. */
-    state->decoder = opus_decoder_create(48000, (int)channels, &error);
-    if (error == OPUS_OK && state->decoder != NULL) {
-      /* Creation of memory all ok. */
+    if (channels <= 2) {
+      state->decoder.decoder = opus_decoder_create(48000,
+                                                   (int)channels, &error);
+    } else {
+      unsigned char mapping[255];
+      memset(mapping, 0, 255);
+      int streams = -1;
+      int coupled_streams = -1;
+      if (GetSurroundParameters(channels, &streams,
+                                &coupled_streams, mapping) != 0) {
+        free(state);
+        return -1;
+      }
+
+      // Create new memory, always at 48000 Hz.
+      state->decoder.multistream_decoder = opus_multistream_decoder_create(
+          48000, (int)channels,
+          /* streams = */ streams,
+          /* coupled streams = */ coupled_streams,
+          mapping,
+          &error);
+    }
+    if (error == OPUS_OK && (state->decoder.decoder ||
+                             state->decoder.multistream_decoder)) {
+      // Creation of memory all ok.
       state->channels = channels;
       state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
       state->in_dtx_mode = 0;
@@ -285,9 +420,12 @@
       return 0;
     }
 
-    /* If memory allocation was unsuccessful, free the entire state. */
-    if (state->decoder) {
-      opus_decoder_destroy(state->decoder);
+    // If memory allocation was unsuccessful, free the entire state.
+    if (state->decoder.decoder) {
+      opus_decoder_destroy(state->decoder.decoder);
+
+    } else if (state->decoder.multistream_decoder) {
+      opus_multistream_decoder_destroy(state->decoder.multistream_decoder);
     }
     free(state);
   }
@@ -296,7 +434,11 @@
 
 int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
   if (inst) {
-    opus_decoder_destroy(inst->decoder);
+    if (inst->channels <= 2) {
+      opus_decoder_destroy(inst->decoder.decoder);
+    } else if (inst->channels > 2) {
+      opus_multistream_decoder_destroy(inst->decoder.multistream_decoder);
+    }
     free(inst);
     return 0;
   } else {
@@ -309,7 +451,12 @@
 }
 
 void WebRtcOpus_DecoderInit(OpusDecInst* inst) {
-  opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
+  if (inst->channels <= 2) {
+    opus_decoder_ctl(inst->decoder.decoder, OPUS_RESET_STATE);
+  } else {
+    opus_multistream_decoder_ctl(inst->decoder.multistream_decoder,
+                                 OPUS_RESET_STATE);
+  }
   inst->in_dtx_mode = 0;
 }
 
@@ -324,6 +471,10 @@
     // fact a 1-byte TOC with a 1-byte payload. That will be erroneously
     // interpreted as comfort noise output, but such a payload is probably
     // faulty anyway.
+
+    // TODO(webrtc:10218): This is wrong for multistream opus. Then are several
+    // single-stream packets glued together with some packet size bytes in
+    // between. See https://tools.ietf.org/html/rfc6716#appendix-B
     inst->in_dtx_mode = 1;
     return 2;  // Comfort noise.
   } else {
@@ -338,8 +489,15 @@
 static int DecodeNative(OpusDecInst* inst, const uint8_t* encoded,
                         size_t encoded_bytes, int frame_size,
                         int16_t* decoded, int16_t* audio_type, int decode_fec) {
-  int res = opus_decode(inst->decoder, encoded, (opus_int32)encoded_bytes,
-                        (opus_int16*)decoded, frame_size, decode_fec);
+  int res = -1;
+  if (inst->channels <= 2) {
+    res = opus_decode(inst->decoder.decoder, encoded, (opus_int32)encoded_bytes,
+                      (opus_int16*)decoded, frame_size, decode_fec);
+  } else {
+    res = opus_multistream_decode(
+        inst->decoder.multistream_decoder, encoded, (opus_int32)encoded_bytes,
+        (opus_int16*)decoded, frame_size, decode_fec);
+  }
 
   if (res <= 0)
     return -1;
diff --git a/modules/audio_coding/codecs/opus/opus_interface.h b/modules/audio_coding/codecs/opus/opus_interface.h
index ddb4ff9..0e97734 100644
--- a/modules/audio_coding/codecs/opus/opus_interface.h
+++ b/modules/audio_coding/codecs/opus/opus_interface.h
@@ -125,6 +125,22 @@
  */
 int16_t WebRtcOpus_SetMaxPlaybackRate(OpusEncInst* inst, int32_t frequency_hz);
 
+/****************************************************************************
+ * WebRtcOpus_GetMaxPlaybackRate(...)
+ *
+ * Queries the maximum playback rate for encoding. If different single-stream
+ * encoders have different maximum playback rates, this function fails.
+ *
+ * Input:
+ *      - inst               : Encoder context.
+ * Output:
+ *      - result_hz          : The maximum playback rate in Hz.
+ * Return value              :  0 - Success
+ *                             -1 - Error
+ */
+int16_t WebRtcOpus_GetMaxPlaybackRate(OpusEncInst* const inst,
+                                      int32_t* result_hz);
+
 /* TODO(minyue): Check whether an API to check the FEC and the packet loss rate
  * is needed. It might not be very useful since there are not many use cases and
  * the caller can always maintain the states. */
diff --git a/modules/audio_coding/codecs/opus/opus_speed_test.cc b/modules/audio_coding/codecs/opus/opus_speed_test.cc
index 03b59ed..1a629a8 100644
--- a/modules/audio_coding/codecs/opus/opus_speed_test.cc
+++ b/modules/audio_coding/codecs/opus/opus_speed_test.cc
@@ -96,17 +96,17 @@
     EncodeDecode(kDurationSec);                                        \
   }
 
-ADD_TEST(10);
-ADD_TEST(9);
-ADD_TEST(8);
-ADD_TEST(7);
-ADD_TEST(6);
-ADD_TEST(5);
-ADD_TEST(4);
-ADD_TEST(3);
-ADD_TEST(2);
-ADD_TEST(1);
-ADD_TEST(0);
+ADD_TEST(10)
+ADD_TEST(9)
+ADD_TEST(8)
+ADD_TEST(7)
+ADD_TEST(6)
+ADD_TEST(5)
+ADD_TEST(4)
+ADD_TEST(3)
+ADD_TEST(2)
+ADD_TEST(1)
+ADD_TEST(0)
 
 #define ADD_BANDWIDTH_TEST(bandwidth)                                \
   TEST_P(OpusSpeedTest, OpusSetBandwidthTest##bandwidth) {           \
@@ -116,11 +116,11 @@
     EncodeDecode(kDurationSec);                                      \
   }
 
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_NARROWBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_MEDIUMBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_WIDEBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_SUPERWIDEBAND);
-ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_FULLBAND);
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_NARROWBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_MEDIUMBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_WIDEBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_SUPERWIDEBAND)
+ADD_BANDWIDTH_TEST(OPUS_BANDWIDTH_FULLBAND)
 
 // List all test cases: (channel, bit rat, filename, extension).
 const coding_param param_set[] = {
@@ -140,6 +140,8 @@
                     string("pcm"),
                     true)};
 
-INSTANTIATE_TEST_CASE_P(AllTest, OpusSpeedTest, ::testing::ValuesIn(param_set));
+INSTANTIATE_TEST_SUITE_P(AllTest,
+                         OpusSpeedTest,
+                         ::testing::ValuesIn(param_set));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/opus/opus_unittest.cc b/modules/audio_coding/codecs/opus/opus_unittest.cc
index 034f8cd..56dfd6a 100644
--- a/modules/audio_coding/codecs/opus/opus_unittest.cc
+++ b/modules/audio_coding/codecs/opus/opus_unittest.cc
@@ -17,7 +17,7 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -27,7 +27,7 @@
 using ::testing::Combine;
 
 // Maximum number of bytes in output bitstream.
-const size_t kMaxBytes = 1000;
+const size_t kMaxBytes = 2000;
 // Sample rate of Opus.
 const size_t kOpusRateKhz = 48;
 // Number of samples-per-channel in a 20 ms frame, sampled at 48 kHz.
@@ -86,10 +86,14 @@
 void OpusTest::PrepareSpeechData(size_t channel,
                                  int block_length_ms,
                                  int loop_length_ms) {
+  std::map<int, std::string> channel_to_basename = {
+      {1, "audio_coding/testfile32kHz"},
+      {2, "audio_coding/teststereo32kHz"},
+      {4, "audio_coding/speech_4_channels_48k_one_second"}};
+  std::map<int, std::string> channel_to_suffix = {
+      {1, "pcm"}, {2, "pcm"}, {4, "wav"}};
   const std::string file_name = webrtc::test::ResourcePath(
-      (channel == 1) ? "audio_coding/testfile32kHz"
-                     : "audio_coding/teststereo32kHz",
-      "pcm");
+      channel_to_basename[channel], channel_to_suffix[channel]);
   if (loop_length_ms < block_length_ms) {
     loop_length_ms = block_length_ms;
   }
@@ -103,7 +107,7 @@
                                   int32_t set) {
   opus_int32 bandwidth;
   EXPECT_EQ(0, WebRtcOpus_SetMaxPlaybackRate(opus_encoder_, set));
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_MAX_BANDWIDTH(&bandwidth));
+  EXPECT_EQ(0, WebRtcOpus_GetMaxPlaybackRate(opus_encoder_, &bandwidth));
   EXPECT_EQ(expect, bandwidth);
 }
 
@@ -354,13 +358,13 @@
   // Test to see that an invalid pointer is caught.
   EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(NULL, 1, 0));
   // Invalid channel number.
-  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 3, 0));
+  EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 257, 0));
   // Invalid applciation mode.
   EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 2));
 
   EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
   // Invalid channel number.
-  EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 3));
+  EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257));
 }
 
 // Test failing Free.
@@ -382,6 +386,11 @@
   EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
+#define ENCODER_CTL(inst, vargs)                       \
+  inst->channels <= 2                                  \
+      ? opus_encoder_ctl(inst->encoder.encoder, vargs) \
+      : opus_multistream_encoder_ctl(inst->encoder.multistream_encoder, vargs)
+
 TEST_P(OpusTest, OpusEncodeDecode) {
   PrepareSpeechData(channels_, 20, 20);
 
@@ -399,7 +408,7 @@
 
   // Check application mode.
   opus_int32 app;
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_APPLICATION(&app));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_APPLICATION(&app));
   EXPECT_EQ(application_ == 0 ? OPUS_APPLICATION_VOIP : OPUS_APPLICATION_AUDIO,
             app);
 
@@ -450,6 +459,11 @@
 }
 
 TEST_P(OpusTest, OpusSetBandwidth) {
+  if (channels_ > 2) {
+    // TODO(webrtc:10217): investigate why multi-stream Opus reports
+    // narrowband when it's configured with FULLBAND.
+    return;
+  }
   PrepareSpeechData(channels_, 20, 20);
 
   int16_t audio_type;
@@ -495,7 +509,7 @@
   ASSERT_EQ(0,
             WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, application_));
 
-  if (channels_ == 2) {
+  if (channels_ >= 2) {
     EXPECT_EQ(-1, WebRtcOpus_SetForceChannels(opus_encoder_, 3));
     EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 2));
     EXPECT_EQ(0, WebRtcOpus_SetForceChannels(opus_encoder_, 1));
@@ -568,17 +582,17 @@
   opus_int32 dtx;
 
   // DTX is off by default.
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
   EXPECT_EQ(0, dtx);
 
   // Test to enable DTX.
   EXPECT_EQ(0, WebRtcOpus_EnableDtx(opus_encoder_));
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
   EXPECT_EQ(1, dtx);
 
   // Test to disable DTX.
   EXPECT_EQ(0, WebRtcOpus_DisableDtx(opus_encoder_));
-  opus_encoder_ctl(opus_encoder_->encoder, OPUS_GET_DTX(&dtx));
+  ENCODER_CTL(opus_encoder_, OPUS_GET_DTX(&dtx));
   EXPECT_EQ(0, dtx);
 
   // Free memory.
@@ -592,6 +606,11 @@
 }
 
 TEST_P(OpusTest, OpusDtxOn) {
+  if (channels_ > 2) {
+    // TODO(webrtc:10218): adapt the test to the sizes and order of multi-stream
+    // DTX packets.
+    return;
+  }
   TestDtxEffect(true, 10);
   TestDtxEffect(true, 20);
   TestDtxEffect(true, 40);
@@ -723,6 +742,12 @@
 }
 
 TEST_P(OpusTest, OpusDecodeRepacketized) {
+  if (channels_ > 2) {
+    // As per the Opus documentation
+    // https://mf4.xiph.org/jenkins/view/opus/job/opus/ws/doc/html/group__opus__repacketizer.html#details,
+    // multiple streams are not supported.
+    return;
+  }
   constexpr size_t kPackets = 6;
 
   PrepareSpeechData(channels_, 20, 20 * kPackets);
@@ -785,8 +810,8 @@
   EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
 }
 
-INSTANTIATE_TEST_CASE_P(VariousMode,
-                        OpusTest,
-                        Combine(Values(1, 2), Values(0, 1)));
+INSTANTIATE_TEST_SUITE_P(VariousMode,
+                         OpusTest,
+                         Combine(Values(1, 2, 4), Values(0, 1)));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h b/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
index 9b478d8..0334104 100644
--- a/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
+++ b/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h
@@ -17,7 +17,7 @@
 
 #include "api/audio_codecs/audio_decoder.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
index 106ab16..9445b1e 100644
--- a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
+++ b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
@@ -10,7 +10,6 @@
 
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
 
-#include "common_types.h"
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "rtc_base/checks.h"
 
@@ -30,20 +29,6 @@
   return CodecType::kOther;
 }
 
-namespace {
-
-AudioEncoderPcm16B::Config CreateConfig(const CodecInst& codec_inst) {
-  AudioEncoderPcm16B::Config config;
-  config.num_channels = codec_inst.channels;
-  config.sample_rate_hz = codec_inst.plfreq;
-  config.frame_size_ms = rtc::CheckedDivExact(
-      codec_inst.pacsize, rtc::CheckedDivExact(config.sample_rate_hz, 1000));
-  config.payload_type = codec_inst.pltype;
-  return config;
-}
-
-}  // namespace
-
 bool AudioEncoderPcm16B::Config::IsOk() const {
   if ((sample_rate_hz != 8000) && (sample_rate_hz != 16000) &&
       (sample_rate_hz != 32000) && (sample_rate_hz != 48000))
@@ -51,7 +36,4 @@
   return AudioEncoderPcm::Config::IsOk();
 }
 
-AudioEncoderPcm16B::AudioEncoderPcm16B(const CodecInst& codec_inst)
-    : AudioEncoderPcm16B(CreateConfig(codec_inst)) {}
-
 }  // namespace webrtc
diff --git a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
index d6fd6e1..71c7572 100644
--- a/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
+++ b/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h
@@ -12,12 +12,10 @@
 #define MODULES_AUDIO_CODING_CODECS_PCM16B_AUDIO_ENCODER_PCM16B_H_
 
 #include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
-struct CodecInst;
-
 class AudioEncoderPcm16B final : public AudioEncoderPcm {
  public:
   struct Config : public AudioEncoderPcm::Config {
@@ -30,7 +28,6 @@
 
   explicit AudioEncoderPcm16B(const Config& config)
       : AudioEncoderPcm(config, config.sample_rate_hz) {}
-  explicit AudioEncoderPcm16B(const CodecInst& codec_inst);
 
  protected:
   size_t EncodeCall(const int16_t* audio,
diff --git a/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
index 5a68876..f05de19 100644
--- a/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
+++ b/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
@@ -19,7 +19,7 @@
 #include "api/array_view.h"
 #include "api/audio_codecs/audio_encoder.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc b/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
index c539152..1e6b4f0 100644
--- a/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
+++ b/modules/audio_coding/codecs/tools/audio_codec_speed_test.cc
@@ -12,7 +12,7 @@
 
 #include "rtc_base/format_macros.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using ::std::get;
 
diff --git a/modules/audio_coding/include/audio_coding_module.h b/modules/audio_coding/include/audio_coding_module.h
index f9fdba5..7e5bf1b 100644
--- a/modules/audio_coding/include/audio_coding_module.h
+++ b/modules/audio_coding/include/audio_coding_module.h
@@ -13,12 +13,12 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "absl/types/optional.h"
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_encoder.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "rtc_base/function_view.h"
@@ -27,12 +27,11 @@
 namespace webrtc {
 
 // forward declarations
-struct CodecInst;
-struct WebRtcRTPHeader;
 class AudioDecoder;
 class AudioEncoder;
 class AudioFrame;
 class RTPFragmentationHeader;
+struct RTPHeader;
 
 #define WEBRTC_10MS_PCM_AUDIO 960  // 16 bits super wideband 48 kHz
 
@@ -77,80 +76,6 @@
   virtual ~AudioCodingModule() = default;
 
   ///////////////////////////////////////////////////////////////////////////
-  //   Utility functions
-  //
-
-  ///////////////////////////////////////////////////////////////////////////
-  // uint8_t NumberOfCodecs()
-  // Returns number of supported codecs.
-  //
-  // Return value:
-  //   number of supported codecs.
-  ///
-  static int NumberOfCodecs();
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t Codec()
-  // Get supported codec with list number.
-  //
-  // Input:
-  //   -list_id             : list number.
-  //
-  // Output:
-  //   -codec              : a structure where the parameters of the codec,
-  //                         given by list number is written to.
-  //
-  // Return value:
-  //   -1 if the list number (list_id) is invalid.
-  //    0 if succeeded.
-  //
-  static int Codec(int list_id, CodecInst* codec);
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t Codec()
-  // Get supported codec with the given codec name, sampling frequency, and
-  // a given number of channels.
-  //
-  // Input:
-  //   -payload_name       : name of the codec.
-  //   -sampling_freq_hz   : sampling frequency of the codec. Note! for RED
-  //                         a sampling frequency of -1 is a valid input.
-  //   -channels           : number of channels ( 1 - mono, 2 - stereo).
-  //
-  // Output:
-  //   -codec              : a structure where the function returns the
-  //                         default parameters of the codec.
-  //
-  // Return value:
-  //   -1 if no codec matches the given parameters.
-  //    0 if succeeded.
-  //
-  static int Codec(const char* payload_name,
-                   CodecInst* codec,
-                   int sampling_freq_hz,
-                   size_t channels);
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t Codec()
-  //
-  // Returns the list number of the given codec name, sampling frequency, and
-  // a given number of channels.
-  //
-  // Input:
-  //   -payload_name        : name of the codec.
-  //   -sampling_freq_hz    : sampling frequency of the codec. Note! for RED
-  //                          a sampling frequency of -1 is a valid input.
-  //   -channels            : number of channels ( 1 - mono, 2 - stereo).
-  //
-  // Return value:
-  //   if the codec is found, the index of the codec in the list,
-  //   -1 if the codec is not found.
-  //
-  static int Codec(const char* payload_name,
-                   int sampling_freq_hz,
-                   size_t channels);
-
-  ///////////////////////////////////////////////////////////////////////////
   //   Sender
   //
 
@@ -170,15 +95,6 @@
   }
 
   ///////////////////////////////////////////////////////////////////////////
-  // int32_t SendCodec()
-  // Get parameters for the codec currently registered as send codec.
-  //
-  // Return value:
-  //   The send codec, or nothing if we don't have one
-  //
-  virtual absl::optional<CodecInst> SendCodec() const = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
   // Sets the bitrate to the specified value in bits/sec. If the value is not
   // supported by the codec, it will choose another appropriate value.
   //
@@ -302,60 +218,17 @@
   virtual void SetReceiveCodecs(
       const std::map<int, SdpAudioFormat>& codecs) = 0;
 
-  // Registers a decoder for the given payload type. Returns true iff
-  // successful.
-  virtual bool RegisterReceiveCodec(int rtp_payload_type,
-                                    const SdpAudioFormat& audio_format) = 0;
-
-  // Registers an external decoder. The name is only used to provide information
-  // back to the caller about the decoder. Hence, the name is arbitrary, and may
-  // be empty.
-  virtual int RegisterExternalReceiveCodec(int rtp_payload_type,
-                                           AudioDecoder* external_decoder,
-                                           int sample_rate_hz,
-                                           int num_channels,
-                                           const std::string& name) = 0;
-
   ///////////////////////////////////////////////////////////////////////////
-  // int32_t UnregisterReceiveCodec()
-  // Unregister the codec currently registered with a specific payload type
-  // from the list of possible receive codecs.
-  //
-  // Input:
-  //   -payload_type        : The number representing the payload type to
-  //                         unregister.
-  //
-  // Output:
-  //   -1 if fails to unregister.
-  //    0 if the given codec is successfully unregistered.
-  //
-  virtual int UnregisterReceiveCodec(uint8_t payload_type) = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
-  // int32_t ReceiveCodec()
-  // Get the codec associated with last received payload.
-  //
-  // Output:
-  //   -curr_receive_codec : parameters of the codec associated with the last
-  //                         received payload, c.f. common_types.h for
-  //                         the definition of CodecInst.
+  // absl::optional<std::pair<int, SdpAudioFormat>> ReceiveCodec()
+  // Get the codec info associated with last received payload.
   //
   // Return value:
-  //   -1 if failed to retrieve the codec,
-  //    0 if the codec is successfully retrieved.
-  //
-  virtual int32_t ReceiveCodec(CodecInst* curr_receive_codec) const = 0;
-
-  ///////////////////////////////////////////////////////////////////////////
-  // absl::optional<SdpAudioFormat> ReceiveFormat()
-  // Get the format associated with last received payload.
-  //
-  // Return value:
-  //    An SdpAudioFormat describing the format associated with the last
-  //    received payload.
+  //    A payload type and SdpAudioFormat describing the format associated with
+  //    the last received payload.
   //    An empty Optional if no payload has yet been received.
   //
-  virtual absl::optional<SdpAudioFormat> ReceiveFormat() const = 0;
+  virtual absl::optional<std::pair<int, SdpAudioFormat>>
+      ReceiveCodec() const = 0;
 
   ///////////////////////////////////////////////////////////////////////////
   // int32_t IncomingPacket()
@@ -373,7 +246,7 @@
   //
   virtual int32_t IncomingPacket(const uint8_t* incoming_payload,
                                  const size_t payload_len_bytes,
-                                 const WebRtcRTPHeader& rtp_info) = 0;
+                                 const RTPHeader& rtp_header) = 0;
 
   ///////////////////////////////////////////////////////////////////////////
   // int SetMinimumPlayoutDelay()
@@ -402,6 +275,15 @@
   //
   virtual int SetMaximumPlayoutDelay(int time_ms) = 0;
 
+  // Sets a base minimum for the playout delay. Base minimum delay sets lower
+  // bound minimum delay value which is set via SetMinimumPlayoutDelay.
+  //
+  // Returns true if value was successfully set, false overwise.
+  virtual bool SetBaseMinimumPlayoutDelayMs(int delay_ms) = 0;
+
+  // Returns current value of base minimum delay in milliseconds.
+  virtual int GetBaseMinimumPlayoutDelayMs() const = 0;
+
   ///////////////////////////////////////////////////////////////////////////
   // int32_t PlayoutTimestamp()
   // The send timestamp of an RTP packet is associated with the decoded
diff --git a/modules/audio_coding/include/audio_coding_module_typedefs.h b/modules/audio_coding/include/audio_coding_module_typedefs.h
index bafff72..7aa7f8b 100644
--- a/modules/audio_coding/include/audio_coding_module_typedefs.h
+++ b/modules/audio_coding/include/audio_coding_module_typedefs.h
@@ -80,6 +80,7 @@
   uint64_t concealedSamples;
   uint64_t concealmentEvents;
   uint64_t jitterBufferDelayMs;
+  uint64_t jitterBufferEmittedCount;
   // Stats below DO NOT correspond directly to anything in the WebRTC stats
   // Loss rate (network + late); fraction between 0 and 1, scaled to Q14.
   uint16_t currentPacketLossRate;
@@ -121,6 +122,8 @@
   uint64_t packetBufferFlushes;
   // number of samples expanded due to delayed packets
   uint64_t delayedPacketOutageSamples;
+  // arrival delay of incoming packets
+  uint64_t relativePacketArrivalDelayMs;
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/accelerate.h b/modules/audio_coding/neteq/accelerate.h
index 1a3af42..124b633 100644
--- a/modules/audio_coding/neteq/accelerate.h
+++ b/modules/audio_coding/neteq/accelerate.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 
 #include "modules/audio_coding/neteq/time_stretch.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_decoder_unittest.cc b/modules/audio_coding/neteq/audio_decoder_unittest.cc
index 1ad4835..42d96db 100644
--- a/modules/audio_coding/neteq/audio_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/audio_decoder_unittest.cc
@@ -31,7 +31,7 @@
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_multi_vector.h b/modules/audio_coding/neteq/audio_multi_vector.h
index a2dd3c3..a21bf57 100644
--- a/modules/audio_coding/neteq/audio_multi_vector.h
+++ b/modules/audio_coding/neteq/audio_multi_vector.h
@@ -17,7 +17,7 @@
 
 #include "api/array_view.h"
 #include "modules/audio_coding/neteq/audio_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
index 5b2ec20..d1351d8 100644
--- a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
+++ b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
@@ -309,9 +309,9 @@
   }
 }
 
-INSTANTIATE_TEST_CASE_P(TestNumChannels,
-                        AudioMultiVectorTest,
-                        ::testing::Values(static_cast<size_t>(1),
-                                          static_cast<size_t>(2),
-                                          static_cast<size_t>(5)));
+INSTANTIATE_TEST_SUITE_P(TestNumChannels,
+                         AudioMultiVectorTest,
+                         ::testing::Values(static_cast<size_t>(1),
+                                           static_cast<size_t>(2),
+                                           static_cast<size_t>(5)));
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/audio_vector.h b/modules/audio_coding/neteq/audio_vector.h
index d0db332..c8279da 100644
--- a/modules/audio_coding/neteq/audio_vector.h
+++ b/modules/audio_coding/neteq/audio_vector.h
@@ -16,7 +16,7 @@
 #include <memory>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/background_noise.h b/modules/audio_coding/neteq/background_noise.h
index 84d7eb9..d047942 100644
--- a/modules/audio_coding/neteq/background_noise.h
+++ b/modules/audio_coding/neteq/background_noise.h
@@ -14,7 +14,7 @@
 #include <string.h>  // size_t
 #include <memory>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/buffer_level_filter.h b/modules/audio_coding/neteq/buffer_level_filter.h
index c8d27dc..83388fb 100644
--- a/modules/audio_coding/neteq/buffer_level_filter.h
+++ b/modules/audio_coding/neteq/buffer_level_filter.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/comfort_noise.h b/modules/audio_coding/neteq/comfort_noise.h
index 3a9bfde..f748772 100644
--- a/modules/audio_coding/neteq/comfort_noise.h
+++ b/modules/audio_coding/neteq/comfort_noise.h
@@ -13,7 +13,7 @@
 
 #include <stddef.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index 83c2b3b..fda12c3 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -23,34 +23,10 @@
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "system_wrappers/include/field_trial.h"
 
 namespace {
-constexpr char kPostponeDecodingFieldTrial[] =
-    "WebRTC-Audio-NetEqPostponeDecodingAfterExpand";
 
-int GetPostponeDecodingLevel() {
-  const bool enabled =
-      webrtc::field_trial::IsEnabled(kPostponeDecodingFieldTrial);
-  if (!enabled)
-    return 0;
-
-  constexpr int kDefaultPostponeDecodingLevel = 50;
-  const std::string field_trial_string =
-      webrtc::field_trial::FindFullName(kPostponeDecodingFieldTrial);
-  int value = -1;
-  if (sscanf(field_trial_string.c_str(), "Enabled-%d", &value) == 1) {
-    if (value >= 0 && value <= 100) {
-      return value;
-    } else {
-      RTC_LOG(LS_WARNING)
-          << "Wrong value (" << value
-          << ") for postpone decoding after expand, using default ("
-          << kDefaultPostponeDecodingLevel << ")";
-    }
-  }
-  return kDefaultPostponeDecodingLevel;
-}
+constexpr int kPostponeDecodingLevel = 50;
 
 }  // namespace
 
@@ -89,8 +65,7 @@
       disallow_time_stretching_(disallow_time_stretching),
       timescale_countdown_(
           tick_timer_->GetNewCountdown(kMinTimescaleInterval + 1)),
-      num_consecutive_expands_(0),
-      postpone_decoding_level_(GetPostponeDecodingLevel()) {
+      num_consecutive_expands_(0) {
   delay_manager_->set_streaming_mode(false);
   SetSampleRate(fs_hz, output_size_samples);
 }
@@ -141,6 +116,7 @@
 
   const size_t samples_left =
       sync_buffer.FutureLength() - expand.overlap_length();
+  // TODO(jakobi): Use buffer span instead of num samples.
   const size_t cur_size_samples =
       samples_left + packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
 
@@ -194,13 +170,14 @@
   // if the mute factor is low enough (otherwise the expansion was short enough
   // to not be noticable).
   // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
+  size_t current_span =
+      samples_left + packet_buffer_.GetSpanSamples(decoder_frame_length);
   if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
       expand.MuteFactor(0) < 16384 / 2 &&
-      cur_size_samples < static_cast<size_t>(
-              delay_manager_->TargetLevel() * packet_length_samples_ *
-              postpone_decoding_level_ / 100) >> 8 &&
+      current_span < static_cast<size_t>(delay_manager_->TargetLevel() *
+                                         packet_length_samples_ *
+                                         kPostponeDecodingLevel / 100)>> 8 &&
       !packet_buffer_.ContainsDtxOrCngPacket(decoder_database_)) {
-    RTC_DCHECK(webrtc::field_trial::IsEnabled(kPostponeDecodingFieldTrial));
     return kExpand;
   }
 
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index 2a53359..ad8e2cd 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -13,7 +13,7 @@
 
 #include "modules/audio_coding/neteq/defines.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -108,10 +108,6 @@
   }
   void set_prev_time_scale(bool value) { prev_time_scale_ = value; }
 
-  int postpone_decoding_level_for_test() const {
-    return postpone_decoding_level_;
-  }
-
  private:
   // The value 5 sets maximum time-stretch rate to about 100 ms/s.
   static const int kMinTimescaleInterval = 5;
@@ -184,7 +180,6 @@
   bool disallow_time_stretching_;
   std::unique_ptr<TickTimer::Countdown> timescale_countdown_;
   int num_consecutive_expands_;
-  const int postpone_decoding_level_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DecisionLogic);
 };
diff --git a/modules/audio_coding/neteq/decision_logic_unittest.cc b/modules/audio_coding/neteq/decision_logic_unittest.cc
index 183b9c7..5c3d489 100644
--- a/modules/audio_coding/neteq/decision_logic_unittest.cc
+++ b/modules/audio_coding/neteq/decision_logic_unittest.cc
@@ -16,8 +16,8 @@
 #include "modules/audio_coding/neteq/delay_manager.h"
 #include "modules/audio_coding/neteq/delay_peak_detector.h"
 #include "modules/audio_coding/neteq/packet_buffer.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "test/field_trial.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder_factory.h"
 
@@ -29,72 +29,18 @@
   DecoderDatabase decoder_database(
       new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
   TickTimer tick_timer;
+  StatisticsCalculator stats;
   PacketBuffer packet_buffer(10, &tick_timer);
-  DelayPeakDetector delay_peak_detector(&tick_timer);
-  DelayManager delay_manager(240, 0, &delay_peak_detector, &tick_timer);
+  DelayPeakDetector delay_peak_detector(&tick_timer, false);
+  auto delay_manager = DelayManager::Create(240, 0, false, &delay_peak_detector,
+                                            &tick_timer, &stats);
   BufferLevelFilter buffer_level_filter;
   DecisionLogic* logic = DecisionLogic::Create(
       fs_hz, output_size_samples, false, &decoder_database, packet_buffer,
-      &delay_manager, &buffer_level_filter, &tick_timer);
+      delay_manager.get(), &buffer_level_filter, &tick_timer);
   delete logic;
 }
 
-TEST(DecisionLogic, PostponeDecodingAfterExpansionSettings) {
-  constexpr int kDefaultPostponeDecodingLevel = 50;
-  constexpr int kFsHz = 8000;
-  constexpr int kOutputSizeSamples = kFsHz / 100;  // Samples per 10 ms.
-  DecoderDatabase decoder_database(
-      new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
-  TickTimer tick_timer;
-  PacketBuffer packet_buffer(10, &tick_timer);
-  DelayPeakDetector delay_peak_detector(&tick_timer);
-  DelayManager delay_manager(240, 0, &delay_peak_detector, &tick_timer);
-  BufferLevelFilter buffer_level_filter;
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(kDefaultPostponeDecodingLevel,
-              logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled-65/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(65, logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Disabled/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(0, logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled--1/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(kDefaultPostponeDecodingLevel,
-              logic.postpone_decoding_level_for_test());
-  }
-  {
-    test::ScopedFieldTrials field_trial(
-        "WebRTC-Audio-NetEqPostponeDecodingAfterExpand/Enabled-101/");
-    DecisionLogic logic(kFsHz, kOutputSizeSamples, false, &decoder_database,
-                        packet_buffer, &delay_manager, &buffer_level_filter,
-                        &tick_timer);
-    EXPECT_EQ(kDefaultPostponeDecodingLevel,
-              logic.postpone_decoding_level_for_test());
-  }
-}
-
 // TODO(hlundin): Write more tests.
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/decoder_database.cc b/modules/audio_coding/neteq/decoder_database.cc
index 0890beb..2049569 100644
--- a/modules/audio_coding/neteq/decoder_database.cc
+++ b/modules/audio_coding/neteq/decoder_database.cc
@@ -18,7 +18,6 @@
 
 #include "absl/strings/match.h"
 #include "api/audio_codecs/audio_decoder.h"
-#include "common_types.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/strings/audio_format_to_string.h"
@@ -44,7 +43,6 @@
       audio_format_(audio_format),
       codec_pair_id_(codec_pair_id),
       factory_(factory),
-      external_decoder_(nullptr),
       cng_decoder_(CngDecoder::Create(audio_format)),
       subtype_(SubtypeFromFormat(audio_format)) {}
 
@@ -54,48 +52,14 @@
     AudioDecoderFactory* factory)
     : DecoderInfo(audio_format, codec_pair_id, factory, audio_format.name) {}
 
-DecoderDatabase::DecoderInfo::DecoderInfo(
-    NetEqDecoder ct,
-    absl::optional<AudioCodecPairId> codec_pair_id,
-    AudioDecoderFactory* factory)
-    : DecoderInfo(*NetEqDecoderToSdpAudioFormat(ct), codec_pair_id, factory) {}
-
-DecoderDatabase::DecoderInfo::DecoderInfo(const SdpAudioFormat& audio_format,
-                                          AudioDecoder* ext_dec,
-                                          const std::string& codec_name)
-    : name_(codec_name),
-      audio_format_(audio_format),
-      codec_pair_id_(absl::nullopt),
-      factory_(nullptr),
-      external_decoder_(ext_dec),
-      subtype_(Subtype::kNormal) {
-  RTC_CHECK(ext_dec);
-}
-
 DecoderDatabase::DecoderInfo::DecoderInfo(DecoderInfo&&) = default;
 DecoderDatabase::DecoderInfo::~DecoderInfo() = default;
 
-bool DecoderDatabase::DecoderInfo::CanGetDecoder() const {
-  if (subtype_ == Subtype::kNormal && !external_decoder_ && !decoder_) {
-    // TODO(ossu): Keep a check here for now, since a number of tests create
-    // DecoderInfos without factories.
-    RTC_DCHECK(factory_);
-    return factory_->IsSupportedDecoder(audio_format_);
-  } else {
-    return true;
-  }
-}
-
 AudioDecoder* DecoderDatabase::DecoderInfo::GetDecoder() const {
   if (subtype_ != Subtype::kNormal) {
     // These are handled internally, so they have no AudioDecoder objects.
     return nullptr;
   }
-  if (external_decoder_) {
-    RTC_DCHECK(!decoder_);
-    RTC_DCHECK(!cng_decoder_);
-    return external_decoder_;
-  }
   if (!decoder_) {
     // TODO(ossu): Keep a check here for now, since a number of tests create
     // DecoderInfos without factories.
@@ -187,32 +151,6 @@
   return changed_payload_types;
 }
 
-int DecoderDatabase::RegisterPayload(uint8_t rtp_payload_type,
-                                     NetEqDecoder codec_type,
-                                     const std::string& name) {
-  if (rtp_payload_type > 0x7F) {
-    return kInvalidRtpPayloadType;
-  }
-  if (codec_type == NetEqDecoder::kDecoderArbitrary) {
-    return kCodecNotSupported;  // Only supported through InsertExternal.
-  }
-  const auto opt_format = NetEqDecoderToSdpAudioFormat(codec_type);
-  if (!opt_format) {
-    return kCodecNotSupported;
-  }
-  DecoderInfo info(*opt_format, codec_pair_id_, decoder_factory_, name);
-  if (!info.CanGetDecoder()) {
-    return kCodecNotSupported;
-  }
-  auto ret =
-      decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
-  if (ret.second == false) {
-    // Database already contains a decoder with type |rtp_payload_type|.
-    return kDecoderExists;
-  }
-  return kOK;
-}
-
 int DecoderDatabase::RegisterPayload(int rtp_payload_type,
                                      const SdpAudioFormat& audio_format) {
   if (rtp_payload_type < 0 || rtp_payload_type > 0x7f) {
@@ -228,31 +166,6 @@
   return kOK;
 }
 
-int DecoderDatabase::InsertExternal(uint8_t rtp_payload_type,
-                                    NetEqDecoder codec_type,
-                                    const std::string& codec_name,
-                                    AudioDecoder* decoder) {
-  if (rtp_payload_type > 0x7F) {
-    return kInvalidRtpPayloadType;
-  }
-  if (!decoder) {
-    return kInvalidPointer;
-  }
-
-  const auto opt_db_format = NetEqDecoderToSdpAudioFormat(codec_type);
-  const SdpAudioFormat format =
-      opt_db_format.value_or(SdpAudioFormat("arbitrary", 0, 0));
-
-  std::pair<DecoderMap::iterator, bool> ret;
-  DecoderInfo info(format, decoder, codec_name);
-  ret = decoders_.insert(std::make_pair(rtp_payload_type, std::move(info)));
-  if (ret.second == false) {
-    // Database already contains a decoder with type |rtp_payload_type|.
-    return kDecoderExists;
-  }
-  return kOK;
-}
-
 int DecoderDatabase::Remove(uint8_t rtp_payload_type) {
   if (decoders_.erase(rtp_payload_type) == 0) {
     // No decoder with that |rtp_payload_type|.
diff --git a/modules/audio_coding/neteq/decoder_database.h b/modules/audio_coding/neteq/decoder_database.h
index 131e769..e0a3fe3 100644
--- a/modules/audio_coding/neteq/decoder_database.h
+++ b/modules/audio_coding/neteq/decoder_database.h
@@ -17,12 +17,10 @@
 
 #include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/audio_codecs/audio_format.h"
-#include "common_types.h"  // NOLINT(build/include)  // NULL
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/codecs/cng/webrtc_cng.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
 #include "modules/audio_coding/neteq/packet.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -48,19 +46,9 @@
     explicit DecoderInfo(const SdpAudioFormat& audio_format,
                          absl::optional<AudioCodecPairId> codec_pair_id,
                          AudioDecoderFactory* factory = nullptr);
-    explicit DecoderInfo(NetEqDecoder ct,
-                         absl::optional<AudioCodecPairId> codec_pair_id,
-                         AudioDecoderFactory* factory = nullptr);
-    DecoderInfo(const SdpAudioFormat& audio_format,
-                AudioDecoder* ext_dec,
-                const std::string& codec_name);
     DecoderInfo(DecoderInfo&&);
     ~DecoderInfo();
 
-    // Was this info object created with a specification that allows us to
-    // actually produce a decoder?
-    bool CanGetDecoder() const;
-
     // Get the AudioDecoder object, creating it first if necessary.
     AudioDecoder* GetDecoder() const;
 
@@ -110,9 +98,6 @@
     AudioDecoderFactory* const factory_;
     mutable std::unique_ptr<AudioDecoder> decoder_;
 
-    // Set iff this is an external decoder.
-    AudioDecoder* const external_decoder_;
-
     // Set iff this is a comfort noise decoder.
     struct CngDecoder {
       static absl::optional<CngDecoder> Create(const SdpAudioFormat& format);
@@ -153,26 +138,11 @@
   virtual std::vector<int> SetCodecs(
       const std::map<int, SdpAudioFormat>& codecs);
 
-  // Registers |rtp_payload_type| as a decoder of type |codec_type|. The |name|
-  // is only used to populate the name field in the DecoderInfo struct in the
-  // database, and can be arbitrary (including empty). Returns kOK on success;
-  // otherwise an error code.
-  virtual int RegisterPayload(uint8_t rtp_payload_type,
-                              NetEqDecoder codec_type,
-                              const std::string& name);
-
   // Registers a decoder for the given payload type. Returns kOK on success;
   // otherwise an error code.
   virtual int RegisterPayload(int rtp_payload_type,
                               const SdpAudioFormat& audio_format);
 
-  // Registers an externally created AudioDecoder object, and associates it
-  // as a decoder of type |codec_type| with |rtp_payload_type|.
-  virtual int InsertExternal(uint8_t rtp_payload_type,
-                             NetEqDecoder codec_type,
-                             const std::string& codec_name,
-                             AudioDecoder* decoder);
-
   // Removes the entry for |rtp_payload_type| from the database.
   // Returns kDecoderNotFound or kOK depending on the outcome of the operation.
   virtual int Remove(uint8_t rtp_payload_type);
diff --git a/modules/audio_coding/neteq/decoder_database_unittest.cc b/modules/audio_coding/neteq/decoder_database_unittest.cc
index 3c49faa..9a28cac 100644
--- a/modules/audio_coding/neteq/decoder_database_unittest.cc
+++ b/modules/audio_coding/neteq/decoder_database_unittest.cc
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "rtc_base/refcountedobject.h"
+#include "rtc_base/ref_counted_object.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder.h"
@@ -36,17 +36,12 @@
 TEST(DecoderDatabase, InsertAndRemove) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   const uint8_t kPayloadType = 0;
   const std::string kCodecName = "Robert\'); DROP TABLE Students;";
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName));
+      db.RegisterPayload(kPayloadType, SdpAudioFormat(kCodecName, 8000, 1)));
   EXPECT_EQ(1, db.Size());
   EXPECT_FALSE(db.Empty());
   EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
@@ -57,22 +52,13 @@
 TEST(DecoderDatabase, InsertAndRemoveAll) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcma", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   const std::string kCodecName1 = "Robert\'); DROP TABLE Students;";
   const std::string kCodecName2 = "https://xkcd.com/327/";
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu, kCodecName1));
+            db.RegisterPayload(0, SdpAudioFormat(kCodecName1, 8000, 1)));
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(1, NetEqDecoder::kDecoderPCMa, kCodecName2));
+            db.RegisterPayload(1, SdpAudioFormat(kCodecName2, 8000, 1)));
   EXPECT_EQ(2, db.Size());
   EXPECT_FALSE(db.Empty());
   db.RemoveAll();
@@ -83,11 +69,6 @@
 TEST(DecoderDatabase, GetDecoderInfo) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   auto* decoder = new MockAudioDecoder;
   EXPECT_CALL(*factory, MakeAudioDecoderMock(_, _, _))
       .WillOnce(Invoke([decoder](const SdpAudioFormat& format,
@@ -98,10 +79,10 @@
       }));
   DecoderDatabase db(factory, absl::nullopt);
   const uint8_t kPayloadType = 0;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
+  const std::string kCodecName = "pcmu";
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCMu, kCodecName));
+      db.RegisterPayload(kPayloadType, SdpAudioFormat(kCodecName, 8000, 1)));
   const DecoderDatabase::DecoderInfo* info;
   info = db.GetDecoderInfo(kPayloadType);
   ASSERT_TRUE(info != NULL);
@@ -115,10 +96,8 @@
 TEST(DecoderDatabase, GetDecoder) {
   DecoderDatabase db(CreateBuiltinAudioDecoderFactory(), absl::nullopt);
   const uint8_t kPayloadType = 0;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(kPayloadType, NetEqDecoder::kDecoderPCM16B,
-                               kCodecName));
+            db.RegisterPayload(kPayloadType, SdpAudioFormat("l16", 8000, 1)));
   AudioDecoder* dec = db.GetDecoder(kPayloadType);
   ASSERT_TRUE(dec != NULL);
 }
@@ -126,11 +105,6 @@
 TEST(DecoderDatabase, TypeTests) {
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .WillOnce(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   const uint8_t kPayloadTypePcmU = 0;
   const uint8_t kPayloadTypeCng = 13;
@@ -140,16 +114,15 @@
   // Load into database.
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadTypePcmU, NetEqDecoder::kDecoderPCMu, "pcmu"));
+      db.RegisterPayload(kPayloadTypePcmU, SdpAudioFormat("pcmu", 8000, 1)));
   EXPECT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(kPayloadTypeCng, NetEqDecoder::kDecoderCNGnb,
-                               "cng-nb"));
+            db.RegisterPayload(kPayloadTypeCng, SdpAudioFormat("cn", 8000, 1)));
+  EXPECT_EQ(DecoderDatabase::kOK,
+            db.RegisterPayload(kPayloadTypeDtmf,
+                               SdpAudioFormat("telephone-event", 8000, 1)));
   EXPECT_EQ(
       DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadTypeDtmf, NetEqDecoder::kDecoderAVT, "avt"));
-  EXPECT_EQ(
-      DecoderDatabase::kOK,
-      db.RegisterPayload(kPayloadTypeRed, NetEqDecoder::kDecoderRED, "red"));
+      db.RegisterPayload(kPayloadTypeRed, SdpAudioFormat("red", 8000, 1)));
   EXPECT_EQ(4, db.Size());
   // Test.
   EXPECT_FALSE(db.IsComfortNoise(kPayloadNotUsed));
@@ -165,52 +138,18 @@
   EXPECT_TRUE(db.IsRed(kPayloadTypeRed));
 }
 
-TEST(DecoderDatabase, ExternalDecoder) {
-  DecoderDatabase db(new rtc::RefCountedObject<MockAudioDecoderFactory>,
-                     absl::nullopt);
-  const uint8_t kPayloadType = 0;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
-  MockAudioDecoder decoder;
-  // Load into database.
-  EXPECT_EQ(DecoderDatabase::kOK,
-            db.InsertExternal(kPayloadType, NetEqDecoder::kDecoderPCMu,
-                              kCodecName, &decoder));
-  EXPECT_EQ(1, db.Size());
-  // Get decoder and make sure we get the external one.
-  EXPECT_EQ(&decoder, db.GetDecoder(kPayloadType));
-  // Get the decoder info struct and check it too.
-  const DecoderDatabase::DecoderInfo* info;
-  info = db.GetDecoderInfo(kPayloadType);
-  ASSERT_TRUE(info != NULL);
-  EXPECT_TRUE(info->IsType("pcmu"));
-  EXPECT_EQ(info->get_name(), kCodecName);
-  EXPECT_EQ(kCodecName, info->get_name());
-  // Expect not to delete the decoder when removing it from the database, since
-  // it was declared externally.
-  EXPECT_CALL(decoder, Die()).Times(0);
-  EXPECT_EQ(DecoderDatabase::kOK, db.Remove(kPayloadType));
-  EXPECT_TRUE(db.Empty());
-
-  EXPECT_CALL(decoder, Die()).Times(1);  // Will be called when |db| is deleted.
-}
-
 TEST(DecoderDatabase, CheckPayloadTypes) {
   constexpr int kNumPayloads = 10;
   rtc::scoped_refptr<MockAudioDecoderFactory> factory(
       new rtc::RefCountedObject<MockAudioDecoderFactory>);
-  EXPECT_CALL(*factory, IsSupportedDecoder(_))
-      .Times(kNumPayloads)
-      .WillRepeatedly(Invoke([](const SdpAudioFormat& format) {
-        EXPECT_EQ("pcmu", format.name);
-        return true;
-      }));
   DecoderDatabase db(factory, absl::nullopt);
   // Load a number of payloads into the database. Payload types are 0, 1, ...,
   // while the decoder type is the same for all payload types (this does not
   // matter for the test).
   for (uint8_t payload_type = 0; payload_type < kNumPayloads; ++payload_type) {
-    EXPECT_EQ(DecoderDatabase::kOK,
-              db.RegisterPayload(payload_type, NetEqDecoder::kDecoderPCMu, ""));
+    EXPECT_EQ(
+        DecoderDatabase::kOK,
+        db.RegisterPayload(payload_type, SdpAudioFormat("pcmu", 8000, 1)));
   }
   PacketList packet_list;
   for (int i = 0; i < kNumPayloads + 1; ++i) {
@@ -247,11 +186,11 @@
   DecoderDatabase db(CreateBuiltinAudioDecoderFactory(), absl::nullopt);
   // Load payload types.
   ASSERT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(0, NetEqDecoder::kDecoderPCMu, "pcmu"));
+            db.RegisterPayload(0, SdpAudioFormat("pcmu", 8000, 1)));
   ASSERT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(103, NetEqDecoder::kDecoderISAC, "isac"));
+            db.RegisterPayload(103, SdpAudioFormat("isac", 16000, 1)));
   ASSERT_EQ(DecoderDatabase::kOK,
-            db.RegisterPayload(13, NetEqDecoder::kDecoderCNGnb, "cng-nb"));
+            db.RegisterPayload(13, SdpAudioFormat("cn", 8000, 1)));
   // Verify that no decoders are active from the start.
   EXPECT_EQ(NULL, db.GetActiveDecoder());
   EXPECT_EQ(NULL, db.GetActiveCngDecoder());
diff --git a/modules/audio_coding/neteq/delay_manager.cc b/modules/audio_coding/neteq/delay_manager.cc
index 67e6a13..4e2f3c7 100644
--- a/modules/audio_coding/neteq/delay_manager.cc
+++ b/modules/audio_coding/neteq/delay_manager.cc
@@ -17,23 +17,39 @@
 #include <numeric>
 #include <string>
 
+#include "absl/memory/memory.h"
 #include "modules/audio_coding/neteq/delay_peak_detector.h"
+#include "modules/audio_coding/neteq/histogram.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/include/module_common_types_public.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/numerics/safe_minmax.h"
 #include "system_wrappers/include/field_trial.h"
 
 namespace {
 
-constexpr int kLimitProbability = 53687091;         // 1/20 in Q30.
-constexpr int kLimitProbabilityStreaming = 536871;  // 1/2000 in Q30.
-constexpr int kMaxStreamingPeakPeriodMs = 600000;   // 10 minutes in ms.
+constexpr int kLimitProbability = 1020054733;           // 19/20 in Q30.
+constexpr int kLimitProbabilityStreaming = 1073204953;  // 1999/2000 in Q30.
+constexpr int kMaxStreamingPeakPeriodMs = 600000;       // 10 minutes in ms.
 constexpr int kCumulativeSumDrift = 2;  // Drift term for cumulative sum
                                         // |iat_cumulative_sum_|.
-// Steady-state forgetting factor for |iat_vector_|, 0.9993 in Q15.
-constexpr int kIatFactor_ = 32745;
-constexpr int kMaxIat = 64;  // Max inter-arrival time to register.
+constexpr int kMinBaseMinimumDelayMs = 0;
+constexpr int kMaxBaseMinimumDelayMs = 10000;
+constexpr int kIatFactor = 32745;  // 0.9993 in Q15.
+constexpr int kMaxIat = 64;        // Max inter-arrival time to register.
+constexpr int kMaxReorderedPackets =
+    10;  // Max number of consecutive reordered packets.
+constexpr int kMaxHistoryPackets =
+    100;  // Max number of packets used to calculate relative packet arrival
+          // delay.
+constexpr int kDelayBuckets = 100;
+constexpr int kBucketSizeMs = 20;
+
+int PercentileToQuantile(double percentile) {
+  return static_cast<int>((1 << 30) * percentile / 100.0 + 0.5);
+}
 
 absl::optional<int> GetForcedLimitProbability() {
   constexpr char kForceTargetDelayPercentileFieldTrial[] =
@@ -46,8 +62,8 @@
     double percentile = -1.0;
     if (sscanf(field_trial_string.c_str(), "Enabled-%lf", &percentile) == 1 &&
         percentile >= 0.0 && percentile <= 100.0) {
-      return absl::make_optional<int>(static_cast<int>(
-          (1 << 30) * (100.0 - percentile) / 100.0 + 0.5));  // in Q30.
+      return absl::make_optional<int>(
+          PercentileToQuantile(percentile));  // in Q30.
     } else {
       RTC_LOG(LS_WARNING) << "Invalid parameter for "
                           << kForceTargetDelayPercentileFieldTrial
@@ -57,64 +73,111 @@
   return absl::nullopt;
 }
 
+struct DelayHistogramConfig {
+  int quantile = 1020054733;  // 0.95 in Q30.
+  int forget_factor = 32745;  // 0.9993 in Q15.
+};
+
+absl::optional<DelayHistogramConfig> GetDelayHistogramConfig() {
+  constexpr char kDelayHistogramFieldTrial[] =
+      "WebRTC-Audio-NetEqDelayHistogram";
+  const bool use_new_delay_manager =
+      webrtc::field_trial::IsEnabled(kDelayHistogramFieldTrial);
+  if (use_new_delay_manager) {
+    const auto field_trial_string =
+        webrtc::field_trial::FindFullName(kDelayHistogramFieldTrial);
+    DelayHistogramConfig config;
+    double percentile = -1.0;
+    double forget_factor = -1.0;
+    if (sscanf(field_trial_string.c_str(), "Enabled-%lf-%lf", &percentile,
+               &forget_factor) == 2 &&
+        percentile >= 0.0 && percentile <= 100.0 && forget_factor >= 0.0 &&
+        forget_factor <= 1.0) {
+      config.quantile = PercentileToQuantile(percentile);
+      config.forget_factor = (1 << 15) * forget_factor;
+    }
+    RTC_LOG(LS_INFO) << "Delay histogram config:"
+                     << " quantile=" << config.quantile
+                     << " forget_factor=" << config.forget_factor;
+    return absl::make_optional(config);
+  }
+  return absl::nullopt;
+}
+
 }  // namespace
 
 namespace webrtc {
 
 DelayManager::DelayManager(size_t max_packets_in_buffer,
-                           int base_min_target_delay_ms,
+                           int base_minimum_delay_ms,
+                           int histogram_quantile,
+                           HistogramMode histogram_mode,
+                           bool enable_rtx_handling,
                            DelayPeakDetector* peak_detector,
-                           const TickTimer* tick_timer)
+                           const TickTimer* tick_timer,
+                           StatisticsCalculator* statistics,
+                           std::unique_ptr<Histogram> histogram)
     : first_packet_received_(false),
       max_packets_in_buffer_(max_packets_in_buffer),
-      iat_vector_(kMaxIat + 1, 0),
-      iat_factor_(0),
+      histogram_(std::move(histogram)),
+      histogram_quantile_(histogram_quantile),
+      histogram_mode_(histogram_mode),
       tick_timer_(tick_timer),
-      base_min_target_delay_ms_(base_min_target_delay_ms),
+      statistics_(statistics),
+      base_minimum_delay_ms_(base_minimum_delay_ms),
+      effective_minimum_delay_ms_(base_minimum_delay_ms),
       base_target_level_(4),                   // In Q0 domain.
       target_level_(base_target_level_ << 8),  // In Q8 domain.
       packet_len_ms_(0),
       streaming_mode_(false),
       last_seq_no_(0),
       last_timestamp_(0),
-      minimum_delay_ms_(base_min_target_delay_ms_),
-      maximum_delay_ms_(target_level_),
+      minimum_delay_ms_(0),
+      maximum_delay_ms_(0),
       iat_cumulative_sum_(0),
       max_iat_cumulative_sum_(0),
       peak_detector_(*peak_detector),
       last_pack_cng_or_dtmf_(1),
       frame_length_change_experiment_(
           field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")),
-      forced_limit_probability_(GetForcedLimitProbability()) {
+      enable_rtx_handling_(enable_rtx_handling) {
   assert(peak_detector);  // Should never be NULL.
-  RTC_DCHECK_GE(base_min_target_delay_ms_, 0);
-  RTC_DCHECK_LE(minimum_delay_ms_, maximum_delay_ms_);
+  RTC_CHECK(histogram_);
+  RTC_DCHECK_GE(base_minimum_delay_ms_, 0);
 
   Reset();
 }
 
-DelayManager::~DelayManager() {}
-
-const DelayManager::IATVector& DelayManager::iat_vector() const {
-  return iat_vector_;
-}
-
-// Set the histogram vector to an exponentially decaying distribution
-// iat_vector_[i] = 0.5^(i+1), i = 0, 1, 2, ...
-// iat_vector_ is in Q30.
-void DelayManager::ResetHistogram() {
-  // Set temp_prob to (slightly more than) 1 in Q14. This ensures that the sum
-  // of iat_vector_ is 1.
-  uint16_t temp_prob = 0x4002;  // 16384 + 2 = 100000000000010 binary.
-  IATVector::iterator it = iat_vector_.begin();
-  for (; it < iat_vector_.end(); it++) {
-    temp_prob >>= 1;
-    (*it) = temp_prob << 16;
+std::unique_ptr<DelayManager> DelayManager::Create(
+    size_t max_packets_in_buffer,
+    int base_minimum_delay_ms,
+    bool enable_rtx_handling,
+    DelayPeakDetector* peak_detector,
+    const TickTimer* tick_timer,
+    StatisticsCalculator* statistics) {
+  int quantile;
+  std::unique_ptr<Histogram> histogram;
+  HistogramMode mode;
+  auto delay_histogram_config = GetDelayHistogramConfig();
+  if (delay_histogram_config) {
+    DelayHistogramConfig config = delay_histogram_config.value();
+    quantile = config.quantile;
+    histogram =
+        absl::make_unique<Histogram>(kDelayBuckets, config.forget_factor);
+    mode = RELATIVE_ARRIVAL_DELAY;
+  } else {
+    quantile = GetForcedLimitProbability().value_or(kLimitProbability);
+    histogram = absl::make_unique<Histogram>(kMaxIat + 1, kIatFactor);
+    mode = INTER_ARRIVAL_TIME;
   }
-  base_target_level_ = 4;
-  target_level_ = base_target_level_ << 8;
+  return absl::make_unique<DelayManager>(
+      max_packets_in_buffer, base_minimum_delay_ms, quantile, mode,
+      enable_rtx_handling, peak_detector, tick_timer, statistics,
+      std::move(histogram));
 }
 
+DelayManager::~DelayManager() {}
+
 int DelayManager::Update(uint16_t sequence_number,
                          uint32_t timestamp,
                          int sample_rate_hz) {
@@ -146,34 +209,62 @@
         rtc::saturated_cast<int>(1000 * packet_len_samp / sample_rate_hz);
   }
 
+  bool reordered = false;
   if (packet_len_ms > 0) {
     // Cannot update statistics unless |packet_len_ms| is valid.
-    // Calculate inter-arrival time (IAT) in integer "packet times"
-    // (rounding down). This is the value used as index to the histogram
-    // vector |iat_vector_|.
-    int iat_packets = packet_iat_stopwatch_->ElapsedMs() / packet_len_ms;
-
     if (streaming_mode_) {
       UpdateCumulativeSums(packet_len_ms, sequence_number);
     }
 
+    // Inter-arrival time (IAT) in integer "packet times" (rounding down). This
+    // is the value added to the inter-arrival time histogram.
+    int iat_ms = packet_iat_stopwatch_->ElapsedMs();
+    int iat_packets = iat_ms / packet_len_ms;
     // Check for discontinuous packet sequence and re-ordering.
     if (IsNewerSequenceNumber(sequence_number, last_seq_no_ + 1)) {
       // Compensate for gap in the sequence numbers. Reduce IAT with the
-      // expected extra time due to lost packets, but ensure that the IAT is
-      // not negative.
-      iat_packets -= static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
-      iat_packets = std::max(iat_packets, 0);
+      // expected extra time due to lost packets.
+      int packet_offset =
+          static_cast<uint16_t>(sequence_number - last_seq_no_ - 1);
+      iat_packets -= packet_offset;
+      iat_ms -= packet_offset * packet_len_ms;
     } else if (!IsNewerSequenceNumber(sequence_number, last_seq_no_)) {
-      iat_packets += static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
+      int packet_offset =
+          static_cast<uint16_t>(last_seq_no_ + 1 - sequence_number);
+      iat_packets += packet_offset;
+      iat_ms += packet_offset * packet_len_ms;
+      reordered = true;
     }
 
-    // Saturate IAT at maximum value.
-    const int max_iat = kMaxIat;
-    iat_packets = std::min(iat_packets, max_iat);
-    UpdateHistogram(iat_packets);
+    int iat_delay = iat_ms - packet_len_ms;
+    int relative_delay;
+    if (reordered) {
+      relative_delay = std::max(iat_delay, 0);
+    } else {
+      UpdateDelayHistory(iat_delay);
+      relative_delay = CalculateRelativePacketArrivalDelay();
+    }
+    statistics_->RelativePacketArrivalDelay(relative_delay);
+
+    switch (histogram_mode_) {
+      case RELATIVE_ARRIVAL_DELAY: {
+        const int index = relative_delay / kBucketSizeMs;
+        if (index < histogram_->NumBuckets()) {
+          // Maximum delay to register is 2000 ms.
+          histogram_->Add(index);
+        }
+        break;
+      }
+      case INTER_ARRIVAL_TIME: {
+        // Saturate IAT between 0 and maximum value.
+        iat_packets =
+            std::max(std::min(iat_packets, histogram_->NumBuckets() - 1), 0);
+        histogram_->Add(iat_packets);
+        break;
+      }
+    }
     // Calculate new |target_level_| based on updated statistics.
-    target_level_ = CalculateTargetLevel(iat_packets);
+    target_level_ = CalculateTargetLevel(iat_packets, reordered);
     if (streaming_mode_) {
       target_level_ = std::max(target_level_, max_iat_cumulative_sum_);
     }
@@ -181,6 +272,12 @@
     LimitTargetLevel();
   }  // End if (packet_len_ms > 0).
 
+  if (enable_rtx_handling_ && reordered &&
+      num_reordered_packets_ < kMaxReorderedPackets) {
+    ++num_reordered_packets_;
+    return 0;
+  }
+  num_reordered_packets_ = 0;
   // Prepare for next packet arrival.
   packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   last_seq_no_ = sequence_number;
@@ -188,6 +285,26 @@
   return 0;
 }
 
+void DelayManager::UpdateDelayHistory(int iat_delay) {
+  delay_history_.push_back(iat_delay);
+  if (delay_history_.size() > kMaxHistoryPackets) {
+    delay_history_.pop_front();
+  }
+}
+
+int DelayManager::CalculateRelativePacketArrivalDelay() const {
+  // This effectively calculates arrival delay of a packet relative to the
+  // packet preceding the history window. If the arrival delay ever becomes
+  // smaller than zero, it means the reference packet is invalid, and we
+  // move the reference.
+  int relative_delay = 0;
+  for (int delay : delay_history_) {
+    relative_delay += delay;
+    relative_delay = std::max(relative_delay, 0);
+  }
+  return relative_delay;
+}
+
 void DelayManager::UpdateCumulativeSums(int packet_len_ms,
                                         uint16_t sequence_number) {
   // Calculate IAT in Q8, including fractions of a packet (i.e., more
@@ -214,69 +331,19 @@
   }
 }
 
-// Each element in the vector is first multiplied by the forgetting factor
-// |iat_factor_|. Then the vector element indicated by |iat_packets| is then
-// increased (additive) by 1 - |iat_factor_|. This way, the probability of
-// |iat_packets| is slightly increased, while the sum of the histogram remains
-// constant (=1).
-// Due to inaccuracies in the fixed-point arithmetic, the histogram may no
-// longer sum up to 1 (in Q30) after the update. To correct this, a correction
-// term is added or subtracted from the first element (or elements) of the
-// vector.
-// The forgetting factor |iat_factor_| is also updated. When the DelayManager
-// is reset, the factor is set to 0 to facilitate rapid convergence in the
-// beginning. With each update of the histogram, the factor is increased towards
-// the steady-state value |kIatFactor_|.
-void DelayManager::UpdateHistogram(size_t iat_packets) {
-  assert(iat_packets < iat_vector_.size());
-  int vector_sum = 0;  // Sum up the vector elements as they are processed.
-  // Multiply each element in |iat_vector_| with |iat_factor_|.
-  for (IATVector::iterator it = iat_vector_.begin(); it != iat_vector_.end();
-       ++it) {
-    *it = (static_cast<int64_t>(*it) * iat_factor_) >> 15;
-    vector_sum += *it;
-  }
-
-  // Increase the probability for the currently observed inter-arrival time
-  // by 1 - |iat_factor_|. The factor is in Q15, |iat_vector_| in Q30.
-  // Thus, left-shift 15 steps to obtain result in Q30.
-  iat_vector_[iat_packets] += (32768 - iat_factor_) << 15;
-  vector_sum += (32768 - iat_factor_) << 15;  // Add to vector sum.
-
-  // |iat_vector_| should sum up to 1 (in Q30), but it may not due to
-  // fixed-point rounding errors.
-  vector_sum -= 1 << 30;  // Should be zero. Compensate if not.
-  if (vector_sum != 0) {
-    // Modify a few values early in |iat_vector_|.
-    int flip_sign = vector_sum > 0 ? -1 : 1;
-    IATVector::iterator it = iat_vector_.begin();
-    while (it != iat_vector_.end() && abs(vector_sum) > 0) {
-      // Add/subtract 1/16 of the element, but not more than |vector_sum|.
-      int correction = flip_sign * std::min(abs(vector_sum), (*it) >> 4);
-      *it += correction;
-      vector_sum += correction;
-      ++it;
-    }
-  }
-  assert(vector_sum == 0);  // Verify that the above is correct.
-
-  // Update |iat_factor_| (changes only during the first seconds after a reset).
-  // The factor converges to |kIatFactor_|.
-  iat_factor_ += (kIatFactor_ - iat_factor_ + 3) >> 2;
-}
-
 // Enforces upper and lower limits for |target_level_|. The upper limit is
 // chosen to be minimum of i) 75% of |max_packets_in_buffer_|, to leave some
 // headroom for natural fluctuations around the target, and ii) equivalent of
 // |maximum_delay_ms_| in packets. Note that in practice, if no
 // |maximum_delay_ms_| is specified, this does not have any impact, since the
 // target level is far below the buffer capacity in all reasonable cases.
-// The lower limit is equivalent of |minimum_delay_ms_| in packets. We update
-// |least_required_level_| while the above limits are applied.
+// The lower limit is equivalent of |effective_minimum_delay_ms_| in packets.
+// We update |least_required_level_| while the above limits are applied.
 // TODO(hlundin): Move this check to the buffer logistics class.
 void DelayManager::LimitTargetLevel() {
-  if (packet_len_ms_ > 0 && minimum_delay_ms_ > 0) {
-    int minimum_delay_packet_q8 = (minimum_delay_ms_ << 8) / packet_len_ms_;
+  if (packet_len_ms_ > 0 && effective_minimum_delay_ms_ > 0) {
+    int minimum_delay_packet_q8 =
+        (effective_minimum_delay_ms_ << 8) / packet_len_ms_;
     target_level_ = std::max(target_level_, minimum_delay_packet_q8);
   }
 
@@ -294,40 +361,31 @@
   target_level_ = std::max(target_level_, 1 << 8);
 }
 
-int DelayManager::CalculateTargetLevel(int iat_packets) {
-  int limit_probability = forced_limit_probability_.value_or(kLimitProbability);
+int DelayManager::CalculateTargetLevel(int iat_packets, bool reordered) {
+  int limit_probability = histogram_quantile_;
   if (streaming_mode_) {
     limit_probability = kLimitProbabilityStreaming;
   }
 
-  // Calculate target buffer level from inter-arrival time histogram.
-  // Find the |iat_index| for which the probability of observing an
-  // inter-arrival time larger than or equal to |iat_index| is less than or
-  // equal to |limit_probability|. The sought probability is estimated using
-  // the histogram as the reverse cumulant PDF, i.e., the sum of elements from
-  // the end up until |iat_index|. Now, since the sum of all elements is 1
-  // (in Q30) by definition, and since the solution is often a low value for
-  // |iat_index|, it is more efficient to start with |sum| = 1 and subtract
-  // elements from the start of the histogram.
-  size_t index = 0;           // Start from the beginning of |iat_vector_|.
-  int sum = 1 << 30;          // Assign to 1 in Q30.
-  sum -= iat_vector_[index];  // Ensure that target level is >= 1.
-
-  do {
-    // Subtract the probabilities one by one until the sum is no longer greater
-    // than limit_probability.
-    ++index;
-    sum -= iat_vector_[index];
-  } while ((sum > limit_probability) && (index < iat_vector_.size() - 1));
-
-  // This is the base value for the target buffer level.
-  int target_level = static_cast<int>(index);
-  base_target_level_ = static_cast<int>(index);
-
-  // Update detector for delay peaks.
-  bool delay_peak_found = peak_detector_.Update(iat_packets, target_level);
-  if (delay_peak_found) {
-    target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
+  int bucket_index = histogram_->Quantile(limit_probability);
+  int target_level;
+  switch (histogram_mode_) {
+    case RELATIVE_ARRIVAL_DELAY: {
+      target_level = 1 + bucket_index * kBucketSizeMs / packet_len_ms_;
+      base_target_level_ = target_level;
+      break;
+    }
+    case INTER_ARRIVAL_TIME: {
+      target_level = bucket_index;
+      base_target_level_ = target_level;
+      // Update detector for delay peaks.
+      bool delay_peak_found =
+          peak_detector_.Update(iat_packets, reordered, target_level);
+      if (delay_peak_found) {
+        target_level = std::max(target_level, peak_detector_.MaxPeakHeight());
+      }
+      break;
+    }
   }
 
   // Sanity check. |target_level| must be strictly positive.
@@ -342,8 +400,10 @@
     RTC_LOG_F(LS_ERROR) << "length_ms = " << length_ms;
     return -1;
   }
-  if (frame_length_change_experiment_ && packet_len_ms_ != length_ms) {
-    iat_vector_ = ScaleHistogram(iat_vector_, packet_len_ms_, length_ms);
+  if (histogram_mode_ == INTER_ARRIVAL_TIME &&
+      frame_length_change_experiment_ && packet_len_ms_ != length_ms &&
+      packet_len_ms_ > 0) {
+    histogram_->Scale(packet_len_ms_, length_ms);
   }
 
   packet_len_ms_ = length_ms;
@@ -357,8 +417,9 @@
   packet_len_ms_ = 0;  // Packet size unknown.
   streaming_mode_ = false;
   peak_detector_.Reset();
-  ResetHistogram();  // Resets target levels too.
-  iat_factor_ = 0;   // Adapt the histogram faster for the first few packets.
+  histogram_->Reset();
+  base_target_level_ = 4;
+  target_level_ = base_target_level_ << 8;
   packet_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   max_iat_stopwatch_ = tick_timer_->GetNewStopwatch();
   iat_cumulative_sum_ = 0;
@@ -368,12 +429,14 @@
 
 double DelayManager::EstimatedClockDriftPpm() const {
   double sum = 0.0;
-  // Calculate the expected value based on the probabilities in |iat_vector_|.
-  for (size_t i = 0; i < iat_vector_.size(); ++i) {
-    sum += static_cast<double>(iat_vector_[i]) * i;
+  // Calculate the expected value based on the probabilities in
+  // |histogram_|.
+  auto buckets = histogram_->buckets();
+  for (size_t i = 0; i < buckets.size(); ++i) {
+    sum += static_cast<double>(buckets[i]) * i;
   }
-  // The probabilities in |iat_vector_| are in Q30. Divide by 1 << 30 to convert
-  // to Q0; subtract the nominal inter-arrival time (1) to make a zero
+  // The probabilities in |histogram_| are in Q30. Divide by 1 << 30 to
+  // convert to Q0; subtract the nominal inter-arrival time (1) to make a zero
   // clockdrift represent as 0; mulitply by 1000000 to produce parts-per-million
   // (ppm).
   return (sum / (1 << 30) - 1) * 1e6;
@@ -425,87 +488,53 @@
   ++last_seq_no_;
 }
 
-DelayManager::IATVector DelayManager::ScaleHistogram(const IATVector& histogram,
-                                                     int old_packet_length,
-                                                     int new_packet_length) {
-  if (old_packet_length == 0) {
-    // If we don't know the previous frame length, don't make any changes to the
-    // histogram.
-    return histogram;
-  }
-  RTC_DCHECK_GT(new_packet_length, 0);
-  RTC_DCHECK_EQ(old_packet_length % 10, 0);
-  RTC_DCHECK_EQ(new_packet_length % 10, 0);
-  IATVector new_histogram(histogram.size(), 0);
-  int64_t acc = 0;
-  int time_counter = 0;
-  size_t new_histogram_idx = 0;
-  for (size_t i = 0; i < histogram.size(); i++) {
-    acc += histogram[i];
-    time_counter += old_packet_length;
-    // The bins should be scaled, to ensure the histogram still sums to one.
-    const int64_t scaled_acc = acc * new_packet_length / time_counter;
-    int64_t actually_used_acc = 0;
-    while (time_counter >= new_packet_length) {
-      const int64_t old_histogram_val = new_histogram[new_histogram_idx];
-      new_histogram[new_histogram_idx] =
-          rtc::saturated_cast<int>(old_histogram_val + scaled_acc);
-      actually_used_acc += new_histogram[new_histogram_idx] - old_histogram_val;
-      new_histogram_idx =
-          std::min(new_histogram_idx + 1, new_histogram.size() - 1);
-      time_counter -= new_packet_length;
-    }
-    // Only subtract the part that was succesfully written to the new histogram.
-    acc -= actually_used_acc;
-  }
-  // If there is anything left in acc (due to rounding errors), add it to the
-  // last bin. If we cannot add everything to the last bin we need to add as
-  // much as possible to the bins after the last bin (this is only possible
-  // when compressing a histogram).
-  while (acc > 0 && new_histogram_idx < new_histogram.size()) {
-    const int64_t old_histogram_val = new_histogram[new_histogram_idx];
-    new_histogram[new_histogram_idx] =
-        rtc::saturated_cast<int>(old_histogram_val + acc);
-    acc -= new_histogram[new_histogram_idx] - old_histogram_val;
-    new_histogram_idx++;
-  }
-  RTC_DCHECK_EQ(histogram.size(), new_histogram.size());
-  if (acc == 0) {
-    // If acc is non-zero, we were not able to add everything to the new
-    // histogram, so this check will not hold.
-    RTC_DCHECK_EQ(accumulate(histogram.begin(), histogram.end(), 0ll),
-                  accumulate(new_histogram.begin(), new_histogram.end(), 0ll));
-  }
-  return new_histogram;
+bool DelayManager::IsValidMinimumDelay(int delay_ms) const {
+  return 0 <= delay_ms && delay_ms <= MinimumDelayUpperBound();
+}
+
+bool DelayManager::IsValidBaseMinimumDelay(int delay_ms) const {
+  return kMinBaseMinimumDelayMs <= delay_ms &&
+         delay_ms <= kMaxBaseMinimumDelayMs;
 }
 
 bool DelayManager::SetMinimumDelay(int delay_ms) {
-  // Minimum delay shouldn't be more than maximum delay, if any maximum is set.
-  // Also, if possible check |delay| to less than 75% of
-  // |max_packets_in_buffer_|.
-  if ((maximum_delay_ms_ > 0 && delay_ms > maximum_delay_ms_) ||
-      (packet_len_ms_ > 0 &&
-       delay_ms >
-           static_cast<int>(3 * max_packets_in_buffer_ * packet_len_ms_ / 4))) {
+  if (!IsValidMinimumDelay(delay_ms)) {
     return false;
   }
-  minimum_delay_ms_ = std::max(delay_ms, base_min_target_delay_ms_);
+
+  minimum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
 bool DelayManager::SetMaximumDelay(int delay_ms) {
-  if (delay_ms == 0) {
-    // Zero input unsets the maximum delay.
-    maximum_delay_ms_ = 0;
-    return true;
-  } else if (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_) {
+  // If |delay_ms| is zero then it unsets the maximum delay and target level is
+  // unconstrained by maximum delay.
+  if (delay_ms != 0 &&
+      (delay_ms < minimum_delay_ms_ || delay_ms < packet_len_ms_)) {
     // Maximum delay shouldn't be less than minimum delay or less than a packet.
     return false;
   }
+
   maximum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
   return true;
 }
 
+bool DelayManager::SetBaseMinimumDelay(int delay_ms) {
+  if (!IsValidBaseMinimumDelay(delay_ms)) {
+    return false;
+  }
+
+  base_minimum_delay_ms_ = delay_ms;
+  UpdateEffectiveMinimumDelay();
+  return true;
+}
+
+int DelayManager::GetBaseMinimumDelay() const {
+  return base_minimum_delay_ms_;
+}
+
 int DelayManager::base_target_level() const {
   return base_target_level_;
 }
@@ -519,4 +548,28 @@
 void DelayManager::set_last_pack_cng_or_dtmf(int value) {
   last_pack_cng_or_dtmf_ = value;
 }
+
+void DelayManager::UpdateEffectiveMinimumDelay() {
+  // Clamp |base_minimum_delay_ms_| into the range which can be effectively
+  // used.
+  const int base_minimum_delay_ms =
+      rtc::SafeClamp(base_minimum_delay_ms_, 0, MinimumDelayUpperBound());
+  effective_minimum_delay_ms_ =
+      std::max(minimum_delay_ms_, base_minimum_delay_ms);
+}
+
+int DelayManager::MinimumDelayUpperBound() const {
+  // Choose the lowest possible bound discarding 0 cases which mean the value
+  // is not set and unconstrained.
+  int q75 = MaxBufferTimeQ75();
+  q75 = q75 > 0 ? q75 : kMaxBaseMinimumDelayMs;
+  const int maximum_delay_ms =
+      maximum_delay_ms_ > 0 ? maximum_delay_ms_ : kMaxBaseMinimumDelayMs;
+  return std::min(maximum_delay_ms, q75);
+}
+
+int DelayManager::MaxBufferTimeQ75() const {
+  const int max_buffer_time = max_packets_in_buffer_ * packet_len_ms_;
+  return rtc::dchecked_cast<int>(3 * max_buffer_time / 4);
+}
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/delay_manager.h b/modules/audio_coding/neteq/delay_manager.h
index 2c8081b..e54e950 100644
--- a/modules/audio_coding/neteq/delay_manager.h
+++ b/modules/audio_coding/neteq/delay_manager.h
@@ -13,12 +13,14 @@
 
 #include <string.h>  // Provide access to size_t.
 
+#include <deque>
 #include <memory>
-#include <vector>
 
 #include "absl/types/optional.h"
+#include "modules/audio_coding/neteq/histogram.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -27,23 +29,35 @@
 
 class DelayManager {
  public:
-  typedef std::vector<int> IATVector;
+  enum HistogramMode {
+    INTER_ARRIVAL_TIME,
+    RELATIVE_ARRIVAL_DELAY,
+  };
+
+  DelayManager(size_t max_packets_in_buffer,
+               int base_minimum_delay_ms,
+               int histogram_quantile,
+               HistogramMode histogram_mode,
+               bool enable_rtx_handling,
+               DelayPeakDetector* peak_detector,
+               const TickTimer* tick_timer,
+               StatisticsCalculator* statistics,
+               std::unique_ptr<Histogram> histogram);
 
   // Create a DelayManager object. Notify the delay manager that the packet
   // buffer can hold no more than |max_packets_in_buffer| packets (i.e., this
   // is the number of packet slots in the buffer) and that the target delay
-  // should be greater than or equal to |base_min_target_delay_ms|. Supply a
+  // should be greater than or equal to |base_minimum_delay_ms|. Supply a
   // PeakDetector object to the DelayManager.
-  DelayManager(size_t max_packets_in_buffer,
-               int base_min_target_delay_ms,
-               DelayPeakDetector* peak_detector,
-               const TickTimer* tick_timer);
+  static std::unique_ptr<DelayManager> Create(size_t max_packets_in_buffer,
+                                              int base_minimum_delay_ms,
+                                              bool enable_rtx_handling,
+                                              DelayPeakDetector* peak_detector,
+                                              const TickTimer* tick_timer,
+                                              StatisticsCalculator* statistics);
 
   virtual ~DelayManager();
 
-  // Read the inter-arrival time histogram. Mainly for testing purposes.
-  virtual const IATVector& iat_vector() const;
-
   // Updates the delay manager with a new incoming packet, with
   // |sequence_number| and |timestamp| from the RTP header. This updates the
   // inter-arrival time histogram and other statistics, as well as the
@@ -57,7 +71,7 @@
   // Sets target_level_ (in Q8) and returns the same value. Also calculates
   // and updates base_target_level_, which is the target buffer level before
   // taking delay peaks into account.
-  virtual int CalculateTargetLevel(int iat_packets);
+  virtual int CalculateTargetLevel(int iat_packets, bool reordered);
 
   // Notifies the DelayManager of how much audio data is carried in each packet.
   // The method updates the DelayPeakDetector too, and resets the inter-arrival
@@ -101,53 +115,74 @@
   // packet will shift the sequence numbers for the following packets.
   virtual void RegisterEmptyPacket();
 
-  // Apply compression or stretching to the IAT histogram, for a change in frame
-  // size. This returns an updated histogram. This function is public for
-  // testability.
-  static IATVector ScaleHistogram(const IATVector& histogram,
-                                  int old_packet_length,
-                                  int new_packet_length);
-
   // Accessors and mutators.
   // Assuming |delay| is in valid range.
   virtual bool SetMinimumDelay(int delay_ms);
   virtual bool SetMaximumDelay(int delay_ms);
+  virtual bool SetBaseMinimumDelay(int delay_ms);
+  virtual int GetBaseMinimumDelay() const;
   virtual int base_target_level() const;
   virtual void set_streaming_mode(bool value);
   virtual int last_pack_cng_or_dtmf() const;
   virtual void set_last_pack_cng_or_dtmf(int value);
 
   // This accessor is only intended for testing purposes.
-  const absl::optional<int>& forced_limit_probability_for_test() const {
-    return forced_limit_probability_;
+  int effective_minimum_delay_ms_for_test() const {
+    return effective_minimum_delay_ms_;
   }
 
+  // This accessor is only intended for testing purposes.
+  HistogramMode histogram_mode() const { return histogram_mode_; }
+  int histogram_quantile() const { return histogram_quantile_; }
+  int histogram_forget_factor() const { return histogram_->forget_factor(); }
+
  private:
-  // Sets |iat_vector_| to the default start distribution and sets the
-  // |base_target_level_| and |target_level_| to the corresponding values.
-  void ResetHistogram();
+  // Provides value which minimum delay can't exceed based on current buffer
+  // size and given |maximum_delay_ms_|. Lower bound is a constant 0.
+  int MinimumDelayUpperBound() const;
+
+  // Provides 75% of currently possible maximum buffer size in milliseconds.
+  int MaxBufferTimeQ75() const;
+
+  // Updates |delay_history_|.
+  void UpdateDelayHistory(int iat_delay);
+
+  // Calculate relative packet arrival delay from |delay_history_|.
+  int CalculateRelativePacketArrivalDelay() const;
 
   // Updates |iat_cumulative_sum_| and |max_iat_cumulative_sum_|. (These are
   // used by the streaming mode.) This method is called by Update().
   void UpdateCumulativeSums(int packet_len_ms, uint16_t sequence_number);
 
-  // Updates the histogram |iat_vector_|. The probability for inter-arrival time
-  // equal to |iat_packets| (in integer packets) is increased slightly, while
-  // all other entries are decreased. This method is called by Update().
-  void UpdateHistogram(size_t iat_packets);
+  // Updates |effective_minimum_delay_ms_| delay based on current
+  // |minimum_delay_ms_|, |base_minimum_delay_ms_| and |maximum_delay_ms_|
+  // and buffer size.
+  void UpdateEffectiveMinimumDelay();
 
   // Makes sure that |target_level_| is not too large, taking
   // |max_packets_in_buffer_| and |extra_delay_ms_| into account. This method is
   // called by Update().
   void LimitTargetLevel();
 
+  // Makes sure that |delay_ms| is less than maximum delay, if any maximum
+  // is set. Also, if possible check |delay_ms| to be less than 75% of
+  // |max_packets_in_buffer_|.
+  bool IsValidMinimumDelay(int delay_ms) const;
+
+  bool IsValidBaseMinimumDelay(int delay_ms) const;
+
   bool first_packet_received_;
   const size_t max_packets_in_buffer_;  // Capacity of the packet buffer.
-  IATVector iat_vector_;                // Histogram of inter-arrival times.
-  int iat_factor_;  // Forgetting factor for updating the IAT histogram (Q15).
+  std::unique_ptr<Histogram> histogram_;
+  const int histogram_quantile_;
+  const HistogramMode histogram_mode_;
   const TickTimer* tick_timer_;
-  const int base_min_target_delay_ms_;  // Lower bound for target_level_ and
-                                        // minimum_delay_ms_.
+  StatisticsCalculator* statistics_;
+  int base_minimum_delay_ms_;
+  // Provides delay which is used by LimitTargetLevel as lower bound on target
+  // delay.
+  int effective_minimum_delay_ms_;
+
   // Time elapsed since last packet.
   std::unique_ptr<TickTimer::Stopwatch> packet_iat_stopwatch_;
   int base_target_level_;  // Currently preferred buffer level before peak
@@ -169,7 +204,9 @@
   DelayPeakDetector& peak_detector_;
   int last_pack_cng_or_dtmf_;
   const bool frame_length_change_experiment_;
-  const absl::optional<int> forced_limit_probability_;
+  const bool enable_rtx_handling_;
+  int num_reordered_packets_ = 0;  // Number of consecutive reordered packets.
+  std::deque<int> delay_history_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DelayManager);
 };
diff --git a/modules/audio_coding/neteq/delay_manager_unittest.cc b/modules/audio_coding/neteq/delay_manager_unittest.cc
index 6281a15..c57f074 100644
--- a/modules/audio_coding/neteq/delay_manager_unittest.cc
+++ b/modules/audio_coding/neteq/delay_manager_unittest.cc
@@ -14,25 +14,36 @@
 
 #include <math.h>
 
+#include "absl/memory/memory.h"
+#include "modules/audio_coding/neteq/histogram.h"
 #include "modules/audio_coding/neteq/mock/mock_delay_peak_detector.h"
+#include "modules/audio_coding/neteq/mock/mock_histogram.h"
+#include "modules/audio_coding/neteq/mock/mock_statistics_calculator.h"
+#include "rtc_base/checks.h"
 #include "test/field_trial.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 
 namespace webrtc {
 
+namespace {
+constexpr int kMaxNumberOfPackets = 240;
+constexpr int kMinDelayMs = 0;
+constexpr int kTimeStepMs = 10;
+constexpr int kFs = 8000;
+constexpr int kFrameSizeMs = 20;
+constexpr int kTsIncrement = kFrameSizeMs * kFs / 1000;
+constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs;
+constexpr int kDefaultHistogramQuantile = 1020054733;
+constexpr int kMaxIat = 64;
+constexpr int kForgetFactor = 32745;
+}  // namespace
+
 using ::testing::Return;
 using ::testing::_;
 
 class DelayManagerTest : public ::testing::Test {
  protected:
-  static const int kMaxNumberOfPackets = 240;
-  static const int kMinDelayMs = 0;
-  static const int kTimeStepMs = 10;
-  static const int kFs = 8000;
-  static const int kFrameSizeMs = 20;
-  static const int kTsIncrement = kFrameSizeMs * kFs / 1000;
-
   DelayManagerTest();
   virtual void SetUp();
   virtual void TearDown();
@@ -43,13 +54,22 @@
 
   std::unique_ptr<DelayManager> dm_;
   TickTimer tick_timer_;
+  MockStatisticsCalculator stats_;
   MockDelayPeakDetector detector_;
+  MockHistogram* mock_histogram_;
   uint16_t seq_no_;
   uint32_t ts_;
+  bool enable_rtx_handling_ = false;
+  bool use_mock_histogram_ = false;
+  DelayManager::HistogramMode histogram_mode_ =
+      DelayManager::HistogramMode::INTER_ARRIVAL_TIME;
 };
 
 DelayManagerTest::DelayManagerTest()
-    : dm_(nullptr), detector_(&tick_timer_), seq_no_(0x1234), ts_(0x12345678) {}
+    : dm_(nullptr),
+      detector_(&tick_timer_, false),
+      seq_no_(0x1234),
+      ts_(0x12345678) {}
 
 void DelayManagerTest::SetUp() {
   RecreateDelayManager();
@@ -57,8 +77,18 @@
 
 void DelayManagerTest::RecreateDelayManager() {
   EXPECT_CALL(detector_, Reset()).Times(1);
-  dm_.reset(new DelayManager(kMaxNumberOfPackets, kMinDelayMs, &detector_,
-                             &tick_timer_));
+  if (use_mock_histogram_) {
+    mock_histogram_ = new MockHistogram(kMaxIat, kForgetFactor);
+    std::unique_ptr<Histogram> histogram(mock_histogram_);
+    dm_ = absl::make_unique<DelayManager>(
+        kMaxNumberOfPackets, kMinDelayMs, kDefaultHistogramQuantile,
+        histogram_mode_, enable_rtx_handling_, &detector_, &tick_timer_,
+        &stats_, std::move(histogram));
+  } else {
+    dm_ = DelayManager::Create(kMaxNumberOfPackets, kMinDelayMs,
+                               enable_rtx_handling_, &detector_, &tick_timer_,
+                               &stats_);
+  }
 }
 
 void DelayManagerTest::SetPacketAudioLength(int lengt_ms) {
@@ -86,17 +116,6 @@
   // object.
 }
 
-TEST_F(DelayManagerTest, VectorInitialization) {
-  const DelayManager::IATVector& vec = dm_->iat_vector();
-  double sum = 0.0;
-  for (size_t i = 0; i < vec.size(); i++) {
-    EXPECT_NEAR(ldexp(pow(0.5, static_cast<int>(i + 1)), 30), vec[i], 65537);
-    // Tolerance 65537 in Q30 corresponds to a delta of approximately 0.00006.
-    sum += vec[i];
-  }
-  EXPECT_EQ(1 << 30, static_cast<int>(sum));  // Should be 1 in Q30.
-}
-
 TEST_F(DelayManagerTest, SetPacketAudioLength) {
   const int kLengthMs = 30;
   // Expect DelayManager to pass on the new length to the detector object.
@@ -126,7 +145,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
   EXPECT_EQ(1, dm_->base_target_level());
@@ -149,7 +168,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(2, 2)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(2, false, 2)).WillOnce(Return(false));
   InsertNextPacket();
   EXPECT_EQ(2 << 8, dm_->TargetLevel());  // In Q8.
   EXPECT_EQ(2, dm_->base_target_level());
@@ -172,7 +191,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return true to indicate that peaks are found. Let the peak height be 5.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(true));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(true));
   EXPECT_CALL(detector_, MaxPeakHeight()).WillOnce(Return(5));
   InsertNextPacket();
   EXPECT_EQ(5 << 8, dm_->TargetLevel());
@@ -194,7 +213,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   const int kExpectedTarget = 1;
   EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());  // In Q8.
@@ -216,7 +235,7 @@
   // Second packet arrival.
   // Expect detector update method to be called once with inter-arrival time
   // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
-  EXPECT_CALL(detector_, Update(kExpectedTarget, _))
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(detector_, MaxPeakHeight())
       .WillRepeatedly(Return(kExpectedTarget));
@@ -246,7 +265,7 @@
   // Second packet arrival.
   // Expect detector update method to be called once with inter-arrival time
   // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
-  EXPECT_CALL(detector_, Update(kExpectedTarget, _))
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
       .WillRepeatedly(Return(true));
   EXPECT_CALL(detector_, MaxPeakHeight())
       .WillRepeatedly(Return(kExpectedTarget));
@@ -264,6 +283,236 @@
   EXPECT_EQ(kMinDelayPackets << 8, dm_->TargetLevel());
 }
 
+TEST_F(DelayManagerTest, BaseMinimumDelayCheckValidRange) {
+  SetPacketAudioLength(kFrameSizeMs);
+
+  // Base minimum delay should be between [0, 10000] milliseconds.
+  EXPECT_FALSE(dm_->SetBaseMinimumDelay(-1));
+  EXPECT_FALSE(dm_->SetBaseMinimumDelay(10001));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), 0);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(7999));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), 7999);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMinimumDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kBaseMinimumDelayMs = 100;
+  constexpr int kMinimumDelayMs = 200;
+
+  // Base minimum delay sets lower bound on minimum. That is why when base
+  // minimum delay is lower than minimum delay we use minimum delay.
+  RTC_DCHECK_LT(kBaseMinimumDelayMs, kMinimumDelayMs);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMinimumDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kBaseMinimumDelayMs = 70;
+  constexpr int kMinimumDelayMs = 30;
+
+  // Base minimum delay sets lower bound on minimum. That is why when base
+  // minimum delay is greater than minimum delay we use base minimum delay.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanBufferSize) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kBaseMinimumDelayMs = kMaxBufferSizeMs + 1;
+  constexpr int kMinimumDelayMs = 12;
+  constexpr int kMaximumDelayMs = 20;
+  constexpr int kMaxBufferSizeMsQ75 = 3 * kMaxBufferSizeMs / 4;
+
+  EXPECT_TRUE(dm_->SetMaximumDelay(kMaximumDelayMs));
+
+  // Base minimum delay is greater than minimum delay, that is why we clamp
+  // it to current the highest possible value which is maximum delay.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaxBufferSizeMs);
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaximumDelayMs);
+  RTC_DCHECK_LT(kMaximumDelayMs, kMaxBufferSizeMsQ75);
+
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+
+  // Unset maximum value.
+  EXPECT_TRUE(dm_->SetMaximumDelay(0));
+
+  // With maximum value unset, the highest possible value now is 75% of
+  // currently possible maximum buffer size.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMaxBufferSizeMsQ75);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayGreaterThanMaximumDelay) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kMaximumDelayMs = 400;
+  constexpr int kBaseMinimumDelayMs = kMaximumDelayMs + 1;
+  constexpr int kMinimumDelayMs = 20;
+
+  // Base minimum delay is greater than minimum delay, that is why we clamp
+  // it to current the highest possible value which is kMaximumDelayMs.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaximumDelayMs);
+  RTC_DCHECK_LT(kMaximumDelayMs, kMaxBufferSizeMs);
+
+  EXPECT_TRUE(dm_->SetMaximumDelay(kMaximumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMaximumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelayLowerThanMaxSize) {
+  SetPacketAudioLength(kFrameSizeMs);
+  constexpr int kMaximumDelayMs = 400;
+  constexpr int kBaseMinimumDelayMs = kMaximumDelayMs - 1;
+  constexpr int kMinimumDelayMs = 20;
+
+  // Base minimum delay is greater than minimum delay, and lower than maximum
+  // delays that is why it is used.
+  RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs);
+  RTC_DCHECK_LT(kBaseMinimumDelayMs, kMaximumDelayMs);
+
+  EXPECT_TRUE(dm_->SetMaximumDelay(kMaximumDelayMs));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, MinimumDelayMemorization) {
+  // Check that when we increase base minimum delay to value higher than
+  // minimum delay then minimum delay is still memorized. This allows to
+  // restore effective minimum delay to memorized minimum delay value when we
+  // decrease base minimum delay.
+  SetPacketAudioLength(kFrameSizeMs);
+
+  constexpr int kBaseMinimumDelayMsLow = 10;
+  constexpr int kMinimumDelayMs = 20;
+  constexpr int kBaseMinimumDelayMsHigh = 30;
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMsLow));
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  // Minimum delay is used as it is higher than base minimum delay.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMinimumDelayMs);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMsHigh));
+  // Base minimum delay is used as it is now higher than minimum delay.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(),
+            kBaseMinimumDelayMsHigh);
+
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMsLow));
+  // Check that minimum delay is memorized and is used again.
+  EXPECT_EQ(dm_->effective_minimum_delay_ms_for_test(), kMinimumDelayMs);
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDelay) {
+  const int kExpectedTarget = 5;
+  const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget| packet. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+
+  // No limit is applied.
+  EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
+
+  constexpr int kBaseMinimumDelayPackets = kExpectedTarget + 2;
+  constexpr int kBaseMinimumDelayMs = kBaseMinimumDelayPackets * kFrameSizeMs;
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+  EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
+}
+
+TEST_F(DelayManagerTest, BaseMinimumDealyAffectTargetLevel) {
+  const int kExpectedTarget = 5;
+  const int kTimeIncrement = kExpectedTarget * kFrameSizeMs;
+  SetPacketAudioLength(kFrameSizeMs);
+  // First packet arrival.
+  InsertNextPacket();
+  // Second packet arrival.
+  // Expect detector update method to be called once with inter-arrival time
+  // equal to |kExpectedTarget|. Return true to indicate peaks found.
+  EXPECT_CALL(detector_, Update(kExpectedTarget, false, _))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(detector_, MaxPeakHeight())
+      .WillRepeatedly(Return(kExpectedTarget));
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+
+  // No limit is applied.
+  EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());
+
+  // Minimum delay is lower than base minimum delay, that is why base minimum
+  // delay is used to calculate target level.
+  constexpr int kMinimumDelayPackets = kExpectedTarget + 1;
+  constexpr int kBaseMinimumDelayPackets = kExpectedTarget + 2;
+
+  constexpr int kMinimumDelayMs = kMinimumDelayPackets * kFrameSizeMs;
+  constexpr int kBaseMinimumDelayMs = kBaseMinimumDelayPackets * kFrameSizeMs;
+
+  EXPECT_TRUE(kMinimumDelayMs < kBaseMinimumDelayMs);
+  EXPECT_TRUE(dm_->SetMinimumDelay(kMinimumDelayMs));
+  EXPECT_TRUE(dm_->SetBaseMinimumDelay(kBaseMinimumDelayMs));
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+
+  IncreaseTime(kTimeIncrement);
+  InsertNextPacket();
+  EXPECT_EQ(dm_->GetBaseMinimumDelay(), kBaseMinimumDelayMs);
+  EXPECT_EQ(kBaseMinimumDelayPackets << 8, dm_->TargetLevel());
+}
+
+TEST_F(DelayManagerTest, UpdateReorderedPacket) {
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
+
+  // Insert packet that was sent before the previous packet.
+  EXPECT_CALL(detector_, Update(_, true, _));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 1, ts_ - kFrameSizeMs, kFs));
+}
+
+TEST_F(DelayManagerTest, EnableRtxHandling) {
+  enable_rtx_handling_ = true;
+  use_mock_histogram_ = true;
+  RecreateDelayManager();
+  EXPECT_TRUE(mock_histogram_);
+
+  // Insert first packet.
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
+
+  // Insert reordered packet.
+  EXPECT_CALL(*mock_histogram_, Add(3));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 3, ts_ - 3 * kFrameSizeMs, kFs));
+
+  // Insert another reordered packet.
+  EXPECT_CALL(*mock_histogram_, Add(2));
+  EXPECT_EQ(0, dm_->Update(seq_no_ - 2, ts_ - 2 * kFrameSizeMs, kFs));
+
+  // Insert the next packet in order and verify that the inter-arrival time is
+  // estimated correctly.
+  IncreaseTime(kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(1));
+  InsertNextPacket();
+}
+
 // Tests that skipped sequence numbers (simulating empty packets) are handled
 // correctly.
 TEST_F(DelayManagerTest, EmptyPacketsReported) {
@@ -285,7 +534,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
 
   EXPECT_EQ(1 << 8, dm_->TargetLevel());  // In Q8.
@@ -309,7 +558,7 @@
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet, and (base) target level equal to 1 as well.
   // Return false to indicate no peaks found.
-  EXPECT_CALL(detector_, Update(10, 10)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(10, false, 10)).WillOnce(Return(false));
   InsertNextPacket();
 
   // Note 10 times higher target value.
@@ -337,8 +586,7 @@
   test::ScopedFieldTrials field_trial(
       "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-0/");
   RecreateDelayManager();
-  EXPECT_EQ(absl::make_optional<int>(1 << 30),
-            dm_->forced_limit_probability_for_test());
+  EXPECT_EQ(0, dm_->histogram_quantile());
 
   SetPacketAudioLength(kFrameSizeMs);
   // First packet arrival.
@@ -348,7 +596,7 @@
   // Second packet arrival.
   // Expect detector update method to be called once with inter-arrival time
   // equal to 1 packet.
-  EXPECT_CALL(detector_, Update(1, 1)).WillOnce(Return(false));
+  EXPECT_CALL(detector_, Update(1, false, 1)).WillOnce(Return(false));
   InsertNextPacket();
   constexpr int kExpectedTarget = 1;
   EXPECT_EQ(kExpectedTarget << 8, dm_->TargetLevel());  // In Q8.
@@ -359,145 +607,122 @@
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-95/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::make_optional<int>(53687091),
-              dm_->forced_limit_probability_for_test());  // 1/20 in Q30
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::make_optional<int>(536871),
-              dm_->forced_limit_probability_for_test());  // 1/2000 in Q30
+    EXPECT_EQ(1073204953, dm_->histogram_quantile());  // 0.9995 in Q30.
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Disabled/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test());
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled--1/");
-    EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test());
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
   {
     test::ScopedFieldTrials field_trial(
         "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-100.1/");
     RecreateDelayManager();
-    EXPECT_EQ(absl::nullopt, dm_->forced_limit_probability_for_test());
+    EXPECT_EQ(kDefaultHistogramQuantile, dm_->histogram_quantile());
   }
 }
 
-// Test if the histogram is stretched correctly if the packet size is decreased.
-TEST(DelayManagerIATScalingTest, StretchTest) {
-  using IATVector = DelayManager::IATVector;
-  // Test a straightforward 60ms to 20ms change.
-  IATVector iat = {12, 0, 0, 0, 0, 0};
-  IATVector expected_result = {4, 4, 4, 0, 0, 0};
-  IATVector stretched_iat = DelayManager::ScaleHistogram(iat, 60, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test an example where the last bin in the stretched histogram should
-  // contain the sum of the elements that don't fit into the new histogram.
-  iat = {18, 15, 12, 9, 6, 3, 0};
-  expected_result = {6, 6, 6, 5, 5, 5, 30};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 60, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 120ms to 60ms change.
-  iat = {18, 16, 14, 4, 0};
-  expected_result = {9, 9, 8, 8, 18};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 120, 60);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 120ms to 20ms change.
-  iat = {19, 12, 0, 0, 0, 0, 0, 0};
-  expected_result = {3, 3, 3, 3, 3, 3, 2, 11};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 120, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 70ms to 40ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
-  expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 70, 40);
-  EXPECT_EQ(stretched_iat, expected_result);
-
-  // Test a 30ms to 20ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
-  expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11};
-  stretched_iat = DelayManager::ScaleHistogram(iat, 30, 20);
-  EXPECT_EQ(stretched_iat, expected_result);
+TEST_F(DelayManagerTest, DelayHistogramFieldTrial) {
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1030792151, dm_->histogram_quantile());  // 0.96 in Q30.
+    EXPECT_EQ(32702, dm_->histogram_forget_factor());  // 0.998 in Q15.
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-97.5-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1046898278, dm_->histogram_quantile());  // 0.975 in Q30.
+    EXPECT_EQ(32702, dm_->histogram_forget_factor());  // 0.998 in Q15.
+  }
+  {
+    // NetEqDelayHistogram should take precedence over
+    // NetEqForceTargetDelayPercentile.
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqForceTargetDelayPercentile/Enabled-99.95/"
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96-0.998/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(1030792151, dm_->histogram_quantile());  // 0.96 in Q30.
+    EXPECT_EQ(32702, dm_->histogram_forget_factor());  // 0.998 in Q15.
+  }
+  {
+    // Invalid parameters.
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Enabled-96/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY,
+              dm_->histogram_mode());
+    EXPECT_EQ(kDefaultHistogramQuantile,
+              dm_->histogram_quantile());                      // 0.95 in Q30.
+    EXPECT_EQ(kForgetFactor, dm_->histogram_forget_factor());  // 0.9993 in Q15.
+  }
+  {
+    test::ScopedFieldTrials field_trial(
+        "WebRTC-Audio-NetEqDelayHistogram/Disabled/");
+    RecreateDelayManager();
+    EXPECT_EQ(DelayManager::HistogramMode::INTER_ARRIVAL_TIME,
+              dm_->histogram_mode());
+    EXPECT_EQ(kDefaultHistogramQuantile,
+              dm_->histogram_quantile());                      // 0.95 in Q30.
+    EXPECT_EQ(kForgetFactor, dm_->histogram_forget_factor());  // 0.9993 in Q15.
+  }
 }
 
-// Test if the histogram is compressed correctly if the packet size is
-// increased.
-TEST(DelayManagerIATScalingTest, CompressionTest) {
-  using IATVector = DelayManager::IATVector;
-  // Test a 20 to 60 ms change.
-  IATVector iat = {12, 11, 10, 3, 2, 1};
-  IATVector expected_result = {33, 6, 0, 0, 0, 0};
-  IATVector compressed_iat = DelayManager::ScaleHistogram(iat, 20, 60);
-  EXPECT_EQ(compressed_iat, expected_result);
+TEST_F(DelayManagerTest, RelativeArrivalDelayMode) {
+  histogram_mode_ = DelayManager::HistogramMode::RELATIVE_ARRIVAL_DELAY;
+  use_mock_histogram_ = true;
+  RecreateDelayManager();
 
-  // Test a 60ms to 120ms change.
-  iat = {18, 16, 14, 4, 1};
-  expected_result = {34, 18, 1, 0, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 60, 120);
-  EXPECT_EQ(compressed_iat, expected_result);
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
 
-  // Test a 20ms to 120ms change.
-  iat = {18, 12, 5, 4, 4, 3, 5, 1};
-  expected_result = {46, 6, 0, 0, 0, 0, 0, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 20, 120);
-  EXPECT_EQ(compressed_iat, expected_result);
+  IncreaseTime(kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(0));  // Not delayed.
+  InsertNextPacket();
 
-  // Test a 70ms to 80ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3};
-  expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 70, 80);
-  EXPECT_EQ(compressed_iat, expected_result);
+  IncreaseTime(2 * kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(1));  // 20ms delayed.
+  EXPECT_EQ(0, dm_->Update(seq_no_, ts_, kFs));
 
-  // Test a 50ms to 110ms change.
-  iat = {13, 7, 5, 3, 1, 5, 12, 11, 3};
-  expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0};
-  compressed_iat = DelayManager::ScaleHistogram(iat, 50, 110);
-  EXPECT_EQ(compressed_iat, expected_result);
+  IncreaseTime(2 * kFrameSizeMs);
+  EXPECT_CALL(*mock_histogram_, Add(2));  // 40ms delayed.
+  EXPECT_EQ(0, dm_->Update(seq_no_ + 1, ts_ + kTsIncrement, kFs));
+
+  EXPECT_CALL(*mock_histogram_, Add(1));  // Reordered, 20ms delayed.
+  EXPECT_EQ(0, dm_->Update(seq_no_, ts_, kFs));
 }
 
-// Test if the histogram scaling function handles overflows correctly.
-TEST(DelayManagerIATScalingTest, OverflowTest) {
-  using IATVector = DelayManager::IATVector;
-  // Test a compression operation that can cause overflow.
-  IATVector iat = {733544448, 0, 0, 0, 0, 0, 0, 340197376, 0, 0, 0, 0, 0, 0};
-  IATVector expected_result = {733544448, 340197376, 0, 0, 0, 0, 0,
-                               0,         0,         0, 0, 0, 0, 0};
-  IATVector scaled_iat = DelayManager::ScaleHistogram(iat, 10, 60);
-  EXPECT_EQ(scaled_iat, expected_result);
+TEST_F(DelayManagerTest, RelativeArrivalDelayStatistic) {
+  SetPacketAudioLength(kFrameSizeMs);
+  InsertNextPacket();
 
-  iat = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764,
-         114119,    2072996,  0,         2149354, 0};
-  expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0,
-                     0,          0,       0,       0,       0};
-  scaled_iat = DelayManager::ScaleHistogram(iat, 20, 60);
-  EXPECT_EQ(scaled_iat, expected_result);
+  IncreaseTime(kFrameSizeMs);
+  EXPECT_CALL(stats_, RelativePacketArrivalDelay(0));
+  InsertNextPacket();
 
-  // In this test case we will not be able to add everything to the final bin in
-  // the scaled histogram. Check that the last bin doesn't overflow.
-  iat = {2000000000, 2000000000, 2000000000,
-         2000000000, 2000000000, 2000000000};
-  expected_result = {666666666, 666666666, 666666666,
-                     666666667, 666666667, 2147483647};
-  scaled_iat = DelayManager::ScaleHistogram(iat, 60, 20);
-  EXPECT_EQ(scaled_iat, expected_result);
-
-  // In this test case we will not be able to add enough to each of the bins,
-  // so the values should be smeared out past the end of the normal range.
-  iat = {2000000000, 2000000000, 2000000000,
-         2000000000, 2000000000, 2000000000};
-  expected_result = {2147483647, 2147483647, 2147483647,
-                     2147483647, 2147483647, 1262581765};
-  scaled_iat = DelayManager::ScaleHistogram(iat, 20, 60);
-  EXPECT_EQ(scaled_iat, expected_result);
+  IncreaseTime(2 * kFrameSizeMs);
+  EXPECT_CALL(stats_, RelativePacketArrivalDelay(20));
+  InsertNextPacket();
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/delay_peak_detector.cc b/modules/audio_coding/neteq/delay_peak_detector.cc
index 893ce3e..5669d72 100644
--- a/modules/audio_coding/neteq/delay_peak_detector.cc
+++ b/modules/audio_coding/neteq/delay_peak_detector.cc
@@ -26,10 +26,12 @@
 
 DelayPeakDetector::~DelayPeakDetector() = default;
 
-DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer)
+DelayPeakDetector::DelayPeakDetector(const TickTimer* tick_timer,
+                                     bool ignore_reordered_packets)
     : peak_found_(false),
       peak_detection_threshold_(0),
       tick_timer_(tick_timer),
+      ignore_reordered_packets_(ignore_reordered_packets),
       frame_length_change_experiment_(
           field_trial::IsEnabled("WebRTC-Audio-NetEqFramelengthExperiment")) {
   RTC_DCHECK(!peak_period_stopwatch_);
@@ -79,7 +81,12 @@
   return max_period_element->period_ms;
 }
 
-bool DelayPeakDetector::Update(int inter_arrival_time, int target_level) {
+bool DelayPeakDetector::Update(int inter_arrival_time,
+                               bool reordered,
+                               int target_level) {
+  if (ignore_reordered_packets_ && reordered) {
+    return CheckPeakConditions();
+  }
   if (inter_arrival_time > target_level + peak_detection_threshold_ ||
       inter_arrival_time > 2 * target_level) {
     // A delay peak is observed.
diff --git a/modules/audio_coding/neteq/delay_peak_detector.h b/modules/audio_coding/neteq/delay_peak_detector.h
index 272d50e..8cd198d 100644
--- a/modules/audio_coding/neteq/delay_peak_detector.h
+++ b/modules/audio_coding/neteq/delay_peak_detector.h
@@ -17,13 +17,13 @@
 #include <memory>
 
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
 class DelayPeakDetector {
  public:
-  DelayPeakDetector(const TickTimer* tick_timer);
+  DelayPeakDetector(const TickTimer* tick_timer, bool ignore_reordered_packets);
   virtual ~DelayPeakDetector();
   virtual void Reset();
 
@@ -43,10 +43,11 @@
   // larger than 0), or 0 if no delay peaks have been observed recently.
   virtual uint64_t MaxPeakPeriod() const;
 
-  // Updates the DelayPeakDetector with a new inter-arrival time (in packets)
-  // and the current target buffer level (needed to decide if a peak is observed
-  // or not). Returns true if peak-mode is active, false if not.
-  virtual bool Update(int inter_arrival_time, int target_level);
+  // Updates the DelayPeakDetector with a new inter-arrival time (in packets),
+  // the current target buffer level (needed to decide if a peak is observed or
+  // not) and if the new inter-arrival time includes a compensation for
+  // reordering. Returns true if peak-mode is active, false if not.
+  virtual bool Update(int inter_arrival_time, bool reordered, int target_level);
 
  private:
   static const size_t kMaxNumPeaks = 8;
@@ -66,6 +67,7 @@
   int peak_detection_threshold_;
   const TickTimer* tick_timer_;
   std::unique_ptr<TickTimer::Stopwatch> peak_period_stopwatch_;
+  const bool ignore_reordered_packets_;
   const bool frame_length_change_experiment_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(DelayPeakDetector);
diff --git a/modules/audio_coding/neteq/delay_peak_detector_unittest.cc b/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
index fd4dded..6590dc2 100644
--- a/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
+++ b/modules/audio_coding/neteq/delay_peak_detector_unittest.cc
@@ -18,14 +18,14 @@
 
 TEST(DelayPeakDetector, CreateAndDestroy) {
   TickTimer tick_timer;
-  DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer);
+  DelayPeakDetector* detector = new DelayPeakDetector(&tick_timer, false);
   EXPECT_FALSE(detector->peak_found());
   delete detector;
 }
 
 TEST(DelayPeakDetector, EmptyHistory) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   EXPECT_EQ(-1, detector.MaxPeakHeight());
   EXPECT_EQ(0u, detector.MaxPeakPeriod());
 }
@@ -35,7 +35,7 @@
 // start. This should then continue until it is disengaged due to lack of peaks.
 TEST(DelayPeakDetector, TriggerPeakMode) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   const int kPacketSizeMs = 30;
   detector.SetPacketAudioLength(kPacketSizeMs);
 
@@ -69,9 +69,9 @@
           (arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
       const int kTargetBufferLevel = 1;  // Define peaks to be iat > 2.
       if (time < peak_mode_start_ms || time > peak_mode_end_ms) {
-        EXPECT_FALSE(detector.Update(iat_packets, kTargetBufferLevel));
+        EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
       } else {
-        EXPECT_TRUE(detector.Update(iat_packets, kTargetBufferLevel));
+        EXPECT_TRUE(detector.Update(iat_packets, false, kTargetBufferLevel));
         EXPECT_EQ(kWorstPeakPeriod, detector.MaxPeakPeriod());
         EXPECT_EQ(kPeakDelayMs / kPacketSizeMs + 1, detector.MaxPeakHeight());
       }
@@ -87,7 +87,7 @@
 // The delay pattern has peaks with delay = 3, thus should not trigger.
 TEST(DelayPeakDetector, DoNotTriggerPeakMode) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   const int kPacketSizeMs = 30;
   detector.SetPacketAudioLength(kPacketSizeMs);
 
@@ -115,7 +115,7 @@
       int iat_packets =
           (arrival_times_ms[next] - arrival_times_ms[next - 1]) / kPacketSizeMs;
       const int kTargetBufferLevel = 2;  // Define peaks to be iat > 4.
-      EXPECT_FALSE(detector.Update(iat_packets, kTargetBufferLevel));
+      EXPECT_FALSE(detector.Update(iat_packets, false, kTargetBufferLevel));
       ++next;
     }
     tick_timer.Increment();
@@ -129,15 +129,33 @@
 // problems.
 TEST(DelayPeakDetector, ZeroDistancePeaks) {
   TickTimer tick_timer;
-  DelayPeakDetector detector(&tick_timer);
+  DelayPeakDetector detector(&tick_timer, false);
   const int kPacketSizeMs = 30;
   detector.SetPacketAudioLength(kPacketSizeMs);
 
   const int kTargetBufferLevel = 2;  // Define peaks to be iat > 4.
-  const int kInterArrivalTime = 3 * kTargetBufferLevel;  // Will trigger a peak.
-  EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
-  EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
-  EXPECT_FALSE(detector.Update(kInterArrivalTime, kTargetBufferLevel));
+  const int kInterArrivalTime =
+      3 * kTargetBufferLevel;  // Above peak threshold.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  tick_timer.Increment();
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  // The following would fail if there were non-zero time between the updates.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+}
+
+TEST(DelayPeakDetector, IgnoreReorderedPacket) {
+  TickTimer tick_timer;
+  DelayPeakDetector detector(&tick_timer, true);
+
+  const int kTargetBufferLevel = 2;  // Define peaks to be iat > 4.
+  const int kInterArrivalTime =
+      3 * kTargetBufferLevel;  // Above peak threshold.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  tick_timer.Increment();
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, false, kTargetBufferLevel));
+  tick_timer.Increment();
+  // The following would fail if the packet was not reordered.
+  EXPECT_FALSE(detector.Update(kInterArrivalTime, true, kTargetBufferLevel));
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/dsp_helper.h b/modules/audio_coding/neteq/dsp_helper.h
index 8379461..82fe14e 100644
--- a/modules/audio_coding/neteq/dsp_helper.h
+++ b/modules/audio_coding/neteq/dsp_helper.h
@@ -16,7 +16,7 @@
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/audio_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dtmf_buffer.h b/modules/audio_coding/neteq/dtmf_buffer.h
index 24b14ec..a994e3a 100644
--- a/modules/audio_coding/neteq/dtmf_buffer.h
+++ b/modules/audio_coding/neteq/dtmf_buffer.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 #include <list>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/dtmf_tone_generator.h b/modules/audio_coding/neteq/dtmf_tone_generator.h
index 22e166e..968bc7f 100644
--- a/modules/audio_coding/neteq/dtmf_tone_generator.h
+++ b/modules/audio_coding/neteq/dtmf_tone_generator.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand.h b/modules/audio_coding/neteq/expand.h
index 30c34a2..7c041b8 100644
--- a/modules/audio_coding/neteq/expand.h
+++ b/modules/audio_coding/neteq/expand.h
@@ -15,7 +15,7 @@
 #include <memory>
 
 #include "modules/audio_coding/neteq/audio_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand_uma_logger.h b/modules/audio_coding/neteq/expand_uma_logger.h
index bd079c6..7cb11b1 100644
--- a/modules/audio_coding/neteq/expand_uma_logger.h
+++ b/modules/audio_coding/neteq/expand_uma_logger.h
@@ -16,7 +16,7 @@
 
 #include "absl/types/optional.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/expand_unittest.cc b/modules/audio_coding/neteq/expand_unittest.cc
index 09914da..4c8c174 100644
--- a/modules/audio_coding/neteq/expand_unittest.cc
+++ b/modules/audio_coding/neteq/expand_unittest.cc
@@ -20,7 +20,7 @@
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/histogram.cc b/modules/audio_coding/neteq/histogram.cc
new file mode 100644
index 0000000..b8e4e52
--- /dev/null
+++ b/modules/audio_coding/neteq/histogram.cc
@@ -0,0 +1,174 @@
+/*
+ *  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 <algorithm>
+#include <numeric>
+
+#include "modules/audio_coding/neteq/histogram.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+
+namespace webrtc {
+
+Histogram::Histogram(size_t num_buckets, int forget_factor)
+    : buckets_(num_buckets, 0),
+      forget_factor_(0),
+      base_forget_factor_(forget_factor) {}
+
+Histogram::~Histogram() {}
+
+// Each element in the vector is first multiplied by the forgetting factor
+// |forget_factor_|. Then the vector element indicated by |iat_packets| is then
+// increased (additive) by 1 - |forget_factor_|. This way, the probability of
+// |iat_packets| is slightly increased, while the sum of the histogram remains
+// constant (=1).
+// Due to inaccuracies in the fixed-point arithmetic, the histogram may no
+// longer sum up to 1 (in Q30) after the update. To correct this, a correction
+// term is added or subtracted from the first element (or elements) of the
+// vector.
+// The forgetting factor |forget_factor_| is also updated. When the DelayManager
+// is reset, the factor is set to 0 to facilitate rapid convergence in the
+// beginning. With each update of the histogram, the factor is increased towards
+// the steady-state value |kIatFactor_|.
+void Histogram::Add(int value) {
+  RTC_DCHECK(value >= 0);
+  RTC_DCHECK(value < static_cast<int>(buckets_.size()));
+  int vector_sum = 0;  // Sum up the vector elements as they are processed.
+  // Multiply each element in |buckets_| with |forget_factor_|.
+  for (int& bucket : buckets_) {
+    bucket = (static_cast<int64_t>(bucket) * forget_factor_) >> 15;
+    vector_sum += bucket;
+  }
+
+  // Increase the probability for the currently observed inter-arrival time
+  // by 1 - |forget_factor_|. The factor is in Q15, |buckets_| in Q30.
+  // Thus, left-shift 15 steps to obtain result in Q30.
+  buckets_[value] += (32768 - forget_factor_) << 15;
+  vector_sum += (32768 - forget_factor_) << 15;  // Add to vector sum.
+
+  // |buckets_| should sum up to 1 (in Q30), but it may not due to
+  // fixed-point rounding errors.
+  vector_sum -= 1 << 30;  // Should be zero. Compensate if not.
+  if (vector_sum != 0) {
+    // Modify a few values early in |buckets_|.
+    int flip_sign = vector_sum > 0 ? -1 : 1;
+    for (int& bucket : buckets_) {
+      // Add/subtract 1/16 of the element, but not more than |vector_sum|.
+      int correction = flip_sign * std::min(abs(vector_sum), bucket >> 4);
+      bucket += correction;
+      vector_sum += correction;
+      if (abs(vector_sum) == 0) {
+        break;
+      }
+    }
+  }
+  RTC_DCHECK(vector_sum == 0);  // Verify that the above is correct.
+
+  // Update |forget_factor_| (changes only during the first seconds after a
+  // reset). The factor converges to |base_forget_factor_|.
+  forget_factor_ += (base_forget_factor_ - forget_factor_ + 3) >> 2;
+}
+
+int Histogram::Quantile(int probability) {
+  // Find the bucket for which the probability of observing an
+  // inter-arrival time larger than or equal to |index| is larger than or
+  // equal to |probability|. The sought probability is estimated using
+  // the histogram as the reverse cumulant PDF, i.e., the sum of elements from
+  // the end up until |index|. Now, since the sum of all elements is 1
+  // (in Q30) by definition, and since the solution is often a low value for
+  // |iat_index|, it is more efficient to start with |sum| = 1 and subtract
+  // elements from the start of the histogram.
+  int inverse_probability = (1 << 30) - probability;
+  size_t index = 0;        // Start from the beginning of |buckets_|.
+  int sum = 1 << 30;       // Assign to 1 in Q30.
+  sum -= buckets_[index];  // Ensure that target level is >= 1.
+
+  do {
+    // Subtract the probabilities one by one until the sum is no longer greater
+    // than |inverse_probability|.
+    ++index;
+    sum -= buckets_[index];
+  } while ((sum > inverse_probability) && (index < buckets_.size() - 1));
+  return static_cast<int>(index);
+}
+
+// Set the histogram vector to an exponentially decaying distribution
+// buckets_[i] = 0.5^(i+1), i = 0, 1, 2, ...
+// buckets_ is in Q30.
+void Histogram::Reset() {
+  // Set temp_prob to (slightly more than) 1 in Q14. This ensures that the sum
+  // of buckets_ is 1.
+  uint16_t temp_prob = 0x4002;  // 16384 + 2 = 100000000000010 binary.
+  for (int& bucket : buckets_) {
+    temp_prob >>= 1;
+    bucket = temp_prob << 16;
+  }
+  forget_factor_ = 0;  // Adapt the histogram faster for the first few packets.
+}
+
+int Histogram::NumBuckets() const {
+  return buckets_.size();
+}
+
+void Histogram::Scale(int old_bucket_width, int new_bucket_width) {
+  buckets_ = ScaleBuckets(buckets_, old_bucket_width, new_bucket_width);
+}
+
+std::vector<int> Histogram::ScaleBuckets(const std::vector<int>& buckets,
+                                         int old_bucket_width,
+                                         int new_bucket_width) {
+  RTC_DCHECK_GT(old_bucket_width, 0);
+  RTC_DCHECK_GT(new_bucket_width, 0);
+  RTC_DCHECK_EQ(old_bucket_width % 10, 0);
+  RTC_DCHECK_EQ(new_bucket_width % 10, 0);
+  std::vector<int> new_histogram(buckets.size(), 0);
+  int64_t acc = 0;
+  int time_counter = 0;
+  size_t new_histogram_idx = 0;
+  for (size_t i = 0; i < buckets.size(); i++) {
+    acc += buckets[i];
+    time_counter += old_bucket_width;
+    // The bins should be scaled, to ensure the histogram still sums to one.
+    const int64_t scaled_acc = acc * new_bucket_width / time_counter;
+    int64_t actually_used_acc = 0;
+    while (time_counter >= new_bucket_width) {
+      const int64_t old_histogram_val = new_histogram[new_histogram_idx];
+      new_histogram[new_histogram_idx] =
+          rtc::saturated_cast<int>(old_histogram_val + scaled_acc);
+      actually_used_acc += new_histogram[new_histogram_idx] - old_histogram_val;
+      new_histogram_idx =
+          std::min(new_histogram_idx + 1, new_histogram.size() - 1);
+      time_counter -= new_bucket_width;
+    }
+    // Only subtract the part that was succesfully written to the new histogram.
+    acc -= actually_used_acc;
+  }
+  // If there is anything left in acc (due to rounding errors), add it to the
+  // last bin. If we cannot add everything to the last bin we need to add as
+  // much as possible to the bins after the last bin (this is only possible
+  // when compressing a histogram).
+  while (acc > 0 && new_histogram_idx < new_histogram.size()) {
+    const int64_t old_histogram_val = new_histogram[new_histogram_idx];
+    new_histogram[new_histogram_idx] =
+        rtc::saturated_cast<int>(old_histogram_val + acc);
+    acc -= new_histogram[new_histogram_idx] - old_histogram_val;
+    new_histogram_idx++;
+  }
+  RTC_DCHECK_EQ(buckets.size(), new_histogram.size());
+  if (acc == 0) {
+    // If acc is non-zero, we were not able to add everything to the new
+    // histogram, so this check will not hold.
+    RTC_DCHECK_EQ(accumulate(buckets.begin(), buckets.end(), 0ll),
+                  accumulate(new_histogram.begin(), new_histogram.end(), 0ll));
+  }
+  return new_histogram;
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/histogram.h b/modules/audio_coding/neteq/histogram.h
new file mode 100644
index 0000000..fc8f612
--- /dev/null
+++ b/modules/audio_coding/neteq/histogram.h
@@ -0,0 +1,61 @@
+/*
+ *  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.
+ */
+
+#ifndef MODULES_AUDIO_CODING_NETEQ_HISTOGRAM_H_
+#define MODULES_AUDIO_CODING_NETEQ_HISTOGRAM_H_
+
+#include <string.h>  // Provide access to size_t.
+
+#include <vector>
+
+namespace webrtc {
+
+class Histogram {
+ public:
+  // Creates histogram with capacity |num_buckets| and |forget_factor| in Q15.
+  Histogram(size_t num_buckets, int forget_factor);
+
+  virtual ~Histogram();
+
+  // Resets the histogram to the default start distribution.
+  virtual void Reset();
+
+  // Add entry in bucket |index|.
+  virtual void Add(int index);
+
+  // Calculates the quantile at |probability| (in Q30) of the histogram
+  // distribution.
+  virtual int Quantile(int probability);
+
+  // Apply compression or stretching to the histogram.
+  virtual void Scale(int old_bucket_width, int new_bucket_width);
+
+  // Returns the number of buckets in the histogram.
+  virtual int NumBuckets() const;
+
+  // Returns the probability for each bucket in Q30.
+  std::vector<int> buckets() const { return buckets_; }
+
+  int forget_factor() const { return base_forget_factor_; }
+
+  // Made public for testing.
+  static std::vector<int> ScaleBuckets(const std::vector<int>& buckets,
+                                       int old_bucket_width,
+                                       int new_bucket_width);
+
+ private:
+  std::vector<int> buckets_;
+  int forget_factor_;  // Q15
+  const int base_forget_factor_;
+};
+
+}  // namespace webrtc
+
+#endif  // MODULES_AUDIO_CODING_NETEQ_HISTOGRAM_H_
diff --git a/modules/audio_coding/neteq/histogram_unittest.cc b/modules/audio_coding/neteq/histogram_unittest.cc
new file mode 100644
index 0000000..7a887c8
--- /dev/null
+++ b/modules/audio_coding/neteq/histogram_unittest.cc
@@ -0,0 +1,171 @@
+/*
+ *  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 <cmath>
+
+#include "modules/audio_coding/neteq/histogram.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+TEST(HistogramTest, Initialization) {
+  Histogram histogram(65, 32440);
+  histogram.Reset();
+  const auto& buckets = histogram.buckets();
+  double sum = 0.0;
+  for (size_t i = 0; i < buckets.size(); i++) {
+    EXPECT_NEAR(ldexp(std::pow(0.5, static_cast<int>(i + 1)), 30), buckets[i],
+                65537);
+    // Tolerance 65537 in Q30 corresponds to a delta of approximately 0.00006.
+    sum += buckets[i];
+  }
+  EXPECT_EQ(1 << 30, static_cast<int>(sum));  // Should be 1 in Q30.
+}
+
+TEST(HistogramTest, Add) {
+  Histogram histogram(10, 32440);
+  histogram.Reset();
+  const std::vector<int> before = histogram.buckets();
+  const int index = 5;
+  histogram.Add(index);
+  const std::vector<int> after = histogram.buckets();
+  EXPECT_GT(after[index], before[index]);
+  int sum = 0;
+  for (int bucket : after) {
+    sum += bucket;
+  }
+  EXPECT_EQ(1 << 30, sum);
+}
+
+TEST(HistogramTest, ForgetFactor) {
+  Histogram histogram(10, 32440);
+  histogram.Reset();
+  const std::vector<int> before = histogram.buckets();
+  const int index = 4;
+  histogram.Add(index);
+  const std::vector<int> after = histogram.buckets();
+  for (int i = 0; i < histogram.NumBuckets(); ++i) {
+    if (i != index) {
+      EXPECT_LT(after[i], before[i]);
+    }
+  }
+}
+
+// Test if the histogram is scaled correctly if the bucket width is decreased.
+TEST(HistogramTest, DownScale) {
+  // Test a straightforward 60 to 20 change.
+  std::vector<int> buckets = {12, 0, 0, 0, 0, 0};
+  std::vector<int> expected_result = {4, 4, 4, 0, 0, 0};
+  std::vector<int> stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test an example where the last bin in the stretched histogram should
+  // contain the sum of the elements that don't fit into the new histogram.
+  buckets = {18, 15, 12, 9, 6, 3, 0};
+  expected_result = {6, 6, 6, 5, 5, 5, 30};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 120 to 60 change.
+  buckets = {18, 16, 14, 4, 0};
+  expected_result = {9, 9, 8, 8, 18};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 60);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 120 to 20 change.
+  buckets = {19, 12, 0, 0, 0, 0, 0, 0};
+  expected_result = {3, 3, 3, 3, 3, 3, 2, 11};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 120, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 70 to 40 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
+  expected_result = {7, 5, 5, 3, 3, 2, 2, 1, 2, 2, 6, 22};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 70, 40);
+  EXPECT_EQ(stretched_buckets, expected_result);
+
+  // Test a 30 to 20 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3, 0, 0, 0};
+  expected_result = {8, 6, 6, 3, 2, 2, 1, 3, 3, 8, 7, 11};
+  stretched_buckets = Histogram::ScaleBuckets(buckets, 30, 20);
+  EXPECT_EQ(stretched_buckets, expected_result);
+}
+
+// Test if the histogram is scaled correctly if the bucket width is increased.
+TEST(HistogramTest, UpScale) {
+  // Test a 20 to 60 change.
+  std::vector<int> buckets = {12, 11, 10, 3, 2, 1};
+  std::vector<int> expected_result = {33, 6, 0, 0, 0, 0};
+  std::vector<int> compressed_buckets =
+      Histogram::ScaleBuckets(buckets, 20, 60);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 60 to 120 change.
+  buckets = {18, 16, 14, 4, 1};
+  expected_result = {34, 18, 1, 0, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 60, 120);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 20 to 120 change.
+  buckets = {18, 12, 5, 4, 4, 3, 5, 1};
+  expected_result = {46, 6, 0, 0, 0, 0, 0, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 20, 120);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 70 to 80 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
+  expected_result = {11, 8, 6, 2, 5, 12, 13, 3, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 70, 80);
+  EXPECT_EQ(compressed_buckets, expected_result);
+
+  // Test a 50 to 110 change.
+  buckets = {13, 7, 5, 3, 1, 5, 12, 11, 3};
+  expected_result = {18, 8, 16, 16, 2, 0, 0, 0, 0};
+  compressed_buckets = Histogram::ScaleBuckets(buckets, 50, 110);
+  EXPECT_EQ(compressed_buckets, expected_result);
+}
+
+// Test if the histogram scaling function handles overflows correctly.
+TEST(HistogramTest, OverflowTest) {
+  // Test a upscale operation that can cause overflow.
+  std::vector<int> buckets = {733544448, 0, 0, 0, 0, 0, 0,
+                              340197376, 0, 0, 0, 0, 0, 0};
+  std::vector<int> expected_result = {733544448, 340197376, 0, 0, 0, 0, 0,
+                                      0,         0,         0, 0, 0, 0, 0};
+  std::vector<int> scaled_buckets = Histogram::ScaleBuckets(buckets, 10, 60);
+  EXPECT_EQ(scaled_buckets, expected_result);
+
+  buckets = {655591163, 39962288, 360736736, 1930514, 4003853, 1782764,
+             114119,    2072996,  0,         2149354, 0};
+  expected_result = {1056290187, 7717131, 2187115, 2149354, 0, 0,
+                     0,          0,       0,       0,       0};
+  scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
+  EXPECT_EQ(scaled_buckets, expected_result);
+
+  // In this test case we will not be able to add everything to the final bin in
+  // the scaled histogram. Check that the last bin doesn't overflow.
+  buckets = {2000000000, 2000000000, 2000000000,
+             2000000000, 2000000000, 2000000000};
+  expected_result = {666666666, 666666666, 666666666,
+                     666666667, 666666667, 2147483647};
+  scaled_buckets = Histogram::ScaleBuckets(buckets, 60, 20);
+  EXPECT_EQ(scaled_buckets, expected_result);
+
+  // In this test case we will not be able to add enough to each of the bins,
+  // so the values should be smeared out past the end of the normal range.
+  buckets = {2000000000, 2000000000, 2000000000,
+             2000000000, 2000000000, 2000000000};
+  expected_result = {2147483647, 2147483647, 2147483647,
+                     2147483647, 2147483647, 1262581765};
+  scaled_buckets = Histogram::ScaleBuckets(buckets, 20, 60);
+  EXPECT_EQ(scaled_buckets, expected_result);
+}
+
+}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/include/neteq.h b/modules/audio_coding/neteq/include/neteq.h
index 2820fd8..549d355 100644
--- a/modules/audio_coding/neteq/include/neteq.h
+++ b/modules/audio_coding/neteq/include/neteq.h
@@ -13,18 +13,18 @@
 
 #include <string.h>  // Provide access to size_t.
 
+#include <map>
 #include <string>
 #include <vector>
 
 #include "absl/types/optional.h"
 #include "api/audio_codecs/audio_codec_pair_id.h"
 #include "api/audio_codecs/audio_decoder.h"
+#include "api/audio_codecs/audio_format.h"
 #include "api/rtp_headers.h"
-#include "common_types.h"  // NOLINT(build/include)
+#include "api/scoped_refptr.h"
 #include "modules/audio_coding/neteq/defines.h"
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/scoped_ref_ptr.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -70,9 +70,19 @@
   uint64_t concealed_samples = 0;
   uint64_t concealment_events = 0;
   uint64_t jitter_buffer_delay_ms = 0;
-  // Below stat is not part of the spec.
+  uint64_t jitter_buffer_emitted_count = 0;
+  // Below stats are not part of the spec.
   uint64_t voice_concealed_samples = 0;
   uint64_t delayed_packet_outage_samples = 0;
+  // This is sum of relative packet arrival delays of received packets so far.
+  // Since end-to-end delay of a packet is difficult to measure and is not
+  // necessarily useful for measuring jitter buffer performance, we report a
+  // relative packet arrival delay. The relative packet arrival delay of a
+  // packet is defined as the arrival delay compared to the first packet
+  // received, given that it had zero delay. To avoid clock drift, the "first"
+  // packet can be made dynamic.
+  uint64_t relative_packet_arrival_delay_ms = 0;
+  uint64_t jitter_buffer_packets_received = 0;
 };
 
 // Metrics that describe the operations performed in NetEq, and the internal
@@ -85,6 +95,8 @@
   uint64_t accelerate_samples = 0;
   // Count of the number of buffer flushes.
   uint64_t packet_buffer_flushes = 0;
+  // The number of primary packets that were discarded.
+  uint64_t discarded_primary_packets = 0;
   // The statistics below are not cumulative.
   // The waiting time of the last decoded packet.
   uint64_t last_waiting_time_ms = 0;
@@ -111,11 +123,12 @@
 
     int sample_rate_hz = 16000;  // Initial value. Will change with input data.
     bool enable_post_decode_vad = false;
-    size_t max_packets_in_buffer = 50;
-    int max_delay_ms = 2000;
+    size_t max_packets_in_buffer = 200;
+    int max_delay_ms = 0;
     int min_delay_ms = 0;
     bool enable_fast_accelerate = false;
     bool enable_muted_state = false;
+    bool enable_rtx_handling = false;
     absl::optional<AudioCodecPairId> codec_pair_id;
     bool for_test_no_time_stretching = false;  // Use only for testing.
   };
@@ -165,25 +178,6 @@
   // Replaces the current set of decoders with the given one.
   virtual void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) = 0;
 
-  // Associates |rtp_payload_type| with |codec| and |codec_name|, and stores the
-  // information in the codec database. Returns 0 on success, -1 on failure.
-  // The name is only used to provide information back to the caller about the
-  // decoders. Hence, the name is arbitrary, and may be empty.
-  virtual int RegisterPayloadType(NetEqDecoder codec,
-                                  const std::string& codec_name,
-                                  uint8_t rtp_payload_type) = 0;
-
-  // Provides an externally created decoder object |decoder| to insert in the
-  // decoder database. The decoder implements a decoder of type |codec| and
-  // associates it with |rtp_payload_type| and |codec_name|. Returns kOK on
-  // success, kFail on failure. The name is only used to provide information
-  // back to the caller about the decoders. Hence, the name is arbitrary, and
-  // may be empty.
-  virtual int RegisterExternalDecoder(AudioDecoder* decoder,
-                                      NetEqDecoder codec,
-                                      const std::string& codec_name,
-                                      uint8_t rtp_payload_type) = 0;
-
   // Associates |rtp_payload_type| with the given codec, which NetEq will
   // instantiate when it needs it. Returns true iff successful.
   virtual bool RegisterPayloadType(int rtp_payload_type,
@@ -209,13 +203,20 @@
   // the |max_delay_ms| value in the NetEq::Config struct.
   virtual bool SetMaximumDelay(int delay_ms) = 0;
 
+  // Sets a base minimum delay in milliseconds for packet buffer. The minimum
+  // delay which is set via |SetMinimumDelay| can't be lower than base minimum
+  // delay. Calling this method is similar to setting the |min_delay_ms| value
+  // in the NetEq::Config struct. Returns true if the base minimum is
+  // successfully applied, otherwise false is returned.
+  virtual bool SetBaseMinimumDelayMs(int delay_ms) = 0;
+
+  // Returns current value of base minimum delay in milliseconds.
+  virtual int GetBaseMinimumDelayMs() const = 0;
+
   // Returns the current target delay in ms. This includes any extra delay
   // requested through SetMinimumDelay.
   virtual int TargetDelayMs() const = 0;
 
-  // Returns the current total delay (packet buffer and sync buffer) in ms.
-  virtual int CurrentDelayMs() const = 0;
-
   // Returns the current total delay (packet buffer and sync buffer) in ms,
   // with smoothing applied to even out short-time fluctuations due to jitter.
   // The packet buffer part of the delay is not updated during DTX/CNG periods.
@@ -249,11 +250,7 @@
   // (Config::sample_rate_hz) is returned.
   virtual int last_output_sample_rate_hz() const = 0;
 
-  // Returns info about the decoder for the given payload type, or an empty
-  // value if we have no decoder for that payload type.
-  virtual absl::optional<CodecInst> GetDecoder(int payload_type) const = 0;
-
-  // Returns the decoder format for the given payload type. Returns empty if no
+  // Returns the decoder info for the given payload type. Returns empty if no
   // such payload type was registered.
   virtual absl::optional<SdpAudioFormat> GetDecoderFormat(
       int payload_type) const = 0;
diff --git a/modules/audio_coding/neteq/merge.h b/modules/audio_coding/neteq/merge.h
index e7e0bf9..a062a95 100644
--- a/modules/audio_coding/neteq/merge.h
+++ b/modules/audio_coding/neteq/merge.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_MERGE_H_
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/mock/mock_decoder_database.h b/modules/audio_coding/neteq/mock/mock_decoder_database.h
index b1d8151..d1db213 100644
--- a/modules/audio_coding/neteq/mock/mock_decoder_database.h
+++ b/modules/audio_coding/neteq/mock/mock_decoder_database.h
@@ -29,17 +29,8 @@
   MOCK_CONST_METHOD0(Empty, bool());
   MOCK_CONST_METHOD0(Size, int());
   MOCK_METHOD0(Reset, void());
-  MOCK_METHOD3(RegisterPayload,
-               int(uint8_t rtp_payload_type,
-                   NetEqDecoder codec_type,
-                   const std::string& name));
   MOCK_METHOD2(RegisterPayload,
                int(int rtp_payload_type, const SdpAudioFormat& audio_format));
-  MOCK_METHOD4(InsertExternal,
-               int(uint8_t rtp_payload_type,
-                   NetEqDecoder codec_type,
-                   const std::string& codec_name,
-                   AudioDecoder* decoder));
   MOCK_METHOD1(Remove, int(uint8_t rtp_payload_type));
   MOCK_METHOD0(RemoveAll, void());
   MOCK_CONST_METHOD1(GetDecoderInfo,
diff --git a/modules/audio_coding/neteq/mock/mock_delay_manager.h b/modules/audio_coding/neteq/mock/mock_delay_manager.h
index 206cea7..3a128ce 100644
--- a/modules/audio_coding/neteq/mock/mock_delay_manager.h
+++ b/modules/audio_coding/neteq/mock/mock_delay_manager.h
@@ -11,8 +11,11 @@
 #ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_MANAGER_H_
 #define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_DELAY_MANAGER_H_
 
-#include "modules/audio_coding/neteq/delay_manager.h"
+#include <algorithm>
 
+#include "modules/audio_coding/neteq/delay_manager.h"
+#include "modules/audio_coding/neteq/histogram.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "test/gmock.h"
 
 namespace webrtc {
@@ -21,26 +24,37 @@
  public:
   MockDelayManager(size_t max_packets_in_buffer,
                    int base_min_target_delay_ms,
+                   int histogram_quantile,
+                   HistogramMode histogram_mode,
+                   bool enable_rtx_handling,
                    DelayPeakDetector* peak_detector,
-                   const TickTimer* tick_timer)
+                   const TickTimer* tick_timer,
+                   StatisticsCalculator* stats,
+                   std::unique_ptr<Histogram> histogram)
       : DelayManager(max_packets_in_buffer,
                      base_min_target_delay_ms,
+                     histogram_quantile,
+                     histogram_mode,
+                     enable_rtx_handling,
                      peak_detector,
-                     tick_timer) {}
+                     tick_timer,
+                     stats,
+                     std::move(histogram)) {}
   virtual ~MockDelayManager() { Die(); }
   MOCK_METHOD0(Die, void());
-  MOCK_CONST_METHOD0(iat_vector, const IATVector&());
   MOCK_METHOD3(Update,
                int(uint16_t sequence_number,
                    uint32_t timestamp,
                    int sample_rate_hz));
-  MOCK_METHOD1(CalculateTargetLevel, int(int iat_packets));
+  MOCK_METHOD2(CalculateTargetLevel, int(int iat_packets, bool reordered));
   MOCK_METHOD1(SetPacketAudioLength, int(int length_ms));
   MOCK_METHOD0(Reset, void());
   MOCK_CONST_METHOD0(PeakFound, bool());
   MOCK_METHOD1(UpdateCounters, void(int elapsed_time_ms));
   MOCK_METHOD0(ResetPacketIatCount, void());
   MOCK_CONST_METHOD2(BufferLimits, void(int* lower_limit, int* higher_limit));
+  MOCK_METHOD1(SetBaseMinimumDelay, bool(int delay_ms));
+  MOCK_CONST_METHOD0(GetBaseMinimumDelay, int());
   MOCK_CONST_METHOD0(TargetLevel, int());
   MOCK_METHOD0(RegisterEmptyPacket, void());
   MOCK_METHOD1(set_extra_delay_ms, void(int16_t delay));
diff --git a/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h b/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
index f6cdea0..f7f0465 100644
--- a/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
+++ b/modules/audio_coding/neteq/mock/mock_delay_peak_detector.h
@@ -19,8 +19,9 @@
 
 class MockDelayPeakDetector : public DelayPeakDetector {
  public:
-  MockDelayPeakDetector(const TickTimer* tick_timer)
-      : DelayPeakDetector(tick_timer) {}
+  MockDelayPeakDetector(const TickTimer* tick_timer,
+                        bool ignore_reordered_packets)
+      : DelayPeakDetector(tick_timer, ignore_reordered_packets) {}
   virtual ~MockDelayPeakDetector() { Die(); }
   MOCK_METHOD0(Die, void());
   MOCK_METHOD0(Reset, void());
@@ -28,7 +29,8 @@
   MOCK_METHOD0(peak_found, bool());
   MOCK_CONST_METHOD0(MaxPeakHeight, int());
   MOCK_CONST_METHOD0(MaxPeakPeriod, uint64_t());
-  MOCK_METHOD2(Update, bool(int inter_arrival_time, int target_level));
+  MOCK_METHOD3(Update,
+               bool(int inter_arrival_time, bool reordered, int target_level));
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h b/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
deleted file mode 100644
index 1fb3db5..0000000
--- a/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- *  Copyright (c) 2013 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_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
-#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
-
-#include "api/audio_codecs/audio_decoder.h"
-#include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
-#include "rtc_base/constructormagic.h"
-#include "test/gmock.h"
-
-namespace webrtc {
-
-using ::testing::_;
-using ::testing::Invoke;
-
-// Implement an external version of the PCM16b decoder.
-class ExternalPcm16B : public AudioDecoder {
- public:
-  explicit ExternalPcm16B(int sample_rate_hz)
-      : sample_rate_hz_(sample_rate_hz) {}
-  void Reset() override {}
-
-  int DecodeInternal(const uint8_t* encoded,
-                     size_t encoded_len,
-                     int sample_rate_hz,
-                     int16_t* decoded,
-                     SpeechType* speech_type) override {
-    EXPECT_EQ(sample_rate_hz_, sample_rate_hz);
-    size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len, decoded);
-    *speech_type = ConvertSpeechType(1);
-    return static_cast<int>(ret);
-  }
-  int SampleRateHz() const override { return sample_rate_hz_; }
-  size_t Channels() const override { return 1; }
-
- private:
-  const int sample_rate_hz_;
-  RTC_DISALLOW_COPY_AND_ASSIGN(ExternalPcm16B);
-};
-
-// Create a mock of ExternalPcm16B which delegates all calls to the real object.
-// The reason is that we can then track that the correct calls are being made.
-class MockExternalPcm16B : public AudioDecoder {
- public:
-  explicit MockExternalPcm16B(int sample_rate_hz) : real_(sample_rate_hz) {
-    // By default, all calls are delegated to the real object.
-    ON_CALL(*this, DecodeInternal(_, _, _, _, _))
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodeInternal));
-    ON_CALL(*this, HasDecodePlc())
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::HasDecodePlc));
-    ON_CALL(*this, DecodePlc(_, _))
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodePlc));
-    ON_CALL(*this, Reset())
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::Reset));
-    ON_CALL(*this, IncomingPacket(_, _, _, _, _))
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::IncomingPacket));
-    ON_CALL(*this, ErrorCode())
-        .WillByDefault(Invoke(&real_, &ExternalPcm16B::ErrorCode));
-  }
-  virtual ~MockExternalPcm16B() { Die(); }
-
-  MOCK_METHOD0(Die, void());
-  MOCK_METHOD5(DecodeInternal,
-               int(const uint8_t* encoded,
-                   size_t encoded_len,
-                   int sample_rate_hz,
-                   int16_t* decoded,
-                   SpeechType* speech_type));
-  MOCK_CONST_METHOD0(HasDecodePlc, bool());
-  MOCK_METHOD2(DecodePlc, size_t(size_t num_frames, int16_t* decoded));
-  MOCK_METHOD0(Reset, void());
-  MOCK_METHOD5(IncomingPacket,
-               int(const uint8_t* payload,
-                   size_t payload_len,
-                   uint16_t rtp_sequence_number,
-                   uint32_t rtp_timestamp,
-                   uint32_t arrival_timestamp));
-  MOCK_METHOD0(ErrorCode, int());
-
-  int SampleRateHz() const /* override */ { return real_.SampleRateHz(); }
-  size_t Channels() const /* override */ { return real_.Channels(); }
-
- private:
-  ExternalPcm16B real_;
-};
-
-}  // namespace webrtc
-#endif  // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_EXTERNAL_DECODER_PCM16B_H_
diff --git a/modules/audio_coding/neteq/mock/mock_histogram.h b/modules/audio_coding/neteq/mock/mock_histogram.h
new file mode 100644
index 0000000..09b1b89
--- /dev/null
+++ b/modules/audio_coding/neteq/mock/mock_histogram.h
@@ -0,0 +1,31 @@
+/*
+ *  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.
+ */
+
+#ifndef MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_HISTOGRAM_H_
+#define MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_HISTOGRAM_H_
+
+#include "modules/audio_coding/neteq/histogram.h"
+
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockHistogram : public Histogram {
+ public:
+  MockHistogram(size_t num_buckets, int forget_factor)
+      : Histogram(num_buckets, forget_factor) {}
+  virtual ~MockHistogram() {}
+
+  MOCK_METHOD1(Add, void(int));
+  MOCK_METHOD1(Quantile, int(int));
+};
+
+}  // namespace webrtc
+#endif  // MODULES_AUDIO_CODING_NETEQ_MOCK_MOCK_HISTOGRAM_H_
diff --git a/modules/audio_coding/neteq/mock/mock_statistics_calculator.h b/modules/audio_coding/neteq/mock/mock_statistics_calculator.h
index 85f2620..aedb1df 100644
--- a/modules/audio_coding/neteq/mock/mock_statistics_calculator.h
+++ b/modules/audio_coding/neteq/mock/mock_statistics_calculator.h
@@ -21,6 +21,7 @@
  public:
   MOCK_METHOD1(PacketsDiscarded, void(size_t num_packets));
   MOCK_METHOD1(SecondaryPacketsDiscarded, void(size_t num_packets));
+  MOCK_METHOD1(RelativePacketArrivalDelay, void(size_t delay_ms));
 };
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq.cc b/modules/audio_coding/neteq/neteq.cc
index 0e6147e..a84c942 100644
--- a/modules/audio_coding/neteq/neteq.cc
+++ b/modules/audio_coding/neteq/neteq.cc
@@ -28,9 +28,10 @@
   ss << "sample_rate_hz=" << sample_rate_hz << ", enable_post_decode_vad="
      << (enable_post_decode_vad ? "true" : "false")
      << ", max_packets_in_buffer=" << max_packets_in_buffer
-     << ", enable_fast_accelerate="
-     << (enable_fast_accelerate ? " true" : "false")
-     << ", enable_muted_state=" << (enable_muted_state ? " true" : "false");
+     << ", min_delay_ms=" << min_delay_ms << ", enable_fast_accelerate="
+     << (enable_fast_accelerate ? "true" : "false")
+     << ", enable_muted_state=" << (enable_muted_state ? "true" : "false")
+     << ", enable_rtx_handling=" << (enable_rtx_handling ? "true" : "false");
   return ss.str();
 }
 
diff --git a/modules/audio_coding/neteq/neteq_decoder_enum.cc b/modules/audio_coding/neteq/neteq_decoder_enum.cc
deleted file mode 100644
index e3b633e..0000000
--- a/modules/audio_coding/neteq/neteq_decoder_enum.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *  Copyright (c) 2017 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 <map>
-#include <string>
-
-#include "modules/audio_coding/neteq/neteq_decoder_enum.h"
-
-namespace webrtc {
-
-absl::optional<SdpAudioFormat> NetEqDecoderToSdpAudioFormat(NetEqDecoder nd) {
-  switch (nd) {
-    case NetEqDecoder::kDecoderPCMu:
-      return SdpAudioFormat("pcmu", 8000, 1);
-    case NetEqDecoder::kDecoderPCMa:
-      return SdpAudioFormat("pcma", 8000, 1);
-    case NetEqDecoder::kDecoderPCMu_2ch:
-      return SdpAudioFormat("pcmu", 8000, 2);
-    case NetEqDecoder::kDecoderPCMa_2ch:
-      return SdpAudioFormat("pcma", 8000, 2);
-    case NetEqDecoder::kDecoderILBC:
-      return SdpAudioFormat("ilbc", 8000, 1);
-    case NetEqDecoder::kDecoderISAC:
-      return SdpAudioFormat("isac", 16000, 1);
-    case NetEqDecoder::kDecoderISACswb:
-      return SdpAudioFormat("isac", 32000, 1);
-    case NetEqDecoder::kDecoderPCM16B:
-      return SdpAudioFormat("l16", 8000, 1);
-    case NetEqDecoder::kDecoderPCM16Bwb:
-      return SdpAudioFormat("l16", 16000, 1);
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz:
-      return SdpAudioFormat("l16", 32000, 1);
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz:
-      return SdpAudioFormat("l16", 48000, 1);
-    case NetEqDecoder::kDecoderPCM16B_2ch:
-      return SdpAudioFormat("l16", 8000, 2);
-    case NetEqDecoder::kDecoderPCM16Bwb_2ch:
-      return SdpAudioFormat("l16", 16000, 2);
-    case NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch:
-      return SdpAudioFormat("l16", 32000, 2);
-    case NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch:
-      return SdpAudioFormat("l16", 48000, 2);
-    case NetEqDecoder::kDecoderPCM16B_5ch:
-      return SdpAudioFormat("l16", 8000, 5);
-    case NetEqDecoder::kDecoderG722:
-      return SdpAudioFormat("g722", 8000, 1);
-    case NetEqDecoder::kDecoderG722_2ch:
-      return SdpAudioFormat("g722", 8000, 2);
-    case NetEqDecoder::kDecoderOpus:
-      return SdpAudioFormat("opus", 48000, 2);
-    case NetEqDecoder::kDecoderOpus_2ch:
-      return SdpAudioFormat(
-          "opus", 48000, 2,
-          std::map<std::string, std::string>{{"stereo", "1"}});
-    case NetEqDecoder::kDecoderRED:
-      return SdpAudioFormat("red", 8000, 1);
-    case NetEqDecoder::kDecoderAVT:
-      return SdpAudioFormat("telephone-event", 8000, 1);
-    case NetEqDecoder::kDecoderAVT16kHz:
-      return SdpAudioFormat("telephone-event", 16000, 1);
-    case NetEqDecoder::kDecoderAVT32kHz:
-      return SdpAudioFormat("telephone-event", 32000, 1);
-    case NetEqDecoder::kDecoderAVT48kHz:
-      return SdpAudioFormat("telephone-event", 48000, 1);
-    case NetEqDecoder::kDecoderCNGnb:
-      return SdpAudioFormat("cn", 8000, 1);
-    case NetEqDecoder::kDecoderCNGwb:
-      return SdpAudioFormat("cn", 16000, 1);
-    case NetEqDecoder::kDecoderCNGswb32kHz:
-      return SdpAudioFormat("cn", 32000, 1);
-    case NetEqDecoder::kDecoderCNGswb48kHz:
-      return SdpAudioFormat("cn", 48000, 1);
-    default:
-      return absl::nullopt;
-  }
-}
-
-}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq_decoder_enum.h b/modules/audio_coding/neteq/neteq_decoder_enum.h
deleted file mode 100644
index 00629bc..0000000
--- a/modules/audio_coding/neteq/neteq_decoder_enum.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Copyright (c) 2017 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_CODING_NETEQ_NETEQ_DECODER_ENUM_H_
-#define MODULES_AUDIO_CODING_NETEQ_NETEQ_DECODER_ENUM_H_
-
-#include "absl/types/optional.h"
-#include "api/audio_codecs/audio_format.h"
-
-namespace webrtc {
-
-enum class NetEqDecoder {
-  kDecoderPCMu,
-  kDecoderPCMa,
-  kDecoderPCMu_2ch,
-  kDecoderPCMa_2ch,
-  kDecoderILBC,
-  kDecoderISAC,
-  kDecoderISACswb,
-  kDecoderPCM16B,
-  kDecoderPCM16Bwb,
-  kDecoderPCM16Bswb32kHz,
-  kDecoderPCM16Bswb48kHz,
-  kDecoderPCM16B_2ch,
-  kDecoderPCM16Bwb_2ch,
-  kDecoderPCM16Bswb32kHz_2ch,
-  kDecoderPCM16Bswb48kHz_2ch,
-  kDecoderPCM16B_5ch,
-  kDecoderG722,
-  kDecoderG722_2ch,
-  kDecoderRED,
-  kDecoderAVT,
-  kDecoderAVT16kHz,
-  kDecoderAVT32kHz,
-  kDecoderAVT48kHz,
-  kDecoderCNGnb,
-  kDecoderCNGwb,
-  kDecoderCNGswb32kHz,
-  kDecoderCNGswb48kHz,
-  kDecoderArbitrary,
-  kDecoderOpus,
-  kDecoderOpus_2ch,
-};
-
-absl::optional<SdpAudioFormat> NetEqDecoderToSdpAudioFormat(NetEqDecoder nd);
-
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_NETEQ_NETEQ_DECODER_ENUM_H_
diff --git a/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc b/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc
index 8d0972c..21b15a9 100644
--- a/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_decoder_plc_unittest.cc
@@ -14,6 +14,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/memory/memory.h"
 #include "absl/types/optional.h"
 #include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
 #include "modules/audio_coding/neteq/tools/audio_checksum.h"
@@ -23,8 +24,10 @@
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/audio_decoder_proxy_factory.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace test {
@@ -174,10 +177,7 @@
       webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm"));
   AudioDecoderPlc dec(std::move(input_file), kSampleRateHz);
   // Masquerading as a PCM16b decoder.
-  NetEqTest::ExternalDecoderInfo dec_info = {
-      &dec, NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16b_PLC"};
-  NetEqTest::ExtDecoderMap external_decoders;
-  external_decoders.insert(std::make_pair(kPayloadType, dec_info));
+  decoders.emplace(kPayloadType, SdpAudioFormat("l16", 32000, 1));
 
   // Output is simply a checksum calculator.
   auto output = absl::make_unique<AudioChecksumWithOutput>(checksum);
@@ -185,8 +185,9 @@
   // No callback objects.
   NetEqTest::Callbacks callbacks;
 
-  NetEqTest neteq_test(config, decoders, external_decoders,
-                       std::move(lossy_input), std::move(output), callbacks);
+  NetEqTest neteq_test(
+      config, new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&dec),
+      decoders, nullptr, std::move(lossy_input), std::move(output), callbacks);
   EXPECT_LE(kRunTimeMs, neteq_test.Run());
 
   auto lifetime_stats = neteq_test.LifetimeStats();
diff --git a/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc b/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
index 872829c..8214ed2 100644
--- a/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_external_decoder_unittest.cc
@@ -14,14 +14,13 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gmock.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 2a025f3..f1e8527 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -41,6 +41,7 @@
 #include "modules/audio_coding/neteq/post_decode_vad.h"
 #include "modules/audio_coding/neteq/preemptive_expand.h"
 #include "modules/audio_coding/neteq/red_payload_splitter.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/sync_buffer.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
 #include "modules/audio_coding/neteq/time_stretch.h"
@@ -58,14 +59,18 @@
     const NetEq::Config& config,
     const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory)
     : tick_timer(new TickTimer),
+      stats(new StatisticsCalculator),
       buffer_level_filter(new BufferLevelFilter),
       decoder_database(
           new DecoderDatabase(decoder_factory, config.codec_pair_id)),
-      delay_peak_detector(new DelayPeakDetector(tick_timer.get())),
-      delay_manager(new DelayManager(config.max_packets_in_buffer,
-                                     config.min_delay_ms,
-                                     delay_peak_detector.get(),
-                                     tick_timer.get())),
+      delay_peak_detector(
+          new DelayPeakDetector(tick_timer.get(), config.enable_rtx_handling)),
+      delay_manager(DelayManager::Create(config.max_packets_in_buffer,
+                                         config.min_delay_ms,
+                                         config.enable_rtx_handling,
+                                         delay_peak_detector.get(),
+                                         tick_timer.get(),
+                                         stats.get())),
       dtmf_buffer(new DtmfBuffer(config.sample_rate_hz)),
       dtmf_tone_generator(new DtmfToneGenerator),
       packet_buffer(
@@ -95,6 +100,7 @@
       expand_factory_(std::move(deps.expand_factory)),
       accelerate_factory_(std::move(deps.accelerate_factory)),
       preemptive_expand_factory_(std::move(deps.preemptive_expand_factory)),
+      stats_(std::move(deps.stats)),
       last_mode_(kModeNormal),
       decoded_buffer_length_(kMaxFrameSize),
       decoded_buffer_(new int16_t[decoded_buffer_length_]),
@@ -102,7 +108,6 @@
       new_codec_(false),
       timestamp_(0),
       reset_decoder_(false),
-      ssrc_(0),
       first_packet_(true),
       enable_fast_accelerate_(config.enable_fast_accelerate),
       nack_enabled_(false),
@@ -113,7 +118,8 @@
       speech_expand_uma_logger_("WebRTC.Audio.SpeechExpandRatePercent",
                                 10,  // Report once every 10 s.
                                 tick_timer_.get()),
-      no_time_stretching_(config.for_test_no_time_stretching) {
+      no_time_stretching_(config.for_test_no_time_stretching),
+      enable_rtx_handling_(config.enable_rtx_handling) {
   RTC_LOG(LS_INFO) << "NetEq config: " << config.ToString();
   int fs = config.sample_rate_hz;
   if (fs != 8000 && fs != 16000 && fs != 32000 && fs != 48000) {
@@ -231,44 +237,10 @@
   const std::vector<int> changed_payload_types =
       decoder_database_->SetCodecs(codecs);
   for (const int pt : changed_payload_types) {
-    packet_buffer_->DiscardPacketsWithPayloadType(pt, &stats_);
+    packet_buffer_->DiscardPacketsWithPayloadType(pt, stats_.get());
   }
 }
 
-int NetEqImpl::RegisterPayloadType(NetEqDecoder codec,
-                                   const std::string& name,
-                                   uint8_t rtp_payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  RTC_LOG(LS_VERBOSE) << "RegisterPayloadType "
-                      << static_cast<int>(rtp_payload_type) << " "
-                      << static_cast<int>(codec);
-  if (decoder_database_->RegisterPayload(rtp_payload_type, codec, name) !=
-      DecoderDatabase::kOK) {
-    return kFail;
-  }
-  return kOK;
-}
-
-int NetEqImpl::RegisterExternalDecoder(AudioDecoder* decoder,
-                                       NetEqDecoder codec,
-                                       const std::string& codec_name,
-                                       uint8_t rtp_payload_type) {
-  rtc::CritScope lock(&crit_sect_);
-  RTC_LOG(LS_VERBOSE) << "RegisterExternalDecoder "
-                      << static_cast<int>(rtp_payload_type) << " "
-                      << static_cast<int>(codec);
-  if (!decoder) {
-    RTC_LOG(LS_ERROR) << "Cannot register external decoder with NULL pointer";
-    assert(false);
-    return kFail;
-  }
-  if (decoder_database_->InsertExternal(rtp_payload_type, codec, codec_name,
-                                        decoder) != DecoderDatabase::kOK) {
-    return kFail;
-  }
-  return kOK;
-}
-
 bool NetEqImpl::RegisterPayloadType(int rtp_payload_type,
                                     const SdpAudioFormat& audio_format) {
   RTC_LOG(LS_VERBOSE) << "NetEqImpl::RegisterPayloadType: payload type "
@@ -283,7 +255,8 @@
   rtc::CritScope lock(&crit_sect_);
   int ret = decoder_database_->Remove(rtp_payload_type);
   if (ret == DecoderDatabase::kOK || ret == DecoderDatabase::kDecoderNotFound) {
-    packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type, &stats_);
+    packet_buffer_->DiscardPacketsWithPayloadType(rtp_payload_type,
+                                                  stats_.get());
     return kOK;
   }
   return kFail;
@@ -312,6 +285,19 @@
   return false;
 }
 
+bool NetEqImpl::SetBaseMinimumDelayMs(int delay_ms) {
+  rtc::CritScope lock(&crit_sect_);
+  if (delay_ms >= 0 && delay_ms <= 10000) {
+    return delay_manager_->SetBaseMinimumDelay(delay_ms);
+  }
+  return false;
+}
+
+int NetEqImpl::GetBaseMinimumDelayMs() const {
+  rtc::CritScope lock(&crit_sect_);
+  return delay_manager_->GetBaseMinimumDelay();
+}
+
 int NetEqImpl::TargetDelayMs() const {
   rtc::CritScope lock(&crit_sect_);
   RTC_DCHECK(delay_manager_.get());
@@ -322,21 +308,6 @@
          rtc::CheckedDivExact(fs_hz_, 1000);
 }
 
-int NetEqImpl::CurrentDelayMs() const {
-  rtc::CritScope lock(&crit_sect_);
-  if (fs_hz_ == 0)
-    return 0;
-  // Sum up the samples in the packet buffer with the future length of the sync
-  // buffer, and divide the sum by the sample rate.
-  const size_t delay_samples =
-      packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
-      sync_buffer_->FutureLength();
-  // The division below will truncate.
-  const int delay_ms =
-      static_cast<int>(delay_samples) / rtc::CheckedDivExact(fs_hz_, 1000);
-  return delay_ms;
-}
-
 int NetEqImpl::FilteredCurrentDelayMs() const {
   rtc::CritScope lock(&crit_sect_);
   // Calculate the filtered packet buffer level in samples. The value from
@@ -363,20 +334,21 @@
   assert(decision_logic_.get());
   const int ms_per_packet = rtc::dchecked_cast<int>(
       decision_logic_->packet_length_samples() / (fs_hz_ / 1000));
-  stats_.PopulateDelayManagerStats(ms_per_packet, *delay_manager_.get(), stats);
-  stats_.GetNetworkStatistics(fs_hz_, total_samples_in_buffers,
-                              decoder_frame_length_, stats);
+  stats_->PopulateDelayManagerStats(ms_per_packet, *delay_manager_.get(),
+                                    stats);
+  stats_->GetNetworkStatistics(fs_hz_, total_samples_in_buffers,
+                               decoder_frame_length_, stats);
   return 0;
 }
 
 NetEqLifetimeStatistics NetEqImpl::GetLifetimeStatistics() const {
   rtc::CritScope lock(&crit_sect_);
-  return stats_.GetLifetimeStatistics();
+  return stats_->GetLifetimeStatistics();
 }
 
 NetEqOperationsAndState NetEqImpl::GetOperationsAndState() const {
   rtc::CritScope lock(&crit_sect_);
-  auto result = stats_.GetOperationsAndState();
+  auto result = stats_->GetOperationsAndState();
   result.current_buffer_size_ms =
       (packet_buffer_->NumSamplesInBuffer(decoder_frame_length_) +
        sync_buffer_->FutureLength()) *
@@ -417,27 +389,6 @@
   return last_output_sample_rate_hz_;
 }
 
-absl::optional<CodecInst> NetEqImpl::GetDecoder(int payload_type) const {
-  rtc::CritScope lock(&crit_sect_);
-  const DecoderDatabase::DecoderInfo* di =
-      decoder_database_->GetDecoderInfo(payload_type);
-  if (!di) {
-    return absl::nullopt;
-  }
-
-  // Create a CodecInst with some fields set. The remaining fields are zeroed,
-  // but we tell MSan to consider them uninitialized.
-  CodecInst ci = {0};
-  rtc::MsanMarkUninitialized(rtc::MakeArrayView(&ci, 1));
-  ci.pltype = payload_type;
-  std::strncpy(ci.plname, di->get_name().c_str(), sizeof(ci.plname));
-  ci.plname[sizeof(ci.plname) - 1] = '\0';
-  ci.plfreq = di->IsRed() ? 8000 : di->SampleRateHz();
-  AudioDecoder* const decoder = di->GetDecoder();
-  ci.channels = decoder ? decoder->Channels() : 1;
-  return ci;
-}
-
 absl::optional<SdpAudioFormat> NetEqImpl::GetDecoderFormat(
     int payload_type) const {
   rtc::CritScope lock(&crit_sect_);
@@ -446,7 +397,13 @@
   if (!di) {
     return absl::nullopt;  // Payload type not registered.
   }
-  return di->GetFormat();
+
+  SdpAudioFormat format = di->GetFormat();
+  // TODO(solenberg): This is legacy but messed up - mixing RTP rate and SR.
+  format.clockrate_hz = di->IsRed() ? 8000 : di->SampleRateHz();
+  const AudioDecoder* const decoder = di->GetDecoder();
+  format.num_channels = decoder ? decoder->Channels() : 1;
+  return format;
 }
 
 void NetEqImpl::FlushBuffers() {
@@ -518,6 +475,7 @@
     RTC_LOG_F(LS_ERROR) << "payload is empty";
     return kInvalidPointer;
   }
+  stats_->ReceivedPacket();
 
   PacketList packet_list;
   // Insert packet in a packet list.
@@ -533,8 +491,7 @@
     return packet;
   }());
 
-  bool update_sample_rate_and_channels =
-      first_packet_ || (rtp_header.ssrc != ssrc_);
+  bool update_sample_rate_and_channels = first_packet_;
 
   if (update_sample_rate_and_channels) {
     // Reset timestamp scaling.
@@ -561,9 +518,6 @@
     packet_buffer_->Flush();
     dtmf_buffer_->Flush();
 
-    // Store new SSRC.
-    ssrc_ = rtp_header.ssrc;
-
     // Update audio buffer timestamp.
     sync_buffer_->IncreaseEndTimestamp(main_timestamp - timestamp_);
 
@@ -707,7 +661,7 @@
   // Insert packets in buffer.
   const int ret = packet_buffer_->InsertPacketList(
       &parsed_packet_list, *decoder_database_, &current_rtp_payload_type_,
-      &current_cng_rtp_payload_type_, &stats_);
+      &current_cng_rtp_payload_type_, stats_.get());
   if (ret == PacketBuffer::kFlushed) {
     // Reset DSP timestamp etc. if packet buffer flushed.
     new_codec_ = true;
@@ -777,9 +731,11 @@
     }
 
     // Update statistics.
-    if ((int32_t)(main_timestamp - timestamp_) >= 0 && !new_codec_) {
+    if ((enable_rtx_handling_ || (int32_t)(main_timestamp - timestamp_) >= 0) &&
+        !new_codec_) {
       // Only update statistics if incoming packet is not older than last played
-      // out packet, and if new codec flag is not set.
+      // out packet or RTX handling is enabled, and if new codec flag is not
+      // set.
       delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz_);
     }
   } else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {
@@ -802,8 +758,8 @@
   *muted = false;
   last_decoded_timestamps_.clear();
   tick_timer_->Increment();
-  stats_.IncreaseCounter(output_size_samples_, fs_hz_);
-  const auto lifetime_stats = stats_.GetLifetimeStatistics();
+  stats_->IncreaseCounter(output_size_samples_, fs_hz_);
+  const auto lifetime_stats = stats_->GetLifetimeStatistics();
   expand_uma_logger_.UpdateSampleCounter(lifetime_stats.concealed_samples,
                                          fs_hz_);
   speech_expand_uma_logger_.UpdateSampleCounter(
@@ -823,7 +779,7 @@
             : timestamp_scaler_->ToExternal(playout_timestamp_) -
                   static_cast<uint32_t>(audio_frame->samples_per_channel_);
     audio_frame->num_channels_ = sync_buffer_->Channels();
-    stats_.ExpandedNoiseSamples(output_size_samples_, false);
+    stats_->ExpandedNoiseSamples(output_size_samples_, false);
     *muted = true;
     return 0;
   }
@@ -1032,7 +988,7 @@
   if (!new_codec_) {
     const uint32_t five_seconds_samples = 5 * fs_hz_;
     packet_buffer_->DiscardOldPackets(end_timestamp, five_seconds_samples,
-                                      &stats_);
+                                      stats_.get());
   }
   const Packet* packet = packet_buffer_->PeekNextPacket();
 
@@ -1052,12 +1008,14 @@
            (end_timestamp >= packet->timestamp ||
             end_timestamp + generated_noise_samples > packet->timestamp)) {
       // Don't use this packet, discard it.
-      if (packet_buffer_->DiscardNextPacket(&stats_) != PacketBuffer::kOK) {
+      if (packet_buffer_->DiscardNextPacket(stats_.get()) !=
+          PacketBuffer::kOK) {
         assert(false);  // Must be ok by design.
       }
       // Check buffer again.
       if (!new_codec_) {
-        packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_, &stats_);
+        packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_,
+                                          stats_.get());
       }
       packet = packet_buffer_->PeekNextPacket();
     }
@@ -1139,7 +1097,7 @@
     decision_logic_->SoftReset();
     buffer_level_filter_->Reset();
     delay_manager_->Reset();
-    stats_.ResetMcu();
+    stats_->ResetMcu();
   }
 
   size_t required_samples = output_size_samples_;
@@ -1244,7 +1202,7 @@
       // if comfort noise is not played. If comfort noise was just played,
       // this adjustment of timestamp is only done to get back in sync with the
       // stream timestamp; no loss to report.
-      stats_.LostSamples(packet->timestamp - end_timestamp);
+      stats_->LostSamples(packet->timestamp - end_timestamp);
     }
 
     if (*operation != kRfc3389Cng) {
@@ -1511,10 +1469,10 @@
   // Update in-call and post-call statistics.
   if (expand_->MuteFactor(0) == 0) {
     // Expand generates only noise.
-    stats_.ExpandedNoiseSamplesCorrection(expand_length_correction);
+    stats_->ExpandedNoiseSamplesCorrection(expand_length_correction);
   } else {
     // Expansion generates more than only noise.
-    stats_.ExpandedVoiceSamplesCorrection(expand_length_correction);
+    stats_->ExpandedVoiceSamplesCorrection(expand_length_correction);
   }
 
   last_mode_ = kModeMerge;
@@ -1555,12 +1513,12 @@
   if (std::all_of(concealment_audio_.cbegin(), concealment_audio_.cend(),
                   [](int16_t i) { return i == 0; })) {
     // Expand operation generates only noise.
-    stats_.ExpandedNoiseSamples(concealed_samples_per_channel,
-                                is_new_concealment_event);
+    stats_->ExpandedNoiseSamples(concealed_samples_per_channel,
+                                 is_new_concealment_event);
   } else {
     // Expand operation generates more than only noise.
-    stats_.ExpandedVoiceSamples(concealed_samples_per_channel,
-                                is_new_concealment_event);
+    stats_->ExpandedVoiceSamples(concealed_samples_per_channel,
+                                 is_new_concealment_event);
   }
   last_mode_ = kModeCodecPlc;
   if (!generated_noise_stopwatch_) {
@@ -1581,10 +1539,10 @@
     // Update in-call and post-call statistics.
     if (expand_->MuteFactor(0) == 0) {
       // Expand operation generates only noise.
-      stats_.ExpandedNoiseSamples(length, is_new_concealment_event);
+      stats_->ExpandedNoiseSamples(length, is_new_concealment_event);
     } else {
       // Expand operation generates more than only noise.
-      stats_.ExpandedVoiceSamples(length, is_new_concealment_event);
+      stats_->ExpandedVoiceSamples(length, is_new_concealment_event);
     }
 
     last_mode_ = kModeExpand;
@@ -1633,7 +1591,7 @@
   Accelerate::ReturnCodes return_code =
       accelerate_->Process(decoded_buffer, decoded_length, fast_accelerate,
                            algorithm_buffer_.get(), &samples_removed);
-  stats_.AcceleratedSamples(samples_removed);
+  stats_->AcceleratedSamples(samples_removed);
   switch (return_code) {
     case Accelerate::kSuccess:
       last_mode_ = kModeAccelerateSuccess;
@@ -1711,7 +1669,7 @@
   PreemptiveExpand::ReturnCodes return_code = preemptive_expand_->Process(
       decoded_buffer, decoded_length, old_borrowed_samples_per_channel,
       algorithm_buffer_.get(), &samples_added);
-  stats_.PreemptiveExpandedSamples(samples_added);
+  stats_->PreemptiveExpandedSamples(samples_added);
   switch (return_code) {
     case PreemptiveExpand::kSuccess:
       last_mode_ = kModePreemptiveExpandSuccess;
@@ -1926,7 +1884,7 @@
       return -1;
     }
     const uint64_t waiting_time_ms = packet->waiting_time->ElapsedMs();
-    stats_.StoreWaitingTime(waiting_time_ms);
+    stats_->StoreWaitingTime(waiting_time_ms);
     RTC_DCHECK(!packet->empty());
 
     if (first_packet) {
@@ -1950,7 +1908,7 @@
       packet_duration = packet->frame->Duration();
       // TODO(ossu): Is this the correct way to track Opus FEC packets?
       if (packet->priority.codec_level > 0) {
-        stats_.SecondaryDecodedSamples(
+        stats_->SecondaryDecodedSamples(
             rtc::dchecked_cast<int>(packet_duration));
       }
     } else if (!has_cng_packet) {
@@ -1966,7 +1924,7 @@
     }
     extracted_samples = packet->timestamp - first_timestamp + packet_duration;
 
-    stats_.JitterBufferDelay(extracted_samples, waiting_time_ms);
+    stats_->JitterBufferDelay(packet_duration, waiting_time_ms);
 
     packet_list->push_back(std::move(*packet));  // Store packet in list.
     packet = absl::nullopt;  // Ensure it's never used after the move.
@@ -1978,13 +1936,14 @@
         !has_cng_packet) {
       int16_t seq_no_diff = next_packet->sequence_number - prev_sequence_number;
       size_t ts_diff = next_packet->timestamp - prev_timestamp;
-      if (seq_no_diff == 1 ||
-          (seq_no_diff == 0 && ts_diff == decoder_frame_length_)) {
+      if ((seq_no_diff == 1 || seq_no_diff == 0) &&
+          ts_diff <= packet_duration) {
         // The next sequence number is available, or the next part of a packet
         // that was split into pieces upon insertion.
         next_packet_available = true;
       }
       prev_sequence_number = next_packet->sequence_number;
+      prev_timestamp = next_packet->timestamp;
     }
   } while (extracted_samples < required_samples && next_packet_available);
 
@@ -1993,7 +1952,7 @@
     // we could end up in the situation where we never decode anything, since
     // all incoming packets are considered too old but the buffer will also
     // never be flooded and flushed.
-    packet_buffer_->DiscardAllOldPackets(timestamp_, &stats_);
+    packet_buffer_->DiscardAllOldPackets(timestamp_, stats_.get());
   }
 
   return rtc::dchecked_cast<int>(extracted_samples);
@@ -2003,7 +1962,7 @@
   // Delete objects and create new ones.
   expand_.reset(expand_factory_->Create(background_noise_.get(),
                                         sync_buffer_.get(), &random_vector_,
-                                        &stats_, fs_hz, channels));
+                                        stats_.get(), fs_hz, channels));
   merge_.reset(new Merge(fs_hz, channels, expand_.get(), sync_buffer_.get()));
 }
 
diff --git a/modules/audio_coding/neteq/neteq_impl.h b/modules/audio_coding/neteq/neteq_impl.h
index 525ae61..34a5c71 100644
--- a/modules/audio_coding/neteq/neteq_impl.h
+++ b/modules/audio_coding/neteq/neteq_impl.h
@@ -24,8 +24,8 @@
 #include "modules/audio_coding/neteq/random_vector.h"
 #include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/tick_timer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/criticalsection.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/critical_section.h"
 #include "rtc_base/thread_annotations.h"
 
 namespace webrtc {
@@ -99,6 +99,7 @@
     ~Dependencies();
 
     std::unique_ptr<TickTimer> tick_timer;
+    std::unique_ptr<StatisticsCalculator> stats;
     std::unique_ptr<BufferLevelFilter> buffer_level_filter;
     std::unique_ptr<DecoderDatabase> decoder_database;
     std::unique_ptr<DelayPeakDetector> delay_peak_detector;
@@ -137,15 +138,6 @@
 
   void SetCodecs(const std::map<int, SdpAudioFormat>& codecs) override;
 
-  int RegisterPayloadType(NetEqDecoder codec,
-                          const std::string& codec_name,
-                          uint8_t rtp_payload_type) override;
-
-  int RegisterExternalDecoder(AudioDecoder* decoder,
-                              NetEqDecoder codec,
-                              const std::string& codec_name,
-                              uint8_t rtp_payload_type) override;
-
   bool RegisterPayloadType(int rtp_payload_type,
                            const SdpAudioFormat& audio_format) override;
 
@@ -159,9 +151,11 @@
 
   bool SetMaximumDelay(int delay_ms) override;
 
-  int TargetDelayMs() const override;
+  bool SetBaseMinimumDelayMs(int delay_ms) override;
 
-  int CurrentDelayMs() const override;
+  int GetBaseMinimumDelayMs() const override;
+
+  int TargetDelayMs() const override;
 
   int FilteredCurrentDelayMs() const override;
 
@@ -184,8 +178,6 @@
 
   int last_output_sample_rate_hz() const override;
 
-  absl::optional<CodecInst> GetDecoder(int payload_type) const override;
-
   absl::optional<SdpAudioFormat> GetDecoderFormat(
       int payload_type) const override;
 
@@ -370,6 +362,7 @@
       RTC_GUARDED_BY(crit_sect_);
   const std::unique_ptr<PreemptiveExpandFactory> preemptive_expand_factory_
       RTC_GUARDED_BY(crit_sect_);
+  const std::unique_ptr<StatisticsCalculator> stats_ RTC_GUARDED_BY(crit_sect_);
 
   std::unique_ptr<BackgroundNoise> background_noise_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<DecisionLogic> decision_logic_ RTC_GUARDED_BY(crit_sect_);
@@ -384,7 +377,6 @@
       RTC_GUARDED_BY(crit_sect_);
   RandomVector random_vector_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<ComfortNoise> comfort_noise_ RTC_GUARDED_BY(crit_sect_);
-  StatisticsCalculator stats_ RTC_GUARDED_BY(crit_sect_);
   int fs_hz_ RTC_GUARDED_BY(crit_sect_);
   int fs_mult_ RTC_GUARDED_BY(crit_sect_);
   int last_output_sample_rate_hz_ RTC_GUARDED_BY(crit_sect_);
@@ -401,7 +393,6 @@
   absl::optional<uint8_t> current_rtp_payload_type_ RTC_GUARDED_BY(crit_sect_);
   absl::optional<uint8_t> current_cng_rtp_payload_type_
       RTC_GUARDED_BY(crit_sect_);
-  uint32_t ssrc_ RTC_GUARDED_BY(crit_sect_);
   bool first_packet_ RTC_GUARDED_BY(crit_sect_);
   bool enable_fast_accelerate_ RTC_GUARDED_BY(crit_sect_);
   std::unique_ptr<NackTracker> nack_ RTC_GUARDED_BY(crit_sect_);
@@ -416,6 +407,7 @@
   ExpandUmaLogger speech_expand_uma_logger_ RTC_GUARDED_BY(crit_sect_);
   bool no_time_stretching_ RTC_GUARDED_BY(crit_sect_);  // Only used for test.
   rtc::BufferT<int16_t> concealment_audio_ RTC_GUARDED_BY(crit_sect_);
+  const bool enable_rtx_handling_ RTC_GUARDED_BY(crit_sect_);
 
  private:
   RTC_DISALLOW_COPY_AND_ASSIGN(NetEqImpl);
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 0e087c8..5875493 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -10,10 +10,11 @@
 
 #include <memory>
 
+#include "absl/memory/memory.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/accelerate.h"
 #include "modules/audio_coding/neteq/expand.h"
+#include "modules/audio_coding/neteq/histogram.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/mock/mock_buffer_level_filter.h"
 #include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
@@ -25,9 +26,12 @@
 #include "modules/audio_coding/neteq/mock/mock_red_payload_splitter.h"
 #include "modules/audio_coding/neteq/neteq_impl.h"
 #include "modules/audio_coding/neteq/preemptive_expand.h"
+#include "modules/audio_coding/neteq/statistics_calculator.h"
 #include "modules/audio_coding/neteq/sync_buffer.h"
 #include "modules/audio_coding/neteq/timestamp_scaler.h"
 #include "rtc_base/numerics/safe_conversions.h"
+#include "test/audio_decoder_proxy_factory.h"
+#include "test/function_audio_decoder_factory.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
 #include "test/mock_audio_decoder.h"
@@ -59,8 +63,10 @@
  protected:
   NetEqImplTest() { config_.sample_rate_hz = 8000; }
 
-  void CreateInstance() {
-    NetEqImpl::Dependencies deps(config_, CreateBuiltinAudioDecoderFactory());
+  void CreateInstance(
+      const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
+    ASSERT_TRUE(decoder_factory);
+    NetEqImpl::Dependencies deps(config_, decoder_factory);
 
     // Get a local pointer to NetEq's TickTimer object.
     tick_timer_ = deps.tick_timer.get();
@@ -83,7 +89,7 @@
 
     if (use_mock_delay_peak_detector_) {
       std::unique_ptr<MockDelayPeakDetector> mock(
-          new MockDelayPeakDetector(tick_timer_));
+          new MockDelayPeakDetector(tick_timer_, config_.enable_rtx_handling));
       mock_delay_peak_detector_ = mock.get();
       EXPECT_CALL(*mock_delay_peak_detector_, Reset()).Times(1);
       deps.delay_peak_detector = std::move(mock);
@@ -92,8 +98,10 @@
 
     if (use_mock_delay_manager_) {
       std::unique_ptr<MockDelayManager> mock(new MockDelayManager(
-          config_.max_packets_in_buffer, config_.min_delay_ms,
-          delay_peak_detector_, tick_timer_));
+          config_.max_packets_in_buffer, config_.min_delay_ms, 1020054733,
+          DelayManager::HistogramMode::INTER_ARRIVAL_TIME,
+          config_.enable_rtx_handling, delay_peak_detector_, tick_timer_,
+          deps.stats.get(), absl::make_unique<Histogram>(50, 32745)));
       mock_delay_manager_ = mock.get();
       EXPECT_CALL(*mock_delay_manager_, set_streaming_mode(false)).Times(1);
       deps.delay_manager = std::move(mock);
@@ -137,6 +145,8 @@
     ASSERT_TRUE(neteq_ != NULL);
   }
 
+  void CreateInstance() { CreateInstance(CreateBuiltinAudioDecoderFactory()); }
+
   void UseNoMocks() {
     ASSERT_TRUE(neteq_ == NULL) << "Must call UseNoMocks before CreateInstance";
     use_mock_buffer_level_filter_ = false;
@@ -173,7 +183,7 @@
     }
   }
 
-  void TestDtmfPacket(NetEqDecoder decoder_type) {
+  void TestDtmfPacket(int sample_rate_hz) {
     const size_t kPayloadLength = 4;
     const uint8_t kPayloadType = 110;
     const uint32_t kReceiveTime = 17;
@@ -189,8 +199,8 @@
     rtp_header.timestamp = 0x12345678;
     rtp_header.ssrc = 0x87654321;
 
-    EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-        decoder_type, "telephone-event", kPayloadType));
+    EXPECT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadType, SdpAudioFormat("telephone-event", sample_rate_hz, 1)));
 
     // Insert first packet.
     EXPECT_EQ(NetEq::kOK,
@@ -257,16 +267,6 @@
   delete neteq;
 }
 
-TEST_F(NetEqImplTest, RegisterPayloadTypeNetEqDecoder) {
-  CreateInstance();
-  uint8_t rtp_payload_type = 0;
-  NetEqDecoder codec_type = NetEqDecoder::kDecoderPCMu;
-  const std::string kCodecName = "Robert\'); DROP TABLE Students;";
-  EXPECT_CALL(*mock_decoder_database_,
-              RegisterPayload(rtp_payload_type, codec_type, kCodecName));
-  neteq_->RegisterPayloadType(codec_type, kCodecName, rtp_payload_type);
-}
-
 TEST_F(NetEqImplTest, RegisterPayloadType) {
   CreateInstance();
   constexpr int rtp_payload_type = 0;
@@ -335,8 +335,8 @@
 
         *dec = std::move(mock_decoder);
       }));
-  DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu, absl::nullopt,
-                                    mock_decoder_factory);
+  DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
+                                    absl::nullopt, mock_decoder_factory);
 
   // Expectations for decoder database.
   EXPECT_CALL(*mock_decoder_database_, GetDecoderInfo(kPayloadType))
@@ -405,8 +405,8 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-                            NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert packets. The buffer should not flush.
   for (size_t i = 1; i <= config_.max_packets_in_buffer; ++i) {
@@ -428,27 +428,24 @@
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT);
+  TestDtmfPacket(8000);
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT16kHz) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT16kHz);
+  TestDtmfPacket(16000);
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT32kHz) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT32kHz);
+  TestDtmfPacket(32000);
 }
 
 TEST_F(NetEqImplTest, TestDtmfPacketAVT48kHz) {
-  TestDtmfPacket(NetEqDecoder::kDecoderAVT48kHz);
+  TestDtmfPacket(48000);
 }
 
 // This test verifies that timestamps propagate from the incoming packets
 // through to the sync buffer and to the playout timestamp.
 TEST_F(NetEqImplTest, VerifyTimestampPropagation) {
-  UseNoMocks();
-  CreateInstance();
-
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
   const int kSampleRateHz = 8000;
@@ -494,9 +491,14 @@
     int16_t next_value_;
   } decoder_;
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &decoder_, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory =
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&decoder_);
+
+  UseNoMocks();
+  CreateInstance(decoder_factory);
+
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   EXPECT_EQ(NetEq::kOK,
@@ -541,7 +543,11 @@
 
 TEST_F(NetEqImplTest, ReorderedPacket) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -556,8 +562,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -575,9 +579,8 @@
                                           dummy_output + kPayloadLengthSamples),
                       SetArgPointee<4>(AudioDecoder::kSpeech),
                       Return(rtc::checked_cast<int>(kPayloadLengthSamples))));
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   EXPECT_EQ(NetEq::kOK,
@@ -662,8 +665,8 @@
   EXPECT_EQ(AudioFrame::kPLC, output.speech_type_);
 
   // Register the payload type.
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-                            NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert 10 packets.
   for (size_t i = 0; i < 10; ++i) {
@@ -689,7 +692,10 @@
 // internal CNG mode properly.
 TEST_F(NetEqImplTest, CodecInternalCng) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -706,8 +712,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateKhz * 1000));
@@ -751,9 +755,8 @@
                       SetArgPointee<4>(AudioDecoder::kSpeech),
                       Return(rtc::checked_cast<int>(kPayloadLengthSamples))));
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderOpus,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("opus", 48000, 2)));
 
   // Insert one packet (decoder will return speech).
   EXPECT_EQ(NetEq::kOK,
@@ -834,7 +837,10 @@
 
 TEST_F(NetEqImplTest, UnsupportedDecoder) {
   UseNoMocks();
-  CreateInstance();
+  ::testing::NiceMock<MockAudioDecoder> decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&decoder));
   static const size_t kNetEqMaxFrameSize = 5760;  // 120 ms @ 48 kHz.
   static const size_t kChannels = 2;
 
@@ -853,8 +859,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  ::testing::NiceMock<MockAudioDecoder> decoder;
-
   const uint8_t kFirstPayloadValue = 1;
   const uint8_t kSecondPayloadValue = 2;
 
@@ -886,9 +890,8 @@
   EXPECT_CALL(decoder, Channels())
       .WillRepeatedly(Return(kChannels));
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   payload[0] = kFirstPayloadValue;  // This will make Decode() fail.
@@ -945,8 +948,8 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(
-                            NetEqDecoder::kDecoderPCM16B, "", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert packets until the buffer flushes.
   for (size_t i = 0; i <= config_.max_packets_in_buffer; ++i) {
@@ -965,7 +968,11 @@
 
 TEST_F(NetEqImplTest, DecodedPayloadTooShort) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -980,8 +987,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -1001,9 +1006,8 @@
                                     dummy_output + kPayloadLengthSamples - 5),
                 SetArgPointee<4>(AudioDecoder::kSpeech),
                 Return(rtc::checked_cast<int>(kPayloadLengthSamples - 5))));
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
   EXPECT_EQ(NetEq::kOK,
@@ -1026,7 +1030,11 @@
 // This test checks the behavior of NetEq when audio decoder fails.
 TEST_F(NetEqImplTest, DecodingError) {
   UseNoMocks();
-  CreateInstance();
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -1047,8 +1055,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -1094,9 +1100,8 @@
                   Return(rtc::checked_cast<int>(kFrameLengthSamples))));
   }
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("L16", 8000, 1)));
 
   // Insert packets.
   for (int i = 0; i < 6; ++i) {
@@ -1140,7 +1145,11 @@
 // This test checks the behavior of NetEq when audio decoder fails during CNG.
 TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) {
   UseNoMocks();
-  CreateInstance();
+
+  // Create a mock decoder object.
+  MockAudioDecoder mock_decoder;
+  CreateInstance(
+      new rtc::RefCountedObject<test::AudioDecoderProxyFactory>(&mock_decoder));
 
   const uint8_t kPayloadType = 17;   // Just an arbitrary number.
   const uint32_t kReceiveTime = 17;  // Value doesn't matter for this test.
@@ -1161,8 +1170,6 @@
   rtp_header.timestamp = 0x12345678;
   rtp_header.ssrc = 0x87654321;
 
-  // Create a mock decoder object.
-  MockAudioDecoder mock_decoder;
   EXPECT_CALL(mock_decoder, Reset()).WillRepeatedly(Return());
   EXPECT_CALL(mock_decoder, SampleRateHz())
       .WillRepeatedly(Return(kSampleRateHz));
@@ -1204,9 +1211,8 @@
                   Return(rtc::checked_cast<int>(kFrameLengthSamples))));
   }
 
-  EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                            &mock_decoder, NetEqDecoder::kDecoderPCM16B,
-                            "dummy name", kPayloadType));
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
 
   // Insert 2 packets. This will make netEq into codec internal CNG mode.
   for (int i = 0; i < 2; ++i) {
@@ -1261,6 +1267,34 @@
   EXPECT_EQ(1u, tick_timer_->ticks());
 }
 
+TEST_F(NetEqImplTest, SetBaseMinimumDelay) {
+  UseNoMocks();
+  use_mock_delay_manager_ = true;
+  CreateInstance();
+
+  EXPECT_CALL(*mock_delay_manager_, SetBaseMinimumDelay(_))
+      .WillOnce(Return(true))
+      .WillOnce(Return(false));
+
+  const int delay_ms = 200;
+
+  EXPECT_EQ(true, neteq_->SetBaseMinimumDelayMs(delay_ms));
+  EXPECT_EQ(false, neteq_->SetBaseMinimumDelayMs(delay_ms));
+}
+
+TEST_F(NetEqImplTest, GetBaseMinimumDelayMs) {
+  UseNoMocks();
+  use_mock_delay_manager_ = true;
+  CreateInstance();
+
+  const int delay_ms = 200;
+
+  EXPECT_CALL(*mock_delay_manager_, GetBaseMinimumDelay())
+      .WillOnce(Return(delay_ms));
+
+  EXPECT_EQ(delay_ms, neteq_->GetBaseMinimumDelayMs());
+}
+
 TEST_F(NetEqImplTest, TargetDelayMs) {
   UseNoMocks();
   use_mock_delay_manager_ = true;
@@ -1289,6 +1323,43 @@
   neteq_->InsertEmptyPacket(rtp_header);
 }
 
+TEST_F(NetEqImplTest, EnableRtxHandling) {
+  UseNoMocks();
+  use_mock_delay_manager_ = true;
+  config_.enable_rtx_handling = true;
+  CreateInstance();
+  EXPECT_CALL(*mock_delay_manager_, BufferLimits(_, _))
+      .Times(1)
+      .WillOnce(DoAll(SetArgPointee<0>(0), SetArgPointee<1>(0)));
+
+  const int kPayloadLengthSamples = 80;
+  const size_t kPayloadLengthBytes = 2 * kPayloadLengthSamples;  // PCM 16-bit.
+  const uint8_t kPayloadType = 17;  // Just an arbitrary number.
+  const uint32_t kReceiveTime = 17;
+  uint8_t payload[kPayloadLengthBytes] = {0};
+  RTPHeader rtp_header;
+  rtp_header.payloadType = kPayloadType;
+  rtp_header.sequenceNumber = 0x1234;
+  rtp_header.timestamp = 0x12345678;
+  rtp_header.ssrc = 0x87654321;
+
+  EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
+                                          SdpAudioFormat("l16", 8000, 1)));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
+  AudioFrame output;
+  bool muted;
+  EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &muted));
+
+  // Insert second packet that was sent before the first packet.
+  rtp_header.sequenceNumber -= 1;
+  rtp_header.timestamp -= kPayloadLengthSamples;
+  EXPECT_CALL(*mock_delay_manager_,
+              Update(rtp_header.sequenceNumber, rtp_header.timestamp, _));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
+}
+
 class Decoder120ms : public AudioDecoder {
  public:
   Decoder120ms(int sample_rate_hz, SpeechType speech_type)
@@ -1328,13 +1399,17 @@
 
   void CreateInstanceNoMocks() {
     UseNoMocks();
-    CreateInstance();
+    CreateInstance(decoder_factory_);
+    EXPECT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadType, SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})));
   }
 
   void CreateInstanceWithDelayManagerMock() {
     UseNoMocks();
     use_mock_delay_manager_ = true;
-    CreateInstance();
+    CreateInstance(decoder_factory_);
+    EXPECT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadType, SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})));
   }
 
   uint32_t timestamp_diff_between_packets() const {
@@ -1364,14 +1439,18 @@
   }
 
   void Register120msCodec(AudioDecoder::SpeechType speech_type) {
-    decoder_.reset(new Decoder120ms(kSamplingFreq_, speech_type));
-    ASSERT_EQ(2u, decoder_->Channels());
-    EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
-                              decoder_.get(), NetEqDecoder::kDecoderOpus_2ch,
-                              "120ms codec", kPayloadType));
+    const uint32_t sampling_freq = kSamplingFreq_;
+    decoder_factory_ =
+        new rtc::RefCountedObject<test::FunctionAudioDecoderFactory>(
+            [sampling_freq, speech_type]() {
+              std::unique_ptr<AudioDecoder> decoder =
+                  absl::make_unique<Decoder120ms>(sampling_freq, speech_type);
+              RTC_CHECK_EQ(2, decoder->Channels());
+              return decoder;
+            });
   }
 
-  std::unique_ptr<Decoder120ms> decoder_;
+  rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
   AudioFrame output_;
   const uint32_t kPayloadType = 17;
   const uint32_t kSamplingFreq_ = 48000;
@@ -1379,8 +1458,8 @@
 };
 
 TEST_F(NetEqImplTest120ms, CodecInternalCng) {
-  CreateInstanceNoMocks();
   Register120msCodec(AudioDecoder::kComfortNoise);
+  CreateInstanceNoMocks();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1391,8 +1470,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, Normal) {
-  CreateInstanceNoMocks();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceNoMocks();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1401,9 +1480,9 @@
 }
 
 TEST_F(NetEqImplTest120ms, Merge) {
+  Register120msCodec(AudioDecoder::kSpeech);
   CreateInstanceWithDelayManagerMock();
 
-  Register120msCodec(AudioDecoder::kSpeech);
   InsertPacket(first_timestamp());
 
   GetFirstPacket();
@@ -1420,8 +1499,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, Expand) {
-  CreateInstanceNoMocks();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceNoMocks();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1432,8 +1511,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, FastAccelerate) {
-  CreateInstanceWithDelayManagerMock();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceWithDelayManagerMock();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1450,8 +1529,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, PreemptiveExpand) {
-  CreateInstanceWithDelayManagerMock();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceWithDelayManagerMock();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
@@ -1469,8 +1548,8 @@
 }
 
 TEST_F(NetEqImplTest120ms, Accelerate) {
-  CreateInstanceWithDelayManagerMock();
   Register120msCodec(AudioDecoder::kSpeech);
+  CreateInstanceWithDelayManagerMock();
 
   InsertPacket(first_timestamp());
   GetFirstPacket();
diff --git a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
index 57fc682..79059b7 100644
--- a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
@@ -10,10 +10,15 @@
 
 #include <memory>
 
+#include "absl/memory/memory.h"
 #include "api/audio/audio_frame.h"
+#include "api/audio_codecs/audio_decoder.h"
 #include "common_types.h"  // NOLINT(build/include)
-#include "modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
+
+#include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
+#include "rtc_base/ref_counted_object.h"
+#include "test/audio_decoder_proxy_factory.h"
 #include "test/gmock.h"
 
 namespace webrtc {
@@ -118,10 +123,12 @@
   bool fec_enabled_;
 };
 
-class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
+class NetEqNetworkStatsTest {
  public:
   static const int kPayloadSizeByte = 30;
   static const int kFrameSizeMs = 20;
+  static const uint8_t kPayloadType = 95;
+  static const int kOutputLengthMs = 10;
 
   enum logic {
     kIgnore,
@@ -146,17 +153,19 @@
     NetEqNetworkStatistics stats_ref;
   };
 
-  NetEqNetworkStatsTest(NetEqDecoder codec,
-                        int sample_rate_hz,
-                        MockAudioDecoder* decoder)
-      : NetEqExternalDecoderTest(codec, sample_rate_hz, decoder),
-        external_decoder_(decoder),
-        samples_per_ms_(sample_rate_hz / 1000),
+  NetEqNetworkStatsTest(const SdpAudioFormat& format, MockAudioDecoder* decoder)
+      : decoder_(decoder),
+        decoder_factory_(
+            new rtc::RefCountedObject<AudioDecoderProxyFactory>(decoder)),
+        samples_per_ms_(format.clockrate_hz / 1000),
         frame_size_samples_(kFrameSizeMs * samples_per_ms_),
-        rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
+        rtp_generator_(new RtpGenerator(samples_per_ms_)),
         last_lost_time_(0),
         packet_loss_interval_(0xffffffff) {
-    Init();
+    NetEq::Config config;
+    config.sample_rate_hz = format.clockrate_hz;
+    neteq_ = absl::WrapUnique(NetEq::Create(config, decoder_factory_));
+    neteq_->RegisterPayloadType(kPayloadType, format);
   }
 
   bool Lost(uint32_t send_time) {
@@ -180,7 +189,7 @@
   // expects.x = 2, 'x' in current stats should > 'x' in |stats_ref|
   void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) {
     NetEqNetworkStatistics stats;
-    neteq()->NetworkStatistics(&stats);
+    neteq_->NetworkStatistics(&stats);
 
 #define CHECK_NETEQ_NETWORK_STATS(x)           \
   switch (expects.x) {                         \
@@ -211,9 +220,6 @@
     CHECK_NETEQ_NETWORK_STATS(added_zero_samples);
 
 #undef CHECK_NETEQ_NETWORK_STATS
-
-    // Compare with CurrentDelay, which should be identical.
-    EXPECT_EQ(stats.current_buffer_size_ms, neteq()->CurrentDelayMs());
   }
 
   void RunTest(int num_loops, NetEqNetworkStatsCheck expects) {
@@ -230,18 +236,26 @@
             kPayloadType, frame_size_samples_, &rtp_header_);
         if (!Lost(next_send_time)) {
           static const uint8_t payload[kPayloadSizeByte] = {0};
-          InsertPacket(rtp_header_, payload, next_send_time);
+          ASSERT_EQ(NetEq::kOK,
+                    neteq_->InsertPacket(rtp_header_, payload, next_send_time));
         }
       }
-      GetOutputAudio(&output_frame_);
+      bool muted = true;
+      EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_frame_, &muted));
+      ASSERT_FALSE(muted);
+      EXPECT_EQ(decoder_->Channels(), output_frame_.num_channels_);
+      EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * samples_per_ms_),
+                output_frame_.samples_per_channel_);
+      EXPECT_EQ(48000, neteq_->last_output_sample_rate_hz());
+
       time_now += kOutputLengthMs;
     }
     CheckNetworkStatistics(expects);
-    neteq()->FlushBuffers();
+    neteq_->FlushBuffers();
   }
 
   void DecodeFecTest() {
-    external_decoder_->set_fec_enabled(false);
+    decoder_->set_fec_enabled(false);
     NetEqNetworkStatsCheck expects = {kIgnore,  // current_buffer_size_ms
                                       kIgnore,  // preferred_buffer_size_ms
                                       kIgnore,  // jitter_peaks_found
@@ -264,7 +278,7 @@
     RunTest(50, expects);
 
     // Next we enable FEC.
-    external_decoder_->set_fec_enabled(true);
+    decoder_->set_fec_enabled(true);
     // If FEC fills in the lost packets, no packet loss will be counted.
     expects.stats_ref.packet_loss_rate = 0;
     expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
@@ -296,10 +310,13 @@
   }
 
  private:
-  MockAudioDecoder* external_decoder_;
+  MockAudioDecoder* decoder_;
+  rtc::scoped_refptr<AudioDecoderProxyFactory> decoder_factory_;
+  std::unique_ptr<NetEq> neteq_;
+
   const int samples_per_ms_;
   const size_t frame_size_samples_;
-  std::unique_ptr<test::RtpGenerator> rtp_generator_;
+  std::unique_ptr<RtpGenerator> rtp_generator_;
   RTPHeader rtp_header_;
   uint32_t last_lost_time_;
   uint32_t packet_loss_interval_;
@@ -308,21 +325,21 @@
 
 TEST(NetEqNetworkStatsTest, DecodeFec) {
   MockAudioDecoder decoder(48000, 1);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
+  NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
   test.DecodeFecTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
 
 TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
   MockAudioDecoder decoder(48000, 2);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
+  NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
   test.DecodeFecTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
 
 TEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
   MockAudioDecoder decoder(48000, 1);
-  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, 48000, &decoder);
+  NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
   test.NoiseExpansionTest();
   EXPECT_CALL(decoder, Die()).Times(1);
 }
diff --git a/modules/audio_coding/neteq/neteq_stereo_unittest.cc b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
index 3f86944..d25e8d6 100644
--- a/modules/audio_coding/neteq/neteq_stereo_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
@@ -17,14 +17,13 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
@@ -90,51 +89,12 @@
     const std::string file_name =
         webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
     input_file_.reset(new test::InputAudioFile(file_name));
-    NetEqDecoder mono_decoder;
-    NetEqDecoder multi_decoder;
-    switch (sample_rate_hz_) {
-      case 8000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16B;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16B_2ch;
-        } else if (num_channels_ == 5) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16B_5ch;
-        } else {
-          FAIL() << "Only 2 and 5 channels supported for 8000 Hz.";
-        }
-        break;
-      case 16000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16Bwb;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16Bwb_2ch;
-        } else {
-          FAIL() << "More than 2 channels is not supported for 16000 Hz.";
-        }
-        break;
-      case 32000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16Bswb32kHz;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16Bswb32kHz_2ch;
-        } else {
-          FAIL() << "More than 2 channels is not supported for 32000 Hz.";
-        }
-        break;
-      case 48000:
-        mono_decoder = NetEqDecoder::kDecoderPCM16Bswb48kHz;
-        if (num_channels_ == 2) {
-          multi_decoder = NetEqDecoder::kDecoderPCM16Bswb48kHz_2ch;
-        } else {
-          FAIL() << "More than 2 channels is not supported for 48000 Hz.";
-        }
-        break;
-      default:
-        FAIL() << "We shouldn't get here.";
-    }
-    ASSERT_EQ(NetEq::kOK, neteq_mono_->RegisterPayloadType(mono_decoder, "mono",
-                                                           kPayloadTypeMono));
-    ASSERT_EQ(NetEq::kOK,
-              neteq_->RegisterPayloadType(multi_decoder, "multi-channel",
-                                          kPayloadTypeMulti));
+    RTC_CHECK_GE(num_channels_, 2);
+    ASSERT_TRUE(neteq_mono_->RegisterPayloadType(
+        kPayloadTypeMono, SdpAudioFormat("l16", sample_rate_hz_, 1)));
+    ASSERT_TRUE(neteq_->RegisterPayloadType(
+        kPayloadTypeMulti,
+        SdpAudioFormat("l16", sample_rate_hz_, num_channels_)));
   }
 
   virtual void TearDown() {}
@@ -404,24 +364,24 @@
 
 // Instantiate the tests. Each test is instantiated using the function above,
 // so that all different parameter combinations are tested.
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestNoJitter,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestNoJitter,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestPositiveDrift,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestPositiveDrift,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestNegativeDrift,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestNegativeDrift,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestDelays,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestDelays,
+                         ::testing::ValuesIn(GetTestParameters()));
 
-INSTANTIATE_TEST_CASE_P(MultiChannel,
-                        NetEqStereoTestLosses,
-                        ::testing::ValuesIn(GetTestParameters()));
+INSTANTIATE_TEST_SUITE_P(MultiChannel,
+                         NetEqStereoTestLosses,
+                         ::testing::ValuesIn(GetTestParameters()));
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index e8b5023..6c67ca8 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -27,17 +27,18 @@
 #include "modules/audio_coding/neteq/tools/neteq_packet_source_input.h"
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 #include "modules/audio_coding/neteq/tools/rtp_file_source.h"
+#include "modules/include/module_common_types_public.h"
 #include "modules/rtp_rtcp/include/rtcp_statistics.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
 #include "rtc_base/ignore_wundef.h"
-#include "rtc_base/messagedigest.h"
+#include "rtc_base/message_digest.h"
 #include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/protobuf_utils.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/string_encode.h"
 #include "rtc_base/strings/string_builder.h"
 #include "rtc_base/system/arch.h"
 #include "test/field_trial.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 // This must come after test/gtest.h
 #include "rtc_base/flags.h"  // NOLINT(build/include)
@@ -129,10 +130,8 @@
 void LoadDecoders(webrtc::NetEq* neteq) {
   ASSERT_EQ(true,
             neteq->RegisterPayloadType(0, SdpAudioFormat("pcmu", 8000, 1)));
-  // Use non-SdpAudioFormat argument when registering PCMa, so that we get test
-  // coverage for that as well.
-  ASSERT_EQ(0, neteq->RegisterPayloadType(webrtc::NetEqDecoder::kDecoderPCMa,
-                                          "pcma", 8));
+  ASSERT_EQ(true,
+            neteq->RegisterPayloadType(8, SdpAudioFormat("pcma", 8000, 1)));
 #ifdef WEBRTC_CODEC_ILBC
   ASSERT_EQ(true,
             neteq->RegisterPayloadType(102, SdpAudioFormat("ilbc", 8000, 1)));
@@ -208,7 +207,7 @@
   neteq_unittest::NetEqNetworkStatistics stats;
   Convert(stats_raw, &stats);
 
-  ProtoString stats_string;
+  std::string stats_string;
   ASSERT_TRUE(stats.SerializeToString(&stats_string));
   AddMessage(output_fp_, digest_.get(), stats_string);
 #else
@@ -221,7 +220,7 @@
   neteq_unittest::RtcpStatistics stats;
   Convert(stats_raw, &stats);
 
-  ProtoString stats_string;
+  std::string stats_string;
   ASSERT_TRUE(stats.SerializeToString(&stats_string));
   AddMessage(output_fp_, digest_.get(), stats_string);
 #else
@@ -258,7 +257,6 @@
   NetEqDecodingTest();
   virtual void SetUp();
   virtual void TearDown();
-  void SelectDecoders(NetEqDecoder* used_codec);
   void OpenInputFile(const std::string& rtp_file);
   void Process();
 
@@ -402,10 +400,6 @@
       ASSERT_EQ(0, neteq_->NetworkStatistics(&current_network_stats));
       ASSERT_NO_FATAL_FAILURE(network_stats.AddResult(current_network_stats));
 
-      // Compare with CurrentDelay, which should be identical.
-      EXPECT_EQ(current_network_stats.current_buffer_size_ms,
-                neteq_->CurrentDelayMs());
-
       // Verify that liftime stats and network stats report similar loss
       // concealment rates.
       auto lifetime_stats = neteq_->GetLifetimeStatistics();
@@ -464,16 +458,16 @@
       webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
 
   const std::string output_checksum =
-      PlatformChecksum("0c6dc227f781c81a229970f8fceda1a012498cba",
-                       "15c4a2202877a414515e218bdb7992f0ad53e5af", "not used",
-                       "0c6dc227f781c81a229970f8fceda1a012498cba",
-                       "25fc4c863caa499aa447a5b8d059f5452cbcc500");
+      PlatformChecksum("9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
+                       "54a7e32f163663c0af35bf70bf45cefc24ad62ef", "not used",
+                       "9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
+                       "79496b0a1ef0a3824f3ee04789748a461bed643f");
 
   const std::string network_stats_checksum =
-      PlatformChecksum("4b2370f5c794741d2a46be5c7935c66ef3fb53e9",
-                       "e339cb2adf5ab3dfc21cb7205d670a34751e8336", "not used",
-                       "4b2370f5c794741d2a46be5c7935c66ef3fb53e9",
-                       "4b2370f5c794741d2a46be5c7935c66ef3fb53e9");
+      PlatformChecksum("c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
+                       "bca95e565996a4ffd6e2ac15736e08843bdca93b", "not used",
+                       "c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
+                       "c59b1f9f282b6d8733cdff975e3c150ca4a47d51");
 
   DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
                    FLAG_gen_ref);
@@ -1661,6 +1655,7 @@
   int packets_sent = 0;
   int packets_received = 0;
   int expected_delay = 0;
+  uint64_t expected_emitted_count = 0;
   while (packets_received < kNumPackets) {
     // Insert packet.
     if (packets_sent < kNumPackets) {
@@ -1684,6 +1679,7 @@
       // number of samples that are sent for play out.
       int current_delay_ms = packets_delay * kPacketLenMs;
       expected_delay += current_delay_ms * kSamples;
+      expected_emitted_count += kSamples;
     }
   }
 
@@ -1695,6 +1691,7 @@
   // Check jitter buffer delay.
   NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
   EXPECT_EQ(expected_delay, static_cast<int>(stats.jitter_buffer_delay_ms));
+  EXPECT_EQ(expected_emitted_count, stats.jitter_buffer_emitted_count);
 }
 
 TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithoutLoss) {
@@ -1705,12 +1702,43 @@
   TestJitterBufferDelay(true);
 }
 
+TEST_F(NetEqDecodingTestFaxMode, TestJitterBufferDelayWithAcceleration) {
+  const int kPacketLenMs = 10;  // All packets are of 10 ms size.
+  const size_t kSamples = kPacketLenMs * 16;
+  const size_t kPayloadBytes = kSamples * 2;
+  RTPHeader rtp_info;
+  rtp_info.ssrc = 0x1234;     // Just an arbitrary SSRC.
+  rtp_info.payloadType = 94;  // PCM16b WB codec.
+  rtp_info.markerBit = 0;
+  const uint8_t payload[kPayloadBytes] = {0};
+
+  neteq_->InsertPacket(rtp_info, payload, 0);
+
+  bool muted;
+  neteq_->GetAudio(&out_frame_, &muted);
+
+  rtp_info.sequenceNumber += 1;
+  rtp_info.timestamp += kSamples;
+  neteq_->InsertPacket(rtp_info, payload, 0);
+  rtp_info.sequenceNumber += 1;
+  rtp_info.timestamp += kSamples;
+  neteq_->InsertPacket(rtp_info, payload, 0);
+
+  // We have two packets in the buffer and kAccelerate operation will
+  // extract 20 ms of data.
+  neteq_->GetAudio(&out_frame_, &muted, Operations::kAccelerate);
+
+  // Check jitter buffer delay.
+  NetEqLifetimeStatistics stats = neteq_->GetLifetimeStatistics();
+  EXPECT_EQ(10 * kSamples * 3, stats.jitter_buffer_delay_ms);
+  EXPECT_EQ(kSamples * 3, stats.jitter_buffer_emitted_count);
+}
+
 namespace test {
 TEST(NetEqNoTimeStretchingMode, RunTest) {
   NetEq::Config config;
   config.for_test_no_time_stretching = true;
   auto codecs = NetEqTest::StandardDecoderMap();
-  NetEqTest::ExtDecoderMap ext_codecs;
   NetEqPacketSourceInput::RtpHeaderExtensionMap rtp_ext_map = {
       {1, kRtpExtensionAudioLevel},
       {3, kRtpExtensionAbsoluteSendTime},
@@ -1724,8 +1752,8 @@
       new TimeLimitedNetEqInput(std::move(input), 20000));
   std::unique_ptr<AudioSink> output(new VoidAudioSink);
   NetEqTest::Callbacks callbacks;
-  NetEqTest test(config, codecs, ext_codecs, std::move(input_time_limit),
-                 std::move(output), callbacks);
+  NetEqTest test(config, CreateBuiltinAudioDecoderFactory(), codecs, nullptr,
+                 std::move(input_time_limit), std::move(output), callbacks);
   test.Run();
   const auto stats = test.SimulationStats();
   EXPECT_EQ(0, stats.accelerate_rate);
diff --git a/modules/audio_coding/neteq/normal.h b/modules/audio_coding/neteq/normal.h
index 80451b5..2059c5a 100644
--- a/modules/audio_coding/neteq/normal.h
+++ b/modules/audio_coding/neteq/normal.h
@@ -16,7 +16,7 @@
 
 #include "modules/audio_coding/neteq/defines.h"
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 #include "rtc_base/numerics/safe_conversions.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/neteq/packet_buffer.cc b/modules/audio_coding/neteq/packet_buffer.cc
index 343763b..e90fadc 100644
--- a/modules/audio_coding/neteq/packet_buffer.cc
+++ b/modules/audio_coding/neteq/packet_buffer.cc
@@ -287,6 +287,20 @@
   return num_samples;
 }
 
+size_t PacketBuffer::GetSpanSamples(size_t last_decoded_length) const {
+  if (buffer_.size() == 0) {
+    return 0;
+  }
+
+  size_t span = buffer_.back().timestamp - buffer_.front().timestamp;
+  if (buffer_.back().frame && buffer_.back().frame->Duration() > 0) {
+    span += buffer_.back().frame->Duration();
+  } else {
+    span += last_decoded_length;
+  }
+  return span;
+}
+
 bool PacketBuffer::ContainsDtxOrCngPacket(
     const DecoderDatabase* decoder_database) const {
   RTC_DCHECK(decoder_database);
diff --git a/modules/audio_coding/neteq/packet_buffer.h b/modules/audio_coding/neteq/packet_buffer.h
index 0f5cd7f..0837027 100644
--- a/modules/audio_coding/neteq/packet_buffer.h
+++ b/modules/audio_coding/neteq/packet_buffer.h
@@ -15,7 +15,7 @@
 #include "modules/audio_coding/neteq/decoder_database.h"
 #include "modules/audio_coding/neteq/packet.h"
 #include "modules/include/module_common_types_public.h"  // IsNewerTimestamp
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -121,6 +121,10 @@
   // duplicate and redundant packets.
   virtual size_t NumSamplesInBuffer(size_t last_decoded_length) const;
 
+  // Returns the total duration in samples that the packets in the buffer spans
+  // across.
+  virtual size_t GetSpanSamples(size_t last_decoded_length) const;
+
   // Returns true if the packet buffer contains any DTX or CNG packets.
   virtual bool ContainsDtxOrCngPacket(
       const DecoderDatabase* decoder_database) const;
diff --git a/modules/audio_coding/neteq/packet_buffer_unittest.cc b/modules/audio_coding/neteq/packet_buffer_unittest.cc
index cb40d7d..7a381ee 100644
--- a/modules/audio_coding/neteq/packet_buffer_unittest.cc
+++ b/modules/audio_coding/neteq/packet_buffer_unittest.cc
@@ -175,7 +175,7 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info));
@@ -220,11 +220,11 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info0(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info0(SdpAudioFormat("pcmu", 8000, 1),
                                            absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info0));
-  const DecoderDatabase::DecoderInfo info1(NetEqDecoder::kDecoderPCMa,
+  const DecoderDatabase::DecoderInfo info1(SdpAudioFormat("pcma", 8000, 1),
                                            absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(1))
       .WillRepeatedly(Return(&info1));
@@ -407,7 +407,7 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info));
@@ -447,12 +447,12 @@
 
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGnb,
+  const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 8000, 1),
                                               absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(kCngPt))
       .WillRepeatedly(Return(&info_cng));
-  const DecoderDatabase::DecoderInfo info_speech(NetEqDecoder::kDecoderPCM16Bwb,
-                                                 absl::nullopt, factory);
+  const DecoderDatabase::DecoderInfo info_speech(
+      SdpAudioFormat("l16", 16000, 1), absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(kSpeechPt))
       .WillRepeatedly(Return(&info_speech));
 
@@ -549,7 +549,7 @@
   list.push_back(gen.NextPacket(payload_len));  // Valid packet.
   MockDecoderDatabase decoder_database;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   EXPECT_CALL(decoder_database, GetDecoderInfo(0))
       .WillRepeatedly(Return(&info));
diff --git a/modules/audio_coding/neteq/post_decode_vad.h b/modules/audio_coding/neteq/post_decode_vad.h
index 27d69a6..ca7cabf 100644
--- a/modules/audio_coding/neteq/post_decode_vad.h
+++ b/modules/audio_coding/neteq/post_decode_vad.h
@@ -16,7 +16,7 @@
 
 #include "api/audio_codecs/audio_decoder.h"
 #include "common_audio/vad/include/webrtc_vad.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/preemptive_expand.h b/modules/audio_coding/neteq/preemptive_expand.h
index 0f7b3bc..e7d2bad 100644
--- a/modules/audio_coding/neteq/preemptive_expand.h
+++ b/modules/audio_coding/neteq/preemptive_expand.h
@@ -15,7 +15,7 @@
 #include <stdint.h>
 
 #include "modules/audio_coding/neteq/time_stretch.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/random_vector.h b/modules/audio_coding/neteq/random_vector.h
index e8c7ba8..1d37600 100644
--- a/modules/audio_coding/neteq/random_vector.h
+++ b/modules/audio_coding/neteq/random_vector.h
@@ -14,7 +14,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/red_payload_splitter.h b/modules/audio_coding/neteq/red_payload_splitter.h
index 55063e7..c2e0a44 100644
--- a/modules/audio_coding/neteq/red_payload_splitter.h
+++ b/modules/audio_coding/neteq/red_payload_splitter.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_RED_PAYLOAD_SPLITTER_H_
 
 #include "modules/audio_coding/neteq/packet.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/red_payload_splitter_unittest.cc b/modules/audio_coding/neteq/red_payload_splitter_unittest.cc
index 52fc1ba..b4cd8d7 100644
--- a/modules/audio_coding/neteq/red_payload_splitter_unittest.cc
+++ b/modules/audio_coding/neteq/red_payload_splitter_unittest.cc
@@ -18,7 +18,7 @@
 #include <utility>  // pair
 
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "modules/audio_coding/neteq/mock/mock_decoder_database.h"
+#include "modules/audio_coding/neteq/decoder_database.h"
 #include "modules/audio_coding/neteq/packet.h"
 #include "rtc_base/numerics/safe_conversions.h"
 #include "test/gtest.h"
@@ -300,10 +300,11 @@
   // do its job.
   DecoderDatabase decoder_database(
       new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
-  decoder_database.RegisterPayload(0, NetEqDecoder::kDecoderCNGnb, "cng-nb");
-  decoder_database.RegisterPayload(1, NetEqDecoder::kDecoderPCMu, "pcmu");
-  decoder_database.RegisterPayload(2, NetEqDecoder::kDecoderAVT, "avt");
-  decoder_database.RegisterPayload(3, NetEqDecoder::kDecoderILBC, "ilbc");
+  decoder_database.RegisterPayload(0, SdpAudioFormat("cn", 8000, 1));
+  decoder_database.RegisterPayload(1, SdpAudioFormat("pcmu", 8000, 1));
+  decoder_database.RegisterPayload(2,
+                                   SdpAudioFormat("telephone-event", 8000, 1));
+  decoder_database.RegisterPayload(3, SdpAudioFormat("ilbc", 8000, 1));
 
   RedPayloadSplitter splitter;
   splitter.CheckRedPayloads(&packet_list, decoder_database);
@@ -334,8 +335,8 @@
   // do its job.
   DecoderDatabase decoder_database(
       new rtc::RefCountedObject<MockAudioDecoderFactory>, absl::nullopt);
-  decoder_database.RegisterPayload(kRedPayloadType, NetEqDecoder::kDecoderRED,
-                                   "red");
+  decoder_database.RegisterPayload(kRedPayloadType,
+                                   SdpAudioFormat("red", 8000, 1));
 
   RedPayloadSplitter splitter;
   splitter.CheckRedPayloads(&packet_list, decoder_database);
diff --git a/modules/audio_coding/neteq/statistics_calculator.cc b/modules/audio_coding/neteq/statistics_calculator.cc
index 50521fb..a0e9bca 100644
--- a/modules/audio_coding/neteq/statistics_calculator.cc
+++ b/modules/audio_coding/neteq/statistics_calculator.cc
@@ -216,7 +216,7 @@
 }
 
 void StatisticsCalculator::PacketsDiscarded(size_t num_packets) {
-  discarded_packets_ += num_packets;
+  operations_and_state_.discarded_primary_packets += num_packets;
 }
 
 void StatisticsCalculator::SecondaryPacketsDiscarded(size_t num_packets) {
@@ -246,6 +246,7 @@
 void StatisticsCalculator::JitterBufferDelay(size_t num_samples,
                                              uint64_t waiting_time_ms) {
   lifetime_stats_.jitter_buffer_delay_ms += waiting_time_ms * num_samples;
+  lifetime_stats_.jitter_buffer_emitted_count += num_samples;
 }
 
 void StatisticsCalculator::SecondaryDecodedSamples(int num_samples) {
@@ -257,6 +258,14 @@
   buffer_full_counter_.RegisterSample();
 }
 
+void StatisticsCalculator::ReceivedPacket() {
+  ++lifetime_stats_.jitter_buffer_packets_received;
+}
+
+void StatisticsCalculator::RelativePacketArrivalDelay(size_t delay_ms) {
+  lifetime_stats_.relative_packet_arrival_delay_ms += delay_ms;
+}
+
 void StatisticsCalculator::LogDelayedPacketOutageEvent(int num_samples,
                                                        int fs_hz) {
   int outage_duration_ms = num_samples / (fs_hz / 1000);
diff --git a/modules/audio_coding/neteq/statistics_calculator.h b/modules/audio_coding/neteq/statistics_calculator.h
index 49b74a0..cb92f37 100644
--- a/modules/audio_coding/neteq/statistics_calculator.h
+++ b/modules/audio_coding/neteq/statistics_calculator.h
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "modules/audio_coding/neteq/include/neteq.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
@@ -83,9 +83,15 @@
   // Reports that |num_samples| samples were decoded from secondary packets.
   void SecondaryDecodedSamples(int num_samples);
 
-  // Rerport that the packet buffer was flushed.
+  // Reports that the packet buffer was flushed.
   void FlushedPacketBuffer();
 
+  // Reports that the jitter buffer received a packet.
+  void ReceivedPacket();
+
+  // Reports that a received packet was delayed by |delay_ms| milliseconds.
+  virtual void RelativePacketArrivalDelay(size_t delay_ms);
+
   // Logs a delayed packet outage event of |num_samples| expanded at a sample
   // rate of |fs_hz|. A delayed packet outage event is defined as an expand
   // period caused not by an actual packet loss, but by a delayed packet.
diff --git a/modules/audio_coding/neteq/statistics_calculator_unittest.cc b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
index 0a4901d..1fb8e1c 100644
--- a/modules/audio_coding/neteq/statistics_calculator_unittest.cc
+++ b/modules/audio_coding/neteq/statistics_calculator_unittest.cc
@@ -104,4 +104,28 @@
   EXPECT_EQ((50u << 14) / k10MsSamples, stats_output.speech_expand_rate);
 }
 
+TEST(StatisticsCalculator, RelativePacketArrivalDelay) {
+  StatisticsCalculator stats;
+
+  stats.RelativePacketArrivalDelay(50);
+  NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(50u, stats_output.relative_packet_arrival_delay_ms);
+
+  stats.RelativePacketArrivalDelay(20);
+  stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(70u, stats_output.relative_packet_arrival_delay_ms);
+}
+
+TEST(StatisticsCalculator, ReceivedPacket) {
+  StatisticsCalculator stats;
+
+  stats.ReceivedPacket();
+  NetEqLifetimeStatistics stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(1u, stats_output.jitter_buffer_packets_received);
+
+  stats.ReceivedPacket();
+  stats_output = stats.GetLifetimeStatistics();
+  EXPECT_EQ(2u, stats_output.jitter_buffer_packets_received);
+}
+
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/sync_buffer.h b/modules/audio_coding/neteq/sync_buffer.h
index d645e91..7f6c111 100644
--- a/modules/audio_coding/neteq/sync_buffer.h
+++ b/modules/audio_coding/neteq/sync_buffer.h
@@ -19,7 +19,7 @@
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/audio_vector.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/tick_timer.h b/modules/audio_coding/neteq/tick_timer.h
index 02f083e..724dd12 100644
--- a/modules/audio_coding/neteq/tick_timer.h
+++ b/modules/audio_coding/neteq/tick_timer.h
@@ -15,7 +15,7 @@
 #include <memory>
 
 #include "rtc_base/checks.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/time_stretch.h b/modules/audio_coding/neteq/time_stretch.h
index 13ad2c8..9f86649 100644
--- a/modules/audio_coding/neteq/time_stretch.h
+++ b/modules/audio_coding/neteq/time_stretch.h
@@ -15,7 +15,7 @@
 #include <string.h>  // memset, size_t
 
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/time_stretch_unittest.cc b/modules/audio_coding/neteq/time_stretch_unittest.cc
index c96c7d4..6fced38 100644
--- a/modules/audio_coding/neteq/time_stretch_unittest.cc
+++ b/modules/audio_coding/neteq/time_stretch_unittest.cc
@@ -21,7 +21,7 @@
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
 #include "rtc_base/checks.h"
 #include "test/gtest.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/timestamp_scaler.h b/modules/audio_coding/neteq/timestamp_scaler.h
index 62f535c..93cb953 100644
--- a/modules/audio_coding/neteq/timestamp_scaler.h
+++ b/modules/audio_coding/neteq/timestamp_scaler.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_TIMESTAMP_SCALER_H_
 
 #include "modules/audio_coding/neteq/packet.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 
diff --git a/modules/audio_coding/neteq/timestamp_scaler_unittest.cc b/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
index 1f1445a..5b14189 100644
--- a/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
+++ b/modules/audio_coding/neteq/timestamp_scaler_unittest.cc
@@ -25,7 +25,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use PCMu, because it doesn't use scaled timestamps.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 0;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -47,7 +47,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use PCMu, because it doesn't use scaled timestamps.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderPCMu,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("pcmu", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 0;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -74,7 +74,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -100,7 +100,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -130,9 +130,9 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info_g722(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info_g722(SdpAudioFormat("g722", 8000, 1),
                                                absl::nullopt, factory);
-  const DecoderDatabase::DecoderInfo info_cng(NetEqDecoder::kDecoderCNGwb,
+  const DecoderDatabase::DecoderInfo info_cng(SdpAudioFormat("cn", 16000, 1),
                                               absl::nullopt, factory);
   static const uint8_t kRtpPayloadTypeG722 = 17;
   static const uint8_t kRtpPayloadTypeCng = 13;
@@ -174,7 +174,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -204,7 +204,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -238,7 +238,7 @@
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
   // Use G722, which has a factor 2 scaling.
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderG722,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("g722", 8000, 1),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
@@ -279,7 +279,7 @@
 TEST(TimestampScaler, TestOpusLargeStep) {
   MockDecoderDatabase db;
   auto factory = CreateBuiltinAudioDecoderFactory();
-  const DecoderDatabase::DecoderInfo info(NetEqDecoder::kDecoderOpus,
+  const DecoderDatabase::DecoderInfo info(SdpAudioFormat("opus", 48000, 2),
                                           absl::nullopt, factory);
   static const uint8_t kRtpPayloadType = 17;
   EXPECT_CALL(db, GetDecoderInfo(kRtpPayloadType))
diff --git a/modules/audio_coding/neteq/tools/audio_checksum.h b/modules/audio_coding/neteq/tools/audio_checksum.h
index ee8c582..e4306fa 100644
--- a/modules/audio_coding/neteq/tools/audio_checksum.h
+++ b/modules/audio_coding/neteq/tools/audio_checksum.h
@@ -16,9 +16,9 @@
 
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
 #include "rtc_base/buffer.h"
-#include "rtc_base/constructormagic.h"
-#include "rtc_base/messagedigest.h"
-#include "rtc_base/stringencode.h"
+#include "rtc_base/constructor_magic.h"
+#include "rtc_base/message_digest.h"
+#include "rtc_base/string_encode.h"
 #include "rtc_base/system/arch.h"
 
 namespace webrtc {
diff --git a/modules/audio_coding/neteq/tools/audio_loop.h b/modules/audio_coding/neteq/tools/audio_loop.h
index c7788a6..cd764cc 100644
--- a/modules/audio_coding/neteq/tools/audio_loop.h
+++ b/modules/audio_coding/neteq/tools/audio_loop.h
@@ -15,7 +15,7 @@
 #include <string>
 
 #include "api/array_view.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/audio_sink.h b/modules/audio_coding/neteq/tools/audio_sink.h
index be2a315..68825eb 100644
--- a/modules/audio_coding/neteq/tools/audio_sink.h
+++ b/modules/audio_coding/neteq/tools/audio_sink.h
@@ -12,7 +12,7 @@
 #define MODULES_AUDIO_CODING_NETEQ_TOOLS_AUDIO_SINK_H_
 
 #include "api/audio/audio_frame.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
index 4e216e4..7adb15b 100644
--- a/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
+++ b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
@@ -14,9 +14,8 @@
 #include <stdio.h>
 #include <string>
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/tools/packet_source.h"
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.cc b/modules/audio_coding/neteq/tools/input_audio_file.cc
index 6d11064..d5e2862 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.cc
+++ b/modules/audio_coding/neteq/tools/input_audio_file.cc
@@ -18,9 +18,11 @@
 InputAudioFile::InputAudioFile(const std::string file_name, bool loop_at_end)
     : loop_at_end_(loop_at_end) {
   fp_ = fopen(file_name.c_str(), "rb");
+  RTC_DCHECK(fp_) << file_name << " could not be opened.";
 }
 
 InputAudioFile::~InputAudioFile() {
+  RTC_DCHECK(fp_);
   fclose(fp_);
 }
 
diff --git a/modules/audio_coding/neteq/tools/input_audio_file.h b/modules/audio_coding/neteq/tools/input_audio_file.h
index b36dc24..4335a99 100644
--- a/modules/audio_coding/neteq/tools/input_audio_file.h
+++ b/modules/audio_coding/neteq/tools/input_audio_file.h
@@ -15,7 +15,7 @@
 
 #include <string>
 
-#include "rtc_base/constructormagic.h"
+#include "rtc_base/constructor_magic.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc b/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
deleted file mode 100644
index 3bd218b..0000000
--- a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  Copyright (c) 2015 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_coding/neteq/tools/neteq_external_decoder_test.h"
-
-#include "api/audio/audio_frame.h"
-#include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "rtc_base/format_macros.h"
-#include "test/gtest.h"
-
-namespace webrtc {
-namespace test {
-
-NetEqExternalDecoderTest::NetEqExternalDecoderTest(NetEqDecoder codec,
-                                                   int sample_rate_hz,
-                                                   AudioDecoder* decoder)
-    : codec_(codec),
-      decoder_(decoder),
-      sample_rate_hz_(sample_rate_hz),
-      channels_(decoder_->Channels()) {
-  NetEq::Config config;
-  config.sample_rate_hz = sample_rate_hz_;
-  neteq_.reset(NetEq::Create(config, CreateBuiltinAudioDecoderFactory()));
-}
-
-void NetEqExternalDecoderTest::Init() {
-  ASSERT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(decoder_, codec_, name_,
-                                                        kPayloadType));
-}
-
-void NetEqExternalDecoderTest::InsertPacket(
-    RTPHeader rtp_header,
-    rtc::ArrayView<const uint8_t> payload,
-    uint32_t receive_timestamp) {
-  ASSERT_EQ(NetEq::kOK,
-            neteq_->InsertPacket(rtp_header, payload, receive_timestamp));
-}
-
-void NetEqExternalDecoderTest::GetOutputAudio(AudioFrame* output) {
-  // Get audio from regular instance.
-  bool muted;
-  EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(output, &muted));
-  ASSERT_FALSE(muted);
-  EXPECT_EQ(channels_, output->num_channels_);
-  EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * sample_rate_hz_ / 1000),
-            output->samples_per_channel_);
-  EXPECT_EQ(sample_rate_hz_, neteq_->last_output_sample_rate_hz());
-}
-
-}  // namespace test
-}  // namespace webrtc
diff --git a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h b/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
deleted file mode 100644
index 78f0085..0000000
--- a/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  Copyright (c) 2015 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_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
-#define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
-
-#include <memory>
-#include <string>
-
-#include "api/audio_codecs/audio_decoder.h"
-#include "common_types.h"  // NOLINT(build/include)
-#include "modules/audio_coding/neteq/include/neteq.h"
-
-namespace webrtc {
-namespace test {
-// This test class provides a way run NetEQ with an external decoder.
-class NetEqExternalDecoderTest {
- protected:
-  static const uint8_t kPayloadType = 95;
-  static const int kOutputLengthMs = 10;
-
-  // The external decoder |decoder| is suppose to be of type |codec|.
-  NetEqExternalDecoderTest(NetEqDecoder codec,
-                           int sample_rate_hz,
-                           AudioDecoder* decoder);
-
-  virtual ~NetEqExternalDecoderTest() {}
-
-  // In Init(), we register the external decoder.
-  void Init();
-
-  // Inserts a new packet with |rtp_header| and |payload| of
-  // |payload_size_bytes| bytes. The |receive_timestamp| is an indication
-  // of the time when the packet was received, and should be measured with
-  // the same tick rate as the RTP timestamp of the current payload.
-  virtual void InsertPacket(RTPHeader rtp_header,
-                            rtc::ArrayView<const uint8_t> payload,
-                            uint32_t receive_timestamp);
-
-  // Get 10 ms of audio data.
-  void GetOutputAudio(AudioFrame* output);
-
-  NetEq* neteq() { return neteq_.get(); }
-
- private:
-  NetEqDecoder codec_;
-  std::string name_ = "dummy name";
-  AudioDecoder* decoder_;
-  int sample_rate_hz_;
-  size_t channels_;
-  std::unique_ptr<NetEq> neteq_;
-};
-
-}  // namespace test
-}  // namespace webrtc
-
-#endif  // MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_EXTERNAL_DECODER_TEST_H_
diff --git a/modules/audio_coding/neteq/tools/neteq_input.h b/modules/audio_coding/neteq/tools/neteq_input.h
index b9cba09..732b807 100644
--- a/modules/audio_coding/neteq/tools/neteq_input.h
+++ b/modules/audio_coding/neteq/tools/neteq_input.h
@@ -16,7 +16,6 @@
 #include <string>
 
 #include "absl/types/optional.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/tools/packet.h"
 #include "modules/audio_coding/neteq/tools/packet_source.h"
 #include "rtc_base/buffer.h"
diff --git a/modules/audio_coding/neteq/tools/neteq_performance_test.cc b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
index 52524fe..61f52bb 100644
--- a/modules/audio_coding/neteq/tools/neteq_performance_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
@@ -12,14 +12,13 @@
 
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_loop.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
 #include "rtc_base/checks.h"
 #include "system_wrappers/include/clock.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 using webrtc::NetEq;
 using webrtc::test::AudioLoop;
@@ -34,8 +33,6 @@
   const std::string kInputFileName =
       webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
   const int kSampRateHz = 32000;
-  const webrtc::NetEqDecoder kDecoderType =
-      webrtc::NetEqDecoder::kDecoderPCM16Bswb32kHz;
   const std::string kDecoderName = "pcm16-swb32";
   const int kPayloadType = 95;
 
@@ -44,7 +41,8 @@
   config.sample_rate_hz = kSampRateHz;
   NetEq* neteq = NetEq::Create(config, CreateBuiltinAudioDecoderFactory());
   // Register decoder in |neteq|.
-  if (neteq->RegisterPayloadType(kDecoderType, kDecoderName, kPayloadType) != 0)
+  if (!neteq->RegisterPayloadType(kPayloadType,
+                                  SdpAudioFormat("l16", kSampRateHz, 1)))
     return -1;
 
   // Set up AudioLoop object.
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
index 2ee6779..a0e7667 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
@@ -17,7 +17,7 @@
 #include "modules/audio_coding/neteq/tools/output_wav_file.h"
 #include "modules/audio_coding/neteq/tools/resample_input_audio_file.h"
 #include "rtc_base/checks.h"
-#include "test/testsupport/fileutils.h"
+#include "test/testsupport/file_utils.h"
 
 namespace webrtc {
 namespace test {
@@ -135,8 +135,8 @@
 NetEqQualityTest::NetEqQualityTest(int block_duration_ms,
                                    int in_sampling_khz,
                                    int out_sampling_khz,
-                                   NetEqDecoder decoder_type)
-    : decoder_type_(decoder_type),
+                                   const SdpAudioFormat& format)
+    : audio_format_(format),
       channels_(static_cast<size_t>(FLAG_channels)),
       decoded_time_ms_(0),
       decodable_time_ms_(0),
@@ -271,8 +271,7 @@
 }
 
 void NetEqQualityTest::SetUp() {
-  ASSERT_EQ(0,
-            neteq_->RegisterPayloadType(decoder_type_, "noname", kPayloadType));
+  ASSERT_TRUE(neteq_->RegisterPayloadType(kPayloadType, audio_format_));
   rtp_generator_->set_drift_factor(drift_factor_);
 
   int units = block_duration_ms_ / kPacketLossTimeUnitMs;
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.h b/modules/audio_coding/neteq/tools/neteq_quality_test.h
index 3d7760e..82a6a64 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.h
@@ -14,7 +14,6 @@
 #include <fstream>
 #include <memory>
 
-#include "common_types.h"  // NOLINT(build/include)
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
@@ -35,7 +34,7 @@
 
 class LossModel {
  public:
-  virtual ~LossModel(){};
+  virtual ~LossModel() {}
   virtual bool Lost(int now_ms) = 0;
 };
 
@@ -99,7 +98,7 @@
   NetEqQualityTest(int block_duration_ms,
                    int in_sampling_khz,
                    int out_sampling_khz,
-                   NetEqDecoder decoder_type);
+                   const SdpAudioFormat& format);
   ~NetEqQualityTest() override;
 
   void SetUp() override;
@@ -133,7 +132,7 @@
   // Write to log file. Usage Log() << ...
   std::ofstream& Log();
 
-  NetEqDecoder decoder_type_;
+  SdpAudioFormat audio_format_;
   const size_t channels_;
 
  private:
diff --git a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
index c2726eb..36c03b8 100644
--- a/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
+++ b/modules/audio_coding/neteq/tools/neteq_rtpplay.cc
@@ -17,6 +17,10 @@
 #include "system_wrappers/include/field_trial.h"
 #include "test/field_trial.h"
 
+namespace {
+
+using TestConfig = webrtc::test::NetEqTestFactory::Config;
+
 WEBRTC_DEFINE_bool(codec_map,
                    false,
                    "Prints the mapping between RTP payload type and "
@@ -28,6 +32,185 @@
     "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
     " will assign the group Enable to field trial WebRTC-FooFeature.");
 WEBRTC_DEFINE_bool(help, false, "Prints this message");
+// Define command line flags.
+WEBRTC_DEFINE_int(pcmu,
+                  TestConfig::default_pcmu(),
+                  "RTP payload type for PCM-u");
+WEBRTC_DEFINE_int(pcma,
+                  TestConfig::default_pcma(),
+                  "RTP payload type for PCM-a");
+WEBRTC_DEFINE_int(ilbc,
+                  TestConfig::default_ilbc(),
+                  "RTP payload type for iLBC");
+WEBRTC_DEFINE_int(isac,
+                  TestConfig::default_isac(),
+                  "RTP payload type for iSAC");
+WEBRTC_DEFINE_int(isac_swb,
+                  TestConfig::default_isac_swb(),
+                  "RTP payload type for iSAC-swb (32 kHz)");
+WEBRTC_DEFINE_int(opus,
+                  TestConfig::default_opus(),
+                  "RTP payload type for Opus");
+WEBRTC_DEFINE_int(pcm16b,
+                  TestConfig::default_pcm16b(),
+                  "RTP payload type for PCM16b-nb (8 kHz)");
+WEBRTC_DEFINE_int(pcm16b_wb,
+                  TestConfig::default_pcm16b_wb(),
+                  "RTP payload type for PCM16b-wb (16 kHz)");
+WEBRTC_DEFINE_int(pcm16b_swb32,
+                  TestConfig::default_pcm16b_swb32(),
+                  "RTP payload type for PCM16b-swb32 (32 kHz)");
+WEBRTC_DEFINE_int(pcm16b_swb48,
+                  TestConfig::default_pcm16b_swb48(),
+                  "RTP payload type for PCM16b-swb48 (48 kHz)");
+WEBRTC_DEFINE_int(g722,
+                  TestConfig::default_g722(),
+                  "RTP payload type for G.722");
+WEBRTC_DEFINE_int(avt,
+                  TestConfig::default_avt(),
+                  "RTP payload type for AVT/DTMF (8 kHz)");
+WEBRTC_DEFINE_int(avt_16,
+                  TestConfig::default_avt_16(),
+                  "RTP payload type for AVT/DTMF (16 kHz)");
+WEBRTC_DEFINE_int(avt_32,
+                  TestConfig::default_avt_32(),
+                  "RTP payload type for AVT/DTMF (32 kHz)");
+WEBRTC_DEFINE_int(avt_48,
+                  TestConfig::default_avt_48(),
+                  "RTP payload type for AVT/DTMF (48 kHz)");
+WEBRTC_DEFINE_int(red,
+                  TestConfig::default_red(),
+                  "RTP payload type for redundant audio (RED)");
+WEBRTC_DEFINE_int(cn_nb,
+                  TestConfig::default_cn_nb(),
+                  "RTP payload type for comfort noise (8 kHz)");
+WEBRTC_DEFINE_int(cn_wb,
+                  TestConfig::default_cn_wb(),
+                  "RTP payload type for comfort noise (16 kHz)");
+WEBRTC_DEFINE_int(cn_swb32,
+                  TestConfig::default_cn_swb32(),
+                  "RTP payload type for comfort noise (32 kHz)");
+WEBRTC_DEFINE_int(cn_swb48,
+                  TestConfig::default_cn_swb48(),
+                  "RTP payload type for comfort noise (48 kHz)");
+WEBRTC_DEFINE_string(replacement_audio_file,
+                     "",
+                     "A PCM file that will be used to populate dummy"
+                     " RTP packets");
+WEBRTC_DEFINE_string(
+    ssrc,
+    "",
+    "Only use packets with this SSRC (decimal or hex, the latter "
+    "starting with 0x)");
+WEBRTC_DEFINE_int(audio_level,
+                  TestConfig::default_audio_level(),
+                  "Extension ID for audio level (RFC 6464)");
+WEBRTC_DEFINE_int(abs_send_time,
+                  TestConfig::default_abs_send_time(),
+                  "Extension ID for absolute sender time");
+WEBRTC_DEFINE_int(transport_seq_no,
+                  TestConfig::default_transport_seq_no(),
+                  "Extension ID for transport sequence number");
+WEBRTC_DEFINE_int(video_content_type,
+                  TestConfig::default_video_content_type(),
+                  "Extension ID for video content type");
+WEBRTC_DEFINE_int(video_timing,
+                  TestConfig::default_video_timing(),
+                  "Extension ID for video timing");
+WEBRTC_DEFINE_bool(matlabplot,
+                   false,
+                   "Generates a matlab script for plotting the delay profile");
+WEBRTC_DEFINE_bool(pythonplot,
+                   false,
+                   "Generates a python script for plotting the delay profile");
+WEBRTC_DEFINE_bool(textlog,
+                   false,
+                   "Generates a text log describing the simulation on a "
+                   "step-by-step basis.");
+WEBRTC_DEFINE_bool(concealment_events, false, "Prints concealment events");
+WEBRTC_DEFINE_int(max_nr_packets_in_buffer,
+                  TestConfig::default_max_nr_packets_in_buffer(),
+                  "Maximum allowed number of packets in the buffer");
+WEBRTC_DEFINE_bool(enable_fast_accelerate,
+                   false,
+                   "Enables jitter buffer fast accelerate");
+
+// Parses the input string for a valid SSRC (at the start of the string). If a
+// valid SSRC is found, it is written to the output variable |ssrc|, and true is
+// returned. Otherwise, false is returned.
+bool ParseSsrc(const std::string& str, uint32_t* ssrc) {
+  if (str.empty())
+    return true;
+  int base = 10;
+  // Look for "0x" or "0X" at the start and change base to 16 if found.
+  if ((str.compare(0, 2, "0x") == 0) || (str.compare(0, 2, "0X") == 0))
+    base = 16;
+  errno = 0;
+  char* end_ptr;
+  unsigned long value = strtoul(str.c_str(), &end_ptr, base);  // NOLINT
+  if (value == ULONG_MAX && errno == ERANGE)
+    return false;  // Value out of range for unsigned long.
+  if (sizeof(unsigned long) > sizeof(uint32_t) && value > 0xFFFFFFFF)  // NOLINT
+    return false;  // Value out of range for uint32_t.
+  if (end_ptr - str.c_str() < static_cast<ptrdiff_t>(str.length()))
+    return false;  // Part of the string was not parsed.
+  *ssrc = static_cast<uint32_t>(value);
+  return true;
+}
+
+static bool ValidateExtensionId(int value) {
+  if (value > 0 && value <= 255)  // Value is ok.
+    return true;
+  printf("Extension ID must be between 1 and 255, not %d\n",
+         static_cast<int>(value));
+  return false;
+}
+
+// Flag validators.
+bool ValidatePayloadType(int value) {
+  if (value >= 0 && value <= 127)  // Value is ok.
+    return true;
+  printf("Payload type must be between 0 and 127, not %d\n",
+         static_cast<int>(value));
+  return false;
+}
+
+bool ValidateSsrcValue(const std::string& str) {
+  uint32_t dummy_ssrc;
+  if (ParseSsrc(str, &dummy_ssrc))  // Value is ok.
+    return true;
+  printf("Invalid SSRC: %s\n", str.c_str());
+  return false;
+}
+
+void PrintCodecMappingEntry(const char* codec, int flag) {
+  std::cout << codec << ": " << flag << std::endl;
+}
+
+void PrintCodecMapping() {
+  PrintCodecMappingEntry("PCM-u", FLAG_pcmu);
+  PrintCodecMappingEntry("PCM-a", FLAG_pcma);
+  PrintCodecMappingEntry("iLBC", FLAG_ilbc);
+  PrintCodecMappingEntry("iSAC", FLAG_isac);
+  PrintCodecMappingEntry("iSAC-swb (32 kHz)", FLAG_isac_swb);
+  PrintCodecMappingEntry("Opus", FLAG_opus);
+  PrintCodecMappingEntry("PCM16b-nb (8 kHz)", FLAG_pcm16b);
+  PrintCodecMappingEntry("PCM16b-wb (16 kHz)", FLAG_pcm16b_wb);
+  PrintCodecMappingEntry("PCM16b-swb32 (32 kHz)", FLAG_pcm16b_swb32);
+  PrintCodecMappingEntry("PCM16b-swb48 (48 kHz)", FLAG_pcm16b_swb48);
+  PrintCodecMappingEntry("G.722", FLAG_g722);
+  PrintCodecMappingEntry("AVT/DTMF (8 kHz)", FLAG_avt);
+  PrintCodecMappingEntry("AVT/DTMF (16 kHz)", FLAG_avt_16);
+  PrintCodecMappingEntry("AVT/DTMF (32 kHz)", FLAG_avt_32);
+  PrintCodecMappingEntry("AVT/DTMF (48 kHz)", FLAG_avt_48);
+  PrintCodecMappingEntry("redundant audio (RED)", FLAG_red);
+  PrintCodecMappingEntry("comfort noise (8 kHz)", FLAG_cn_nb);
+  PrintCodecMappingEntry("comfort noise (16 kHz)", FLAG_cn_wb);
+  PrintCodecMappingEntry("comfort noise (32 kHz)", FLAG_cn_swb32);
+  PrintCodecMappingEntry("comfort noise (48 kHz)", FLAG_cn_swb48);
+}
+
+}  // namespace
 
 int main(int argc, char* argv[]) {
   webrtc::test::NetEqTestFactory factory;
@@ -48,21 +231,85 @@
     exit(0);
   }
   if (FLAG_codec_map) {
-    factory.PrintCodecMap();
+    PrintCodecMapping();
+    exit(0);
   }
   if (argc != 3) {
-    if (FLAG_codec_map) {
-      // We have already printed the codec map. Just end the program.
-      exit(0);
-    }
     // Print usage information.
     std::cout << usage;
     exit(0);
   }
+  RTC_CHECK(ValidatePayloadType(FLAG_pcmu));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcma));
+  RTC_CHECK(ValidatePayloadType(FLAG_ilbc));
+  RTC_CHECK(ValidatePayloadType(FLAG_isac));
+  RTC_CHECK(ValidatePayloadType(FLAG_isac_swb));
+  RTC_CHECK(ValidatePayloadType(FLAG_opus));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_wb));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb32));
+  RTC_CHECK(ValidatePayloadType(FLAG_pcm16b_swb48));
+  RTC_CHECK(ValidatePayloadType(FLAG_g722));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt_16));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt_32));
+  RTC_CHECK(ValidatePayloadType(FLAG_avt_48));
+  RTC_CHECK(ValidatePayloadType(FLAG_red));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_nb));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_wb));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_swb32));
+  RTC_CHECK(ValidatePayloadType(FLAG_cn_swb48));
+  RTC_CHECK(ValidateSsrcValue(FLAG_ssrc));
+  RTC_CHECK(ValidateExtensionId(FLAG_audio_level));
+  RTC_CHECK(ValidateExtensionId(FLAG_abs_send_time));
+  RTC_CHECK(ValidateExtensionId(FLAG_transport_seq_no));
+  RTC_CHECK(ValidateExtensionId(FLAG_video_content_type));
+  RTC_CHECK(ValidateExtensionId(FLAG_video_timing));
+
   webrtc::test::ValidateFieldTrialsStringOrDie(FLAG_force_fieldtrials);
   webrtc::field_trial::InitFieldTrialsFromString(FLAG_force_fieldtrials);
+  webrtc::test::NetEqTestFactory::Config config;
+  config.pcmu = FLAG_pcmu;
+  config.pcma = FLAG_pcma;
+  config.ilbc = FLAG_ilbc;
+  config.isac = FLAG_isac;
+  config.isac_swb = FLAG_isac_swb;
+  config.opus = FLAG_opus;
+  config.pcm16b = FLAG_pcm16b;
+  config.pcm16b_wb = FLAG_pcm16b_wb;
+  config.pcm16b_swb32 = FLAG_pcm16b_swb32;
+  config.pcm16b_swb48 = FLAG_pcm16b_swb48;
+  config.g722 = FLAG_g722;
+  config.avt = FLAG_avt;
+  config.avt_16 = FLAG_avt_16;
+  config.avt_32 = FLAG_avt_32;
+  config.avt_48 = FLAG_avt_48;
+  config.red = FLAG_red;
+  config.cn_nb = FLAG_cn_nb;
+  config.cn_wb = FLAG_cn_wb;
+  config.cn_swb32 = FLAG_cn_swb32;
+  config.cn_swb48 = FLAG_cn_swb48;
+  config.replacement_audio_file = FLAG_replacement_audio_file;
+  config.audio_level = FLAG_audio_level;
+  config.abs_send_time = FLAG_abs_send_time;
+  config.transport_seq_no = FLAG_transport_seq_no;
+  config.video_content_type = FLAG_video_content_type;
+  config.video_timing = FLAG_video_timing;
+  config.matlabplot = FLAG_matlabplot;
+  config.pythonplot = FLAG_pythonplot;
+  config.textlog = FLAG_textlog;
+  config.concealment_events = FLAG_concealment_events;
+  config.max_nr_packets_in_buffer = FLAG_max_nr_packets_in_buffer;
+  config.enable_fast_accelerate = FLAG_enable_fast_accelerate;
+  // Check if an SSRC value was provided.
+  if (strlen(FLAG_ssrc) > 0) {
+    uint32_t ssrc;
+    RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed.";
+    config.ssrc_filter = absl::make_optional(ssrc);
+  }
+
   std::unique_ptr<webrtc::test::NetEqTest> test =
-      factory.InitializeTest(argv[1], argv[2]);
+      factory.InitializeTest(argv[1], argv[2], config);
   test->Run();
   return 0;
 }
diff --git a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc
index 1a52176..291fc24 100644
--- a/modules/audio_coding/neteq/tools/neteq_stats_getter.cc
+++ b/modules/audio_coding/neteq/tools/neteq_stats_getter.cc
@@ -16,7 +16,7 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/strings/string_builder.h"
-#include "rtc_base/timeutils.h"
+#include "rtc_base/time_utils.h"
 
 namespace webrtc {
 namespace test {
diff --git a/modules/audio_coding/neteq/tools/neteq_test.cc b/modules/audio_coding/neteq/tools/neteq_test.cc
index 421f380..97e71bf 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test.cc
@@ -10,9 +10,10 @@
 
 #include "modules/audio_coding/neteq/tools/neteq_test.h"
 
+#include <iomanip>
 #include <iostream>
 
-#include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
 
 namespace webrtc {
 namespace test {
@@ -50,20 +51,21 @@
 }
 
 NetEqTest::NetEqTest(const NetEq::Config& config,
+                     rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
                      const DecoderMap& codecs,
-                     const ExtDecoderMap& ext_codecs,
+                     std::unique_ptr<std::ofstream> text_log,
                      std::unique_ptr<NetEqInput> input,
                      std::unique_ptr<AudioSink> output,
                      Callbacks callbacks)
-    : neteq_(NetEq::Create(config, CreateBuiltinAudioDecoderFactory())),
+    : neteq_(NetEq::Create(config, decoder_factory)),
       input_(std::move(input)),
       output_(std::move(output)),
       callbacks_(callbacks),
-      sample_rate_hz_(config.sample_rate_hz) {
+      sample_rate_hz_(config.sample_rate_hz),
+      text_log_(std::move(text_log)) {
   RTC_CHECK(!config.enable_muted_state)
       << "The code does not handle enable_muted_state";
   RegisterDecoders(codecs);
-  RegisterExternalDecoders(ext_codecs);
 }
 
 NetEqTest::~NetEqTest() = default;
@@ -117,7 +119,36 @@
         current_state_.packet_iat_ms.push_back(time_now_ms -
                                                *last_packet_time_ms_);
       }
+      if (text_log_) {
+        const auto ops_state = neteq_->GetOperationsAndState();
+        const auto delta_wallclock =
+            last_packet_time_ms_ ? (time_now_ms - *last_packet_time_ms_) : -1;
+        const auto delta_timestamp =
+            last_packet_timestamp_
+                ? (static_cast<int64_t>(packet_data->header.timestamp) -
+                   *last_packet_timestamp_) *
+                      1000 / sample_rate_hz_
+                : -1;
+        const auto packet_size_bytes =
+            packet_data->payload.size() == 12
+                ? ByteReader<uint32_t>::ReadLittleEndian(
+                      &packet_data->payload[8])
+                : -1;
+        *text_log_ << "Packet   - wallclock: " << std::setw(5) << time_now_ms
+                   << ", delta wc: " << std::setw(4) << delta_wallclock
+                   << ", seq_no: " << packet_data->header.sequenceNumber
+                   << ", timestamp: " << std::setw(10)
+                   << packet_data->header.timestamp
+                   << ", delta ts: " << std::setw(4) << delta_timestamp
+                   << ", size: " << std::setw(5) << packet_size_bytes
+                   << ", frame size: " << std::setw(3)
+                   << ops_state.current_frame_size_ms
+                   << ", buffer size: " << std::setw(4)
+                   << ops_state.current_buffer_size_ms << std::endl;
+      }
       last_packet_time_ms_ = absl::make_optional<int>(time_now_ms);
+      last_packet_timestamp_ =
+          absl::make_optional<uint32_t>(packet_data->header.timestamp);
     }
 
     // Check if it is time to get output audio.
@@ -186,6 +217,39 @@
         // Consider the whole frame to be the result of normal playout.
         result.action_times_ms[Action::kNormal] = 10;
       }
+      auto lifetime_stats = LifetimeStats();
+      if (text_log_) {
+        const bool plc =
+            (out_frame.speech_type_ == AudioFrame::SpeechType::kPLC) ||
+            (out_frame.speech_type_ == AudioFrame::SpeechType::kPLCCNG);
+        const bool cng = out_frame.speech_type_ == AudioFrame::SpeechType::kCNG;
+        const bool voice_concealed =
+            lifetime_stats.voice_concealed_samples >
+            prev_lifetime_stats_.voice_concealed_samples;
+        *text_log_ << "GetAudio - wallclock: " << std::setw(5) << time_now_ms
+                   << ", delta wc: " << std::setw(4)
+                   << (input_->NextEventTime().value_or(time_now_ms) -
+                       start_time_ms)
+                   << ", CNG: " << cng << ", PLC: " << plc
+                   << ", voice concealed: " << voice_concealed
+                   << ", buffer size: " << std::setw(4)
+                   << current_state_.current_delay_ms << std::endl;
+        if (operations_state.discarded_primary_packets >
+            prev_ops_state_.discarded_primary_packets) {
+          *text_log_ << "Discarded "
+                     << (operations_state.discarded_primary_packets -
+                         prev_ops_state_.discarded_primary_packets)
+                     << " primary packets." << std::endl;
+        }
+        if (operations_state.packet_buffer_flushes >
+            prev_ops_state_.packet_buffer_flushes) {
+          *text_log_ << "Flushed packet buffer "
+                     << (operations_state.packet_buffer_flushes -
+                         prev_ops_state_.packet_buffer_flushes)
+                     << " times." << std::endl;
+        }
+      }
+      prev_lifetime_stats_ = lifetime_stats;
       result.is_simulation_finished = input_->ended();
       prev_ops_state_ = operations_state;
       return result;
@@ -217,53 +281,40 @@
 
 NetEqTest::DecoderMap NetEqTest::StandardDecoderMap() {
   DecoderMap codecs = {
-    {0, std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu")},
-    {8, std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma")},
+    {0, SdpAudioFormat("pcmu", 8000, 1)},
+    {8, SdpAudioFormat("pcma", 8000, 1)},
 #ifdef WEBRTC_CODEC_ILBC
-    {102, std::make_pair(NetEqDecoder::kDecoderILBC, "ilbc")},
+    {102, SdpAudioFormat("ilbc", 8000, 1)},
 #endif
-    {103, std::make_pair(NetEqDecoder::kDecoderISAC, "isac")},
+    {103, SdpAudioFormat("isac", 16000, 1)},
 #if !defined(WEBRTC_ANDROID)
-    {104, std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb")},
+    {104, SdpAudioFormat("isac", 32000, 1)},
 #endif
 #ifdef WEBRTC_CODEC_OPUS
-    {111, std::make_pair(NetEqDecoder::kDecoderOpus, "opus")},
+    {111, SdpAudioFormat("opus", 48000, 2)},
 #endif
-    {93, std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb")},
-    {94, std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb")},
-    {95, std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32")},
-    {96, std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48")},
-    {9, std::make_pair(NetEqDecoder::kDecoderG722, "g722")},
-    {106, std::make_pair(NetEqDecoder::kDecoderAVT, "avt")},
-    {114, std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16")},
-    {115, std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32")},
-    {116, std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48")},
-    {117, std::make_pair(NetEqDecoder::kDecoderRED, "red")},
-    {13, std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb")},
-    {98, std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb")},
-    {99, std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32")},
-    {100, std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48")}
+    {93, SdpAudioFormat("l16", 8000, 1)},
+    {94, SdpAudioFormat("l16", 16000, 1)},
+    {95, SdpAudioFormat("l16", 32000, 1)},
+    {96, SdpAudioFormat("l16", 48000, 1)},
+    {9, SdpAudioFormat("g722", 8000, 1)},
+    {106, SdpAudioFormat("telephone-event", 8000, 1)},
+    {114, SdpAudioFormat("telephone-event", 16000, 1)},
+    {115, SdpAudioFormat("telephone-event", 32000, 1)},
+    {116, SdpAudioFormat("telephone-event", 48000, 1)},
+    {117, SdpAudioFormat("red", 8000, 1)},
+    {13, SdpAudioFormat("cn", 8000, 1)},
+    {98, SdpAudioFormat("cn", 16000, 1)},
+    {99, SdpAudioFormat("cn", 32000, 1)},
+    {100, SdpAudioFormat("cn", 48000, 1)}
   };
   return codecs;
 }
 
 void NetEqTest::RegisterDecoders(const DecoderMap& codecs) {
   for (const auto& c : codecs) {
-    RTC_CHECK_EQ(
-        neteq_->RegisterPayloadType(c.second.first, c.second.second, c.first),
-        NetEq::kOK)
-        << "Cannot register " << c.second.second << " to payload type "
-        << c.first;
-  }
-}
-
-void NetEqTest::RegisterExternalDecoders(const ExtDecoderMap& codecs) {
-  for (const auto& c : codecs) {
-    RTC_CHECK_EQ(
-        neteq_->RegisterExternalDecoder(c.second.decoder, c.second.codec,
-                                        c.second.codec_name, c.first),
-        NetEq::kOK)
-        << "Cannot register " << c.second.codec_name << " to payload type "
+    RTC_CHECK(neteq_->RegisterPayloadType(c.first, c.second))
+        << "Cannot register " << c.second.name << " to payload type "
         << c.first;
   }
 }
diff --git a/modules/audio_coding/neteq/tools/neteq_test.h b/modules/audio_coding/neteq/tools/neteq_test.h
index 23d7c22..5261dd7 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.h
+++ b/modules/audio_coding/neteq/tools/neteq_test.h
@@ -11,12 +11,14 @@
 #ifndef MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_
 #define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_TEST_H_
 
+#include <fstream>
 #include <map>
 #include <memory>
 #include <string>
 #include <utility>
 
 #include "absl/types/optional.h"
+#include "api/audio_codecs/audio_decoder_factory.h"
 #include "api/test/neteq_simulator.h"
 #include "modules/audio_coding/neteq/include/neteq.h"
 #include "modules/audio_coding/neteq/tools/audio_sink.h"
@@ -65,15 +67,7 @@
 // directed to an AudioSink object.
 class NetEqTest : public NetEqSimulator {
  public:
-  using DecoderMap = std::map<int, std::pair<NetEqDecoder, std::string> >;
-
-  struct ExternalDecoderInfo {
-    AudioDecoder* decoder;
-    NetEqDecoder codec;
-    std::string codec_name;
-  };
-
-  using ExtDecoderMap = std::map<int, ExternalDecoderInfo>;
+  using DecoderMap = std::map<int, SdpAudioFormat>;
 
   struct Callbacks {
     NetEqTestErrorCallback* error_callback = nullptr;
@@ -85,8 +79,9 @@
   // Sets up the test with given configuration, codec mappings, input, ouput,
   // and callback objects for error reporting.
   NetEqTest(const NetEq::Config& config,
+            rtc::scoped_refptr<AudioDecoderFactory> decoder_factory,
             const DecoderMap& codecs,
-            const ExtDecoderMap& ext_codecs,
+            std::unique_ptr<std::ofstream> text_log,
             std::unique_ptr<NetEqInput> input,
             std::unique_ptr<AudioSink> output,
             Callbacks callbacks);
@@ -111,7 +106,6 @@
 
  private:
   void RegisterDecoders(const DecoderMap& codecs);
-  void RegisterExternalDecoders(const ExtDecoderMap& codecs);
   absl::optional<Action> next_action_;
   absl::optional<int> last_packet_time_ms_;
   std::unique_ptr<NetEq> neteq_;
@@ -121,6 +115,9 @@
   int sample_rate_hz_;
   NetEqState current_state_;
   NetEqOperationsAndState prev_ops_state_;
+  NetEqLifetimeStatistics prev_lifetime_stats_;
+  absl::optional<uint32_t> last_packet_timestamp_;
+  std::unique_ptr<std::ofstream> text_log_;
 };
 
 }  // namespace test
diff --git a/modules/audio_coding/neteq/tools/neteq_test_factory.cc b/modules/audio_coding/neteq/tools/neteq_test_factory.cc
index aa956ce..1d38bc4 100644
--- a/modules/audio_coding/neteq/tools/neteq_test_factory.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test_factory.cc
@@ -14,6 +14,7 @@
 #include <limits.h>  // For ULONG_MAX returned by strtoul.
 #include <stdio.h>
 #include <stdlib.h>  // For strto