gfe-relnote: In QUIC, Enable multiple packet number support in uber_received_packet_manager. Not used yet, not protected.

PiperOrigin-RevId: 239821420
Change-Id: Iae12d214d8ecf65dfe4918f12e528ea1001ce5f2
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index f213d35..2c7df67 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -357,6 +357,7 @@
           GetQuicReloadableFlag(quic_validate_packet_number_post_decryption)),
       use_uber_received_packet_manager_(
           received_packet_manager_.decide_when_to_send_acks() &&
+          validate_packet_number_post_decryption_ &&
           GetQuicReloadableFlag(quic_use_uber_received_packet_manager)) {
   if (ack_mode_ == ACK_DECIMATION) {
     QUIC_RELOADABLE_FLAG_COUNT(quic_enable_ack_decimation);
@@ -825,7 +826,7 @@
     const bool is_awaiting =
         use_uber_received_packet_manager_
             ? uber_received_packet_manager_.IsAwaitingPacket(
-                  header.packet_number)
+                  last_decrypted_packet_level_, header.packet_number)
             : received_packet_manager_.IsAwaitingPacket(header.packet_number);
     if (!is_awaiting) {
       if (framer_.IsIetfStatelessResetPacket(header)) {
@@ -959,7 +960,8 @@
   // frames, since the processing may result in sending a bundled ack.
   if (use_uber_received_packet_manager_) {
     uber_received_packet_manager_.RecordPacketReceived(
-        last_header_, time_of_last_received_packet_);
+        last_decrypted_packet_level_, last_header_,
+        time_of_last_received_packet_);
   } else {
     received_packet_manager_.RecordPacketReceived(
         last_header_, time_of_last_received_packet_);
@@ -1167,7 +1169,8 @@
 
   largest_seen_packet_with_stop_waiting_ = last_header_.packet_number;
   if (use_uber_received_packet_manager_) {
-    uber_received_packet_manager_.DontWaitForPacketsBefore(frame.least_unacked);
+    uber_received_packet_manager_.DontWaitForPacketsBefore(
+        last_decrypted_packet_level_, frame.least_unacked);
   } else {
     received_packet_manager_.DontWaitForPacketsBefore(frame.least_unacked);
   }
@@ -1490,9 +1493,9 @@
   if (received_packet_manager_.decide_when_to_send_acks()) {
     if (use_uber_received_packet_manager_) {
       uber_received_packet_manager_.MaybeUpdateAckTimeout(
-          should_last_packet_instigate_acks_, last_header_.packet_number,
-          time_of_last_received_packet_, clock_->ApproximateNow(),
-          sent_packet_manager_.GetRttStats(),
+          should_last_packet_instigate_acks_, last_decrypted_packet_level_,
+          last_header_.packet_number, time_of_last_received_packet_,
+          clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
           sent_packet_manager_.delayed_ack_time());
     } else {
       received_packet_manager_.MaybeUpdateAckTimeout(
@@ -1656,6 +1659,7 @@
 const QuicFrame QuicConnection::GetUpdatedAckFrame() {
   if (use_uber_received_packet_manager_) {
     return uber_received_packet_manager_.GetUpdatedAckFrame(
+        QuicUtils::GetPacketNumberSpace(encryption_level_),
         clock_->ApproximateNow());
   }
   return received_packet_manager_.GetUpdatedAckFrame(clock_->ApproximateNow());
@@ -1961,7 +1965,8 @@
   if (received_packet_manager_.decide_when_to_send_acks()) {
     const QuicTime ack_timeout =
         use_uber_received_packet_manager_
-            ? uber_received_packet_manager_.GetAckTimeout()
+            ? uber_received_packet_manager_.GetAckTimeout(
+                  QuicUtils::GetPacketNumberSpace(encryption_level_))
             : received_packet_manager_.ack_timeout();
     if (ack_timeout.IsInitialized() &&
         ack_timeout <= clock_->ApproximateNow()) {
@@ -2088,7 +2093,8 @@
   if (validate_packet_number_post_decryption_) {
     const bool is_awaiting =
         use_uber_received_packet_manager_
-            ? uber_received_packet_manager_.IsAwaitingPacket(packet_number)
+            ? uber_received_packet_manager_.IsAwaitingPacket(
+                  last_decrypted_packet_level_, packet_number)
             : received_packet_manager_.IsAwaitingPacket(packet_number);
     if (!is_awaiting) {
       QUIC_DLOG(INFO) << ENDPOINT << "Packet " << packet_number
@@ -2273,7 +2279,9 @@
   if (received_packet_manager_.decide_when_to_send_acks()) {
     if (use_uber_received_packet_manager_) {
       has_pending_ack =
-          uber_received_packet_manager_.GetAckTimeout().IsInitialized();
+          uber_received_packet_manager_
+              .GetAckTimeout(QuicUtils::GetPacketNumberSpace(encryption_level_))
+              .IsInitialized();
     } else {
       has_pending_ack = received_packet_manager_.ack_timeout().IsInitialized();
     }
@@ -3271,7 +3279,9 @@
       if (connection_->received_packet_manager_.decide_when_to_send_acks()) {
         const QuicTime ack_timeout =
             connection_->use_uber_received_packet_manager_
-                ? connection_->uber_received_packet_manager_.GetAckTimeout()
+                ? connection_->uber_received_packet_manager_.GetAckTimeout(
+                      QuicUtils::GetPacketNumberSpace(
+                          connection_->encryption_level_))
                 : connection_->received_packet_manager_.ack_timeout();
         if (ack_timeout.IsInitialized()) {
           if (ack_timeout <= connection_->clock_->ApproximateNow() &&
@@ -3597,7 +3607,7 @@
 
 bool QuicConnection::ack_frame_updated() const {
   if (use_uber_received_packet_manager_) {
-    return uber_received_packet_manager_.AckFrameUpdated();
+    return uber_received_packet_manager_.IsAckFrameUpdated();
   }
   return received_packet_manager_.ack_frame_updated();
 }
@@ -3746,6 +3756,7 @@
   if (no_stop_waiting_frames_) {
     if (use_uber_received_packet_manager_) {
       uber_received_packet_manager_.DontWaitForPacketsBefore(
+          last_decrypted_packet_level_,
           sent_packet_manager_.largest_packet_peer_knows_is_acked());
     } else {
       received_packet_manager_.DontWaitForPacketsBefore(
@@ -3818,7 +3829,7 @@
   num_packets_received_since_last_ack_sent_ = 0;
   if (received_packet_manager_.decide_when_to_send_acks()) {
     if (use_uber_received_packet_manager_) {
-      uber_received_packet_manager_.ResetAckStates();
+      uber_received_packet_manager_.ResetAckStates(encryption_level_);
     } else {
       received_packet_manager_.ResetAckStates();
     }
@@ -3905,7 +3916,8 @@
 
 QuicPacketNumber QuicConnection::GetLargestReceivedPacket() const {
   if (use_uber_received_packet_manager_) {
-    return uber_received_packet_manager_.GetLargestObserved();
+    return uber_received_packet_manager_.GetLargestObserved(
+        last_decrypted_packet_level_);
   }
   return received_packet_manager_.GetLargestObserved();
 }
diff --git a/quic/core/quic_received_packet_manager.cc b/quic/core/quic_received_packet_manager.cc
index 82984eb..528b866 100644
--- a/quic/core/quic_received_packet_manager.cc
+++ b/quic/core/quic_received_packet_manager.cc
@@ -39,6 +39,9 @@
 const float kShortAckDecimationDelay = 0.125;
 }  // namespace
 
+QuicReceivedPacketManager::QuicReceivedPacketManager()
+    : QuicReceivedPacketManager(nullptr) {}
+
 QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats)
     : ack_frame_updated_(false),
       max_ack_ranges_(0),
diff --git a/quic/core/quic_received_packet_manager.h b/quic/core/quic_received_packet_manager.h
index 8eb8cac..7c9bd7f 100644
--- a/quic/core/quic_received_packet_manager.h
+++ b/quic/core/quic_received_packet_manager.h
@@ -25,6 +25,7 @@
 // Records all received packets by a connection.
 class QUIC_EXPORT_PRIVATE QuicReceivedPacketManager {
  public:
+  QuicReceivedPacketManager();
   explicit QuicReceivedPacketManager(QuicConnectionStats* stats);
   QuicReceivedPacketManager(const QuicReceivedPacketManager&) = delete;
   QuicReceivedPacketManager& operator=(const QuicReceivedPacketManager&) =
@@ -91,6 +92,8 @@
   // least one packet has been received.
   QuicPacketNumber PeerFirstSendingPacketNumber() const;
 
+  void set_connection_stats(QuicConnectionStats* stats) { stats_ = stats; }
+
   // For logging purposes.
   const QuicAckFrame& ack_frame() const { return ack_frame_; }
 
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc
index 63b9b85..56cfe87 100644
--- a/quic/core/quic_utils.cc
+++ b/quic/core/quic_utils.cc
@@ -549,5 +549,21 @@
   }
 }
 
+// static
+EncryptionLevel QuicUtils::GetEncryptionLevel(
+    PacketNumberSpace packet_number_space) {
+  switch (packet_number_space) {
+    case INITIAL_DATA:
+      return ENCRYPTION_INITIAL;
+    case HANDSHAKE_DATA:
+      return ENCRYPTION_HANDSHAKE;
+    case APPLICATION_DATA:
+      return ENCRYPTION_FORWARD_SECURE;
+    default:
+      DCHECK(false);
+      return NUM_ENCRYPTION_LEVELS;
+  }
+}
+
 #undef RETURN_STRING_LITERAL  // undef for jumbo builds
 }  // namespace quic
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h
index 515056c..340f474 100644
--- a/quic/core/quic_utils.h
+++ b/quic/core/quic_utils.h
@@ -183,6 +183,10 @@
   // Determines packet number space from |encryption_level|.
   static PacketNumberSpace GetPacketNumberSpace(
       EncryptionLevel encryption_level);
+
+  // Determines encryption level to send packets in |packet_number_space|.
+  static EncryptionLevel GetEncryptionLevel(
+      PacketNumberSpace packet_number_space);
 };
 
 }  // namespace quic
diff --git a/quic/core/uber_received_packet_manager.cc b/quic/core/uber_received_packet_manager.cc
index b730474..00c430e 100644
--- a/quic/core/uber_received_packet_manager.cc
+++ b/quic/core/uber_received_packet_manager.cc
@@ -4,105 +4,214 @@
 
 #include "net/third_party/quiche/src/quic/core/uber_received_packet_manager.h"
 
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+
 namespace quic {
 
 UberReceivedPacketManager::UberReceivedPacketManager(QuicConnectionStats* stats)
-    : received_packet_manager_(stats) {}
+    : supports_multiple_packet_number_spaces_(false) {
+  for (auto& received_packet_manager : received_packet_managers_) {
+    received_packet_manager.set_connection_stats(stats);
+  }
+}
 
 UberReceivedPacketManager::~UberReceivedPacketManager() {}
 
 void UberReceivedPacketManager::SetFromConfig(const QuicConfig& config,
                                               Perspective perspective) {
-  received_packet_manager_.SetFromConfig(config, perspective);
+  for (auto& received_packet_manager : received_packet_managers_) {
+    received_packet_manager.SetFromConfig(config, perspective);
+  }
 }
 
 bool UberReceivedPacketManager::IsAwaitingPacket(
+    EncryptionLevel decrypted_packet_level,
     QuicPacketNumber packet_number) const {
-  return received_packet_manager_.IsAwaitingPacket(packet_number);
+  if (!supports_multiple_packet_number_spaces_) {
+    return received_packet_managers_[0].IsAwaitingPacket(packet_number);
+  }
+  return received_packet_managers_[QuicUtils::GetPacketNumberSpace(
+                                       decrypted_packet_level)]
+      .IsAwaitingPacket(packet_number);
 }
 
 const QuicFrame UberReceivedPacketManager::GetUpdatedAckFrame(
+    PacketNumberSpace packet_number_space,
     QuicTime approximate_now) {
-  return received_packet_manager_.GetUpdatedAckFrame(approximate_now);
+  if (!supports_multiple_packet_number_spaces_) {
+    return received_packet_managers_[0].GetUpdatedAckFrame(approximate_now);
+  }
+  return received_packet_managers_[packet_number_space].GetUpdatedAckFrame(
+      approximate_now);
 }
 
 void UberReceivedPacketManager::RecordPacketReceived(
+    EncryptionLevel decrypted_packet_level,
     const QuicPacketHeader& header,
     QuicTime receipt_time) {
-  received_packet_manager_.RecordPacketReceived(header, receipt_time);
+  if (!supports_multiple_packet_number_spaces_) {
+    received_packet_managers_[0].RecordPacketReceived(header, receipt_time);
+    return;
+  }
+  received_packet_managers_[QuicUtils::GetPacketNumberSpace(
+                                decrypted_packet_level)]
+      .RecordPacketReceived(header, receipt_time);
 }
 
 void UberReceivedPacketManager::DontWaitForPacketsBefore(
+    EncryptionLevel decrypted_packet_level,
     QuicPacketNumber least_unacked) {
-  received_packet_manager_.DontWaitForPacketsBefore(least_unacked);
+  if (!supports_multiple_packet_number_spaces_) {
+    received_packet_managers_[0].DontWaitForPacketsBefore(least_unacked);
+    return;
+  }
+  received_packet_managers_[QuicUtils::GetPacketNumberSpace(
+                                decrypted_packet_level)]
+      .DontWaitForPacketsBefore(least_unacked);
 }
 
 void UberReceivedPacketManager::MaybeUpdateAckTimeout(
     bool should_last_packet_instigate_acks,
+    EncryptionLevel decrypted_packet_level,
     QuicPacketNumber last_received_packet_number,
     QuicTime time_of_last_received_packet,
     QuicTime now,
     const RttStats* rtt_stats,
     QuicTime::Delta delayed_ack_time) {
-  received_packet_manager_.MaybeUpdateAckTimeout(
-      should_last_packet_instigate_acks, last_received_packet_number,
-      time_of_last_received_packet, now, rtt_stats, delayed_ack_time);
+  if (!supports_multiple_packet_number_spaces_) {
+    received_packet_managers_[0].MaybeUpdateAckTimeout(
+        should_last_packet_instigate_acks, last_received_packet_number,
+        time_of_last_received_packet, now, rtt_stats, delayed_ack_time);
+    return;
+  }
+  received_packet_managers_[QuicUtils::GetPacketNumberSpace(
+                                decrypted_packet_level)]
+      .MaybeUpdateAckTimeout(
+          should_last_packet_instigate_acks, last_received_packet_number,
+          time_of_last_received_packet, now, rtt_stats, delayed_ack_time);
 }
 
-void UberReceivedPacketManager::ResetAckStates() {
-  received_packet_manager_.ResetAckStates();
+void UberReceivedPacketManager::ResetAckStates(
+    EncryptionLevel encryption_level) {
+  if (!supports_multiple_packet_number_spaces_) {
+    received_packet_managers_[0].ResetAckStates();
+    return;
+  }
+  received_packet_managers_[QuicUtils::GetPacketNumberSpace(encryption_level)]
+      .ResetAckStates();
 }
 
-bool UberReceivedPacketManager::AckFrameUpdated() const {
-  return received_packet_manager_.ack_frame_updated();
+void UberReceivedPacketManager::EnableMultiplePacketNumberSpacesSupport() {
+  if (supports_multiple_packet_number_spaces_) {
+    QUIC_BUG << "Multiple packet number spaces has already been enabled";
+    return;
+  }
+  if (received_packet_managers_[0].GetLargestObserved().IsInitialized()) {
+    QUIC_BUG << "Try to enable multiple packet number spaces support after any "
+                "packet has been received.";
+    return;
+  }
+
+  supports_multiple_packet_number_spaces_ = true;
 }
 
-QuicPacketNumber UberReceivedPacketManager::GetLargestObserved() const {
-  return received_packet_manager_.GetLargestObserved();
+bool UberReceivedPacketManager::IsAckFrameUpdated() const {
+  if (!supports_multiple_packet_number_spaces_) {
+    return received_packet_managers_[0].ack_frame_updated();
+  }
+  for (const auto& received_packet_manager : received_packet_managers_) {
+    if (received_packet_manager.ack_frame_updated()) {
+      return true;
+    }
+  }
+  return false;
 }
 
-QuicTime UberReceivedPacketManager::GetAckTimeout() const {
-  return received_packet_manager_.ack_timeout();
+QuicPacketNumber UberReceivedPacketManager::GetLargestObserved(
+    EncryptionLevel decrypted_packet_level) const {
+  if (!supports_multiple_packet_number_spaces_) {
+    return received_packet_managers_[0].GetLargestObserved();
+  }
+  return received_packet_managers_[QuicUtils::GetPacketNumberSpace(
+                                       decrypted_packet_level)]
+      .GetLargestObserved();
+}
+
+QuicTime UberReceivedPacketManager::GetAckTimeout(
+    PacketNumberSpace packet_number_space) const {
+  if (!supports_multiple_packet_number_spaces_) {
+    return received_packet_managers_[0].ack_timeout();
+  }
+  return received_packet_managers_[packet_number_space].ack_timeout();
+}
+
+QuicTime UberReceivedPacketManager::GetEarliestAckTimeout() const {
+  DCHECK(supports_multiple_packet_number_spaces_);
+  QuicTime ack_timeout = QuicTime::Zero();
+  // Returns the earliest non-zero ack timeout.
+  for (const auto& received_packet_manager : received_packet_managers_) {
+    const QuicTime timeout = received_packet_manager.ack_timeout();
+    if (!ack_timeout.IsInitialized()) {
+      ack_timeout = timeout;
+      continue;
+    }
+    if (timeout.IsInitialized()) {
+      ack_timeout = std::min(ack_timeout, timeout);
+    }
+  }
+  return ack_timeout;
 }
 
 QuicPacketNumber UberReceivedPacketManager::PeerFirstSendingPacketNumber()
     const {
-  return received_packet_manager_.PeerFirstSendingPacketNumber();
+  DCHECK(!supports_multiple_packet_number_spaces_);
+  return received_packet_managers_[0].PeerFirstSendingPacketNumber();
 }
 
 QuicPacketNumber UberReceivedPacketManager::peer_least_packet_awaiting_ack()
     const {
-  return received_packet_manager_.peer_least_packet_awaiting_ack();
+  DCHECK(!supports_multiple_packet_number_spaces_);
+  return received_packet_managers_[0].peer_least_packet_awaiting_ack();
 }
 
 size_t UberReceivedPacketManager::min_received_before_ack_decimation() const {
-  return received_packet_manager_.min_received_before_ack_decimation();
+  return received_packet_managers_[0].min_received_before_ack_decimation();
 }
 
 void UberReceivedPacketManager::set_min_received_before_ack_decimation(
     size_t new_value) {
-  received_packet_manager_.set_min_received_before_ack_decimation(new_value);
+  for (auto& received_packet_manager : received_packet_managers_) {
+    received_packet_manager.set_min_received_before_ack_decimation(new_value);
+  }
 }
 
 size_t UberReceivedPacketManager::ack_frequency_before_ack_decimation() const {
-  return received_packet_manager_.ack_frequency_before_ack_decimation();
+  return received_packet_managers_[0].ack_frequency_before_ack_decimation();
 }
 
 void UberReceivedPacketManager::set_ack_frequency_before_ack_decimation(
     size_t new_value) {
-  received_packet_manager_.set_ack_frequency_before_ack_decimation(new_value);
+  for (auto& received_packet_manager : received_packet_managers_) {
+    received_packet_manager.set_ack_frequency_before_ack_decimation(new_value);
+  }
 }
 
 const QuicAckFrame& UberReceivedPacketManager::ack_frame() const {
-  return received_packet_manager_.ack_frame();
+  DCHECK(!supports_multiple_packet_number_spaces_);
+  return received_packet_managers_[0].ack_frame();
 }
 
 void UberReceivedPacketManager::set_max_ack_ranges(size_t max_ack_ranges) {
-  received_packet_manager_.set_max_ack_ranges(max_ack_ranges);
+  for (auto& received_packet_manager : received_packet_managers_) {
+    received_packet_manager.set_max_ack_ranges(max_ack_ranges);
+  }
 }
 
 void UberReceivedPacketManager::set_save_timestamps(bool save_timestamps) {
-  received_packet_manager_.set_save_timestamps(save_timestamps);
+  for (auto& received_packet_manager : received_packet_managers_) {
+    received_packet_manager.set_save_timestamps(save_timestamps);
+  }
 }
 
 }  // namespace quic
diff --git a/quic/core/uber_received_packet_manager.h b/quic/core/uber_received_packet_manager.h
index 367a7c0..62348b9 100644
--- a/quic/core/uber_received_packet_manager.h
+++ b/quic/core/uber_received_packet_manager.h
@@ -9,7 +9,9 @@
 
 namespace quic {
 
-// This class simply wraps a single received packet manager.
+// This class comprises multiple received packet managers, one per packet number
+// space. Please note, if multiple packet number spaces is not supported, only
+// one received packet manager will be used.
 class QUIC_EXPORT_PRIVATE UberReceivedPacketManager {
  public:
   explicit UberReceivedPacketManager(QuicConnectionStats* stats);
@@ -21,23 +23,28 @@
   void SetFromConfig(const QuicConfig& config, Perspective perspective);
 
   // Checks if we are still waiting for the packet with |packet_number|.
-  bool IsAwaitingPacket(QuicPacketNumber packet_number) const;
+  bool IsAwaitingPacket(EncryptionLevel decrypted_packet_level,
+                        QuicPacketNumber packet_number) const;
 
   // Called after a packet has been successfully decrypted and its header has
   // been parsed.
-  void RecordPacketReceived(const QuicPacketHeader& header,
+  void RecordPacketReceived(EncryptionLevel decrypted_packet_level,
+                            const QuicPacketHeader& header,
                             QuicTime receipt_time);
 
   // Retrieves a frame containing a QuicAckFrame. The ack frame must be
   // serialized before another packet is received, or it will change.
-  const QuicFrame GetUpdatedAckFrame(QuicTime approximate_now);
+  const QuicFrame GetUpdatedAckFrame(PacketNumberSpace packet_number_space,
+                                     QuicTime approximate_now);
 
   // Stop ACKing packets before |least_unacked|.
-  void DontWaitForPacketsBefore(QuicPacketNumber least_unacked);
+  void DontWaitForPacketsBefore(EncryptionLevel decrypted_packet_level,
+                                QuicPacketNumber least_unacked);
 
   // Called after header of last received packet has been successfully processed
   // to update ACK timeout.
   void MaybeUpdateAckTimeout(bool should_last_packet_instigate_acks,
+                             EncryptionLevel decrypted_packet_level,
                              QuicPacketNumber last_received_packet_number,
                              QuicTime time_of_last_received_packet,
                              QuicTime now,
@@ -45,17 +52,24 @@
                              QuicTime::Delta delayed_ack_time);
 
   // Resets ACK related states, called after an ACK is successfully sent.
-  void ResetAckStates();
+  void ResetAckStates(EncryptionLevel encryption_level);
+
+  // Called to enable multiple packet number support.
+  void EnableMultiplePacketNumberSpacesSupport();
 
   // Returns true if ACK frame has been updated since GetUpdatedAckFrame was
   // last called.
-  bool AckFrameUpdated() const;
+  bool IsAckFrameUpdated() const;
 
   // Returns the largest received packet number.
-  QuicPacketNumber GetLargestObserved() const;
+  QuicPacketNumber GetLargestObserved(
+      EncryptionLevel decrypted_packet_level) const;
 
-  // Returns current ACK timeout.
-  QuicTime GetAckTimeout() const;
+  // Returns ACK timeout of |packet_number_space|.
+  QuicTime GetAckTimeout(PacketNumberSpace packet_number_space) const;
+
+  // Get the earliest ack_timeout of all packet number spaces.
+  QuicTime GetEarliestAckTimeout() const;
 
   // Returns peer first sending packet number to our best knowledge.
   QuicPacketNumber PeerFirstSendingPacketNumber() const;
@@ -68,6 +82,10 @@
   size_t ack_frequency_before_ack_decimation() const;
   void set_ack_frequency_before_ack_decimation(size_t new_value);
 
+  bool supports_multiple_packet_number_spaces() const {
+    return supports_multiple_packet_number_spaces_;
+  }
+
   // For logging purposes.
   const QuicAckFrame& ack_frame() const;
 
@@ -79,7 +97,12 @@
   friend class test::QuicConnectionPeer;
   friend class test::UberReceivedPacketManagerPeer;
 
-  QuicReceivedPacketManager received_packet_manager_;
+  // One received packet manager per packet number space. If
+  // supports_multiple_packet_number_spaces_ is false, only the first (0 index)
+  // received_packet_manager is used.
+  QuicReceivedPacketManager received_packet_managers_[NUM_PACKET_NUMBER_SPACES];
+
+  bool supports_multiple_packet_number_spaces_;
 };
 
 }  // namespace quic
diff --git a/quic/core/uber_received_packet_manager_test.cc b/quic/core/uber_received_packet_manager_test.cc
index 4ffb03c..b717178 100644
--- a/quic/core/uber_received_packet_manager_test.cc
+++ b/quic/core/uber_received_packet_manager_test.cc
@@ -7,6 +7,7 @@
 #include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
 #include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
@@ -17,19 +18,24 @@
 class UberReceivedPacketManagerPeer {
  public:
   static void SetAckMode(UberReceivedPacketManager* manager, AckMode ack_mode) {
-    manager->received_packet_manager_.ack_mode_ = ack_mode;
+    for (auto& received_packet_manager : manager->received_packet_managers_) {
+      received_packet_manager.ack_mode_ = ack_mode;
+    }
   }
 
   static void SetFastAckAfterQuiescence(UberReceivedPacketManager* manager,
                                         bool fast_ack_after_quiescence) {
-    manager->received_packet_manager_.fast_ack_after_quiescence_ =
-        fast_ack_after_quiescence;
+    for (auto& received_packet_manager : manager->received_packet_managers_) {
+      received_packet_manager.fast_ack_after_quiescence_ =
+          fast_ack_after_quiescence;
+    }
   }
 
   static void SetAckDecimationDelay(UberReceivedPacketManager* manager,
                                     float ack_decimation_delay) {
-    manager->received_packet_manager_.ack_decimation_delay_ =
-        ack_decimation_delay;
+    for (auto& received_packet_manager : manager->received_packet_managers_) {
+      received_packet_manager.ack_decimation_delay_ = ack_decimation_delay;
+    }
   }
 };
 
@@ -52,31 +58,73 @@
   }
 
   void RecordPacketReceipt(uint64_t packet_number) {
-    RecordPacketReceipt(packet_number, QuicTime::Zero());
+    RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, packet_number);
   }
 
   void RecordPacketReceipt(uint64_t packet_number, QuicTime receipt_time) {
-    QuicPacketHeader header;
-    header.packet_number = QuicPacketNumber(packet_number);
-    manager_->RecordPacketReceived(header, receipt_time);
+    RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, packet_number, receipt_time);
   }
 
-  bool HasPendingAck() { return manager_->GetAckTimeout().IsInitialized(); }
+  void RecordPacketReceipt(EncryptionLevel decrypted_packet_level,
+                           uint64_t packet_number) {
+    RecordPacketReceipt(decrypted_packet_level, packet_number,
+                        QuicTime::Zero());
+  }
+
+  void RecordPacketReceipt(EncryptionLevel decrypted_packet_level,
+                           uint64_t packet_number,
+                           QuicTime receipt_time) {
+    QuicPacketHeader header;
+    header.packet_number = QuicPacketNumber(packet_number);
+    manager_->RecordPacketReceived(decrypted_packet_level, header,
+                                   receipt_time);
+  }
+
+  bool HasPendingAck() {
+    if (!manager_->supports_multiple_packet_number_spaces()) {
+      return manager_->GetAckTimeout(APPLICATION_DATA).IsInitialized();
+    }
+    return manager_->GetEarliestAckTimeout().IsInitialized();
+  }
 
   void MaybeUpdateAckTimeout(bool should_last_packet_instigate_acks,
                              uint64_t last_received_packet_number) {
+    MaybeUpdateAckTimeout(should_last_packet_instigate_acks,
+                          ENCRYPTION_FORWARD_SECURE,
+                          last_received_packet_number);
+  }
+
+  void MaybeUpdateAckTimeout(bool should_last_packet_instigate_acks,
+                             EncryptionLevel decrypted_packet_level,
+                             uint64_t last_received_packet_number) {
     manager_->MaybeUpdateAckTimeout(
-        should_last_packet_instigate_acks,
+        should_last_packet_instigate_acks, decrypted_packet_level,
         QuicPacketNumber(last_received_packet_number), clock_.ApproximateNow(),
         clock_.ApproximateNow(), &rtt_stats_, kDelayedAckTime);
   }
 
   void CheckAckTimeout(QuicTime time) {
-    DCHECK(HasPendingAck() && manager_->GetAckTimeout() == time);
-    if (time <= clock_.ApproximateNow()) {
-      // ACK timeout expires, send an ACK.
-      manager_->ResetAckStates();
-      DCHECK(!HasPendingAck());
+    DCHECK(HasPendingAck());
+    if (!manager_->supports_multiple_packet_number_spaces()) {
+      DCHECK(manager_->GetAckTimeout(APPLICATION_DATA) == time);
+      if (time <= clock_.ApproximateNow()) {
+        // ACK timeout expires, send an ACK.
+        manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE);
+        DCHECK(!HasPendingAck());
+      }
+      return;
+    }
+    DCHECK(manager_->GetEarliestAckTimeout() == time);
+    // Send all expired ACKs.
+    for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+      const QuicTime ack_timeout =
+          manager_->GetAckTimeout(static_cast<PacketNumberSpace>(i));
+      if (!ack_timeout.IsInitialized() ||
+          ack_timeout > clock_.ApproximateNow()) {
+        continue;
+      }
+      manager_->ResetAckStates(
+          QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)));
     }
   }
 
@@ -87,38 +135,39 @@
 };
 
 TEST_F(UberReceivedPacketManagerTest, DontWaitForPacketsBefore) {
-  QuicPacketHeader header;
-  header.packet_number = QuicPacketNumber(2u);
-  manager_->RecordPacketReceived(header, QuicTime::Zero());
-  header.packet_number = QuicPacketNumber(7u);
-  manager_->RecordPacketReceived(header, QuicTime::Zero());
-  EXPECT_TRUE(manager_->IsAwaitingPacket(QuicPacketNumber(3u)));
-  EXPECT_TRUE(manager_->IsAwaitingPacket(QuicPacketNumber(6u)));
-  manager_->DontWaitForPacketsBefore(QuicPacketNumber(4));
-  EXPECT_FALSE(manager_->IsAwaitingPacket(QuicPacketNumber(3u)));
-  EXPECT_TRUE(manager_->IsAwaitingPacket(QuicPacketNumber(6u)));
+  RecordPacketReceipt(2);
+  RecordPacketReceipt(7);
+  EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                         QuicPacketNumber(3u)));
+  EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                         QuicPacketNumber(6u)));
+  manager_->DontWaitForPacketsBefore(ENCRYPTION_FORWARD_SECURE,
+                                     QuicPacketNumber(4));
+  EXPECT_FALSE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                          QuicPacketNumber(3u)));
+  EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                         QuicPacketNumber(6u)));
 }
 
 TEST_F(UberReceivedPacketManagerTest, GetUpdatedAckFrame) {
-  QuicPacketHeader header;
-  header.packet_number = QuicPacketNumber(2u);
   QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2);
-  EXPECT_FALSE(manager_->AckFrameUpdated());
-  manager_->RecordPacketReceived(header, two_ms);
-  EXPECT_TRUE(manager_->AckFrameUpdated());
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
+  RecordPacketReceipt(2, two_ms);
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
 
-  QuicFrame ack = manager_->GetUpdatedAckFrame(QuicTime::Zero());
-  manager_->ResetAckStates();
-  EXPECT_FALSE(manager_->AckFrameUpdated());
+  QuicFrame ack =
+      manager_->GetUpdatedAckFrame(APPLICATION_DATA, QuicTime::Zero());
+  manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE);
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
   // When UpdateReceivedPacketInfo with a time earlier than the time of the
   // largest observed packet, make sure that the delta is 0, not negative.
   EXPECT_EQ(QuicTime::Delta::Zero(), ack.ack_frame->ack_delay_time);
   EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
 
   QuicTime four_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(4);
-  ack = manager_->GetUpdatedAckFrame(four_ms);
-  manager_->ResetAckStates();
-  EXPECT_FALSE(manager_->AckFrameUpdated());
+  ack = manager_->GetUpdatedAckFrame(APPLICATION_DATA, four_ms);
+  manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE);
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
   // When UpdateReceivedPacketInfo after not having received a new packet,
   // the delta should still be accurate.
   EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
@@ -126,25 +175,22 @@
   // And received packet times won't have change.
   EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
 
-  header.packet_number = QuicPacketNumber(999u);
-  manager_->RecordPacketReceived(header, two_ms);
-  header.packet_number = QuicPacketNumber(4u);
-  manager_->RecordPacketReceived(header, two_ms);
-  header.packet_number = QuicPacketNumber(1000u);
-  manager_->RecordPacketReceived(header, two_ms);
-  EXPECT_TRUE(manager_->AckFrameUpdated());
-  ack = manager_->GetUpdatedAckFrame(two_ms);
-  manager_->ResetAckStates();
-  EXPECT_FALSE(manager_->AckFrameUpdated());
+  RecordPacketReceipt(999, two_ms);
+  RecordPacketReceipt(4, two_ms);
+  RecordPacketReceipt(1000, two_ms);
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
+  ack = manager_->GetUpdatedAckFrame(APPLICATION_DATA, two_ms);
+  manager_->ResetAckStates(ENCRYPTION_FORWARD_SECURE);
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
   // UpdateReceivedPacketInfo should discard any times which can't be
   // expressed on the wire.
   EXPECT_EQ(2u, ack.ack_frame->received_packet_times.size());
 }
 
 TEST_F(UberReceivedPacketManagerTest, UpdateReceivedConnectionStats) {
-  EXPECT_FALSE(manager_->AckFrameUpdated());
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
   RecordPacketReceipt(1);
-  EXPECT_TRUE(manager_->AckFrameUpdated());
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
   RecordPacketReceipt(6);
   RecordPacketReceipt(2,
                       QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1));
@@ -156,11 +202,11 @@
 
 TEST_F(UberReceivedPacketManagerTest, LimitAckRanges) {
   manager_->set_max_ack_ranges(10);
-  EXPECT_FALSE(manager_->AckFrameUpdated());
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
   for (int i = 0; i < 100; ++i) {
     RecordPacketReceipt(1 + 2 * i);
-    EXPECT_TRUE(manager_->AckFrameUpdated());
-    manager_->GetUpdatedAckFrame(QuicTime::Zero());
+    EXPECT_TRUE(manager_->IsAckFrameUpdated());
+    manager_->GetUpdatedAckFrame(APPLICATION_DATA, QuicTime::Zero());
     EXPECT_GE(10u, manager_->ack_frame().packets.NumIntervals());
     EXPECT_EQ(QuicPacketNumber(1u + 2 * i),
               manager_->ack_frame().packets.Max());
@@ -177,9 +223,9 @@
 }
 
 TEST_F(UberReceivedPacketManagerTest, IgnoreOutOfOrderTimestamps) {
-  EXPECT_FALSE(manager_->AckFrameUpdated());
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
   RecordPacketReceipt(1, QuicTime::Zero());
-  EXPECT_TRUE(manager_->AckFrameUpdated());
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
   EXPECT_EQ(1u, manager_->ack_frame().received_packet_times.size());
   RecordPacketReceipt(2,
                       QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(1));
@@ -685,6 +731,69 @@
   CheckAckTimeout(clock_.ApproximateNow());
 }
 
+TEST_F(UberReceivedPacketManagerTest,
+       DontWaitForPacketsBeforeMultiplePacketNumberSpaces) {
+  manager_->EnableMultiplePacketNumberSpacesSupport();
+  EXPECT_FALSE(
+      manager_->GetLargestObserved(ENCRYPTION_HANDSHAKE).IsInitialized());
+  EXPECT_FALSE(
+      manager_->GetLargestObserved(ENCRYPTION_FORWARD_SECURE).IsInitialized());
+  RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 2);
+  RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 4);
+  RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 3);
+  RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 7);
+  EXPECT_EQ(QuicPacketNumber(4),
+            manager_->GetLargestObserved(ENCRYPTION_HANDSHAKE));
+  EXPECT_EQ(QuicPacketNumber(7),
+            manager_->GetLargestObserved(ENCRYPTION_FORWARD_SECURE));
+
+  EXPECT_TRUE(
+      manager_->IsAwaitingPacket(ENCRYPTION_HANDSHAKE, QuicPacketNumber(3)));
+  EXPECT_FALSE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                          QuicPacketNumber(3)));
+  EXPECT_TRUE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                         QuicPacketNumber(4)));
+
+  manager_->DontWaitForPacketsBefore(ENCRYPTION_FORWARD_SECURE,
+                                     QuicPacketNumber(5));
+  EXPECT_TRUE(
+      manager_->IsAwaitingPacket(ENCRYPTION_HANDSHAKE, QuicPacketNumber(3)));
+  EXPECT_FALSE(manager_->IsAwaitingPacket(ENCRYPTION_FORWARD_SECURE,
+                                          QuicPacketNumber(4)));
+}
+
+TEST_F(UberReceivedPacketManagerTest, AckSendingDifferentPacketNumberSpaces) {
+  manager_->EnableMultiplePacketNumberSpacesSupport();
+  SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
+  EXPECT_FALSE(HasPendingAck());
+  EXPECT_FALSE(manager_->IsAckFrameUpdated());
+
+  RecordPacketReceipt(ENCRYPTION_HANDSHAKE, 3);
+  EXPECT_TRUE(manager_->IsAckFrameUpdated());
+  MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_HANDSHAKE, 3);
+  EXPECT_TRUE(HasPendingAck());
+  // Delayed ack is scheduled.
+  CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+
+  RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 3);
+  MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_FORWARD_SECURE, 3);
+  EXPECT_TRUE(HasPendingAck());
+  // Delayed ack is scheduled.
+  CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+
+  RecordPacketReceipt(ENCRYPTION_FORWARD_SECURE, 2);
+  MaybeUpdateAckTimeout(kInstigateAck, ENCRYPTION_FORWARD_SECURE, 2);
+  // Application data ACK should be sent immediately.
+  CheckAckTimeout(clock_.ApproximateNow());
+  // Delayed ACK of handshake data is pending.
+  CheckAckTimeout(clock_.ApproximateNow() + kDelayedAckTime);
+
+  // Send delayed handshake data ACK.
+  clock_.AdvanceTime(kDelayedAckTime);
+  CheckAckTimeout(clock_.ApproximateNow());
+  EXPECT_FALSE(HasPendingAck());
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic