Internal QUICHE change

PiperOrigin-RevId: 301656000
Change-Id: Icf94da3805b379e988edd32dfcfddb8222318d78
diff --git a/quic/core/congestion_control/bandwidth_sampler.cc b/quic/core/congestion_control/bandwidth_sampler.cc
index df6eb24..37a49a1 100644
--- a/quic/core/congestion_control/bandwidth_sampler.cc
+++ b/quic/core/congestion_control/bandwidth_sampler.cc
@@ -78,7 +78,7 @@
       total_bytes_sent_at_last_acked_packet_(0),
       last_acked_packet_sent_time_(QuicTime::Zero()),
       last_acked_packet_ack_time_(QuicTime::Zero()),
-      is_app_limited_(false),
+      is_app_limited_(started_as_app_limited_),
       connection_state_map_(),
       max_tracked_packets_(GetQuicFlag(FLAGS_quic_max_tracked_packet_count)),
       unacked_packet_map_(unacked_packet_map),
@@ -289,11 +289,26 @@
     recent_ack_points_.Update(ack_time, total_bytes_acked_);
   }
 
-  // Exit app-limited phase once a packet that was sent while the connection is
-  // not app-limited is acknowledged.
-  if (is_app_limited_ && end_of_app_limited_phase_.IsInitialized() &&
-      packet_number > end_of_app_limited_phase_) {
-    is_app_limited_ = false;
+  if (started_as_app_limited_) {
+    if (is_app_limited_) {
+      // Exit app-limited phase in two cases:
+      // (1) end_of_app_limited_phase_ is not initialized, i.e., so far all
+      // packets are sent while there are buffered packets or pending data.
+      // (2) The current acked packet is after the sent packet marked as the end
+      // of the app limit phase.
+      if (!end_of_app_limited_phase_.IsInitialized() ||
+          packet_number > end_of_app_limited_phase_) {
+        QUIC_RELOADABLE_FLAG_COUNT(quic_bw_sampler_app_limited_starting_value);
+        is_app_limited_ = false;
+      }
+    }
+  } else {
+    // Exit app-limited phase once a packet that was sent while the connection
+    // is not app-limited is acknowledged.
+    if (is_app_limited_ && end_of_app_limited_phase_.IsInitialized() &&
+        packet_number > end_of_app_limited_phase_) {
+      is_app_limited_ = false;
+    }
   }
 
   // There might have been no packets acknowledged at the moment when the
diff --git a/quic/core/congestion_control/bandwidth_sampler.h b/quic/core/congestion_control/bandwidth_sampler.h
index b0ad576..0a69447 100644
--- a/quic/core/congestion_control/bandwidth_sampler.h
+++ b/quic/core/congestion_control/bandwidth_sampler.h
@@ -509,6 +509,10 @@
   // The most recently sent packet.
   QuicPacketNumber last_sent_packet_;
 
+  // Indicates whether the bandwidth sampler is started in app-limited phase.
+  const bool started_as_app_limited_ =
+      GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value);
+
   // Indicates whether the bandwidth sampler is currently in an app-limited
   // phase.
   bool is_app_limited_;
diff --git a/quic/core/congestion_control/bandwidth_sampler_test.cc b/quic/core/congestion_control/bandwidth_sampler_test.cc
index 73b812f..5dda998 100644
--- a/quic/core/congestion_control/bandwidth_sampler_test.cc
+++ b/quic/core/congestion_control/bandwidth_sampler_test.cc
@@ -39,6 +39,7 @@
  protected:
   BandwidthSamplerTest()
       : sampler_(nullptr, /*max_height_tracker_window_length=*/0),
+        sampler_app_limited_at_start_(sampler_.is_app_limited()),
         bytes_in_flight_(0),
         max_bandwidth_(QuicBandwidth::Zero()),
         est_bandwidth_upper_bound_(QuicBandwidth::Infinite()),
@@ -53,6 +54,7 @@
 
   MockClock clock_;
   BandwidthSampler sampler_;
+  bool sampler_app_limited_at_start_;
   QuicByteCount bytes_in_flight_;
   QuicBandwidth max_bandwidth_;  // Max observed bandwidth from acks.
   QuicBandwidth est_bandwidth_upper_bound_;
@@ -89,6 +91,7 @@
     bandwidth_sample.bandwidth = sample.sample_max_bandwidth;
     bandwidth_sample.rtt = sample.sample_rtt;
     bandwidth_sample.state_at_send = sample.last_packet_send_state;
+    EXPECT_TRUE(bandwidth_sample.state_at_send.is_valid);
     return bandwidth_sample;
   }
 
@@ -107,8 +110,6 @@
   // Acknowledge receipt of a packet and expect it to be not app-limited.
   QuicBandwidth AckPacket(uint64_t packet_number) {
     BandwidthSample sample = AckPacketInner(packet_number);
-    EXPECT_TRUE(sample.state_at_send.is_valid);
-    EXPECT_FALSE(sample.state_at_send.is_app_limited);
     return sample.bandwidth;
   }
 
@@ -446,14 +447,29 @@
   QuicBandwidth expected_bandwidth =
       QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize);
 
-  Send40PacketsAndAckFirst20(time_between_packets);
+  // Send 20 packets at a constant inter-packet time.
+  for (int i = 1; i <= 20; i++) {
+    SendPacket(i);
+    clock_.AdvanceTime(time_between_packets);
+  }
+
+  // Ack packets 1 to 20, while sending new packets at the same rate as
+  // before.
+  for (int i = 1; i <= 20; i++) {
+    BandwidthSample sample = AckPacketInner(i);
+    EXPECT_EQ(sample.state_at_send.is_app_limited,
+              sampler_app_limited_at_start_);
+    SendPacket(i + 20);
+    clock_.AdvanceTime(time_between_packets);
+  }
 
   // We are now app-limited. Ack 21 to 40 as usual, but do not send anything for
   // now.
   sampler_.OnAppLimited();
   for (int i = 21; i <= 40; i++) {
-    QuicBandwidth current_sample = AckPacket(i);
-    EXPECT_EQ(expected_bandwidth, current_sample);
+    BandwidthSample sample = AckPacketInner(i);
+    EXPECT_FALSE(sample.state_at_send.is_app_limited);
+    EXPECT_EQ(expected_bandwidth, sample.bandwidth);
     clock_.AdvanceTime(time_between_packets);
   }
 
@@ -480,8 +496,9 @@
   // Run out of packets, and then ack packet 61 to 80, all of which should have
   // correct non-app-limited samples.
   for (int i = 61; i <= 80; i++) {
-    QuicBandwidth last_bandwidth = AckPacket(i);
-    EXPECT_EQ(expected_bandwidth, last_bandwidth);
+    BandwidthSample sample = AckPacketInner(i);
+    EXPECT_FALSE(sample.state_at_send.is_app_limited);
+    EXPECT_EQ(sample.bandwidth, expected_bandwidth);
     clock_.AdvanceTime(time_between_packets);
   }
   sampler_.RemoveObsoletePackets(QuicPacketNumber(81));
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 2e12f5b..a10f415 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -1376,7 +1376,9 @@
         // to the client.
         control_frame_manager_.WriteOrBufferHandshakeDone();
       }
-      connection_->ResetHasNonAppLimitedSampleAfterHandshakeCompletion();
+      if (!GetQuicReloadableFlag(quic_bw_sampler_app_limited_starting_value)) {
+        connection_->ResetHasNonAppLimitedSampleAfterHandshakeCompletion();
+      }
       break;
     default:
       QUIC_BUG << "Unknown encryption level: "