gfe-relnote: In gQUIC, move dynamic stream accounting to LegacyStreamIdManager. Protected by gfe2_reloadable_flag_quic_stream_id_manager_handles_accounting.

Making it clear that QuicSession::GetNumOpenIncomingStreams and QuicSession::GetNumOpenOutgoingStreams are only used for gQUIC.

PiperOrigin-RevId: 308126943
Change-Id: Ib57ab52bf023ea83e1ada418ced8cb1dd08d186a
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc
index 606d3eb..51b981f 100644
--- a/quic/core/http/quic_server_session_base_test.cc
+++ b/quic/core/http/quic_server_session_base_test.cc
@@ -236,7 +236,7 @@
   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
                         quiche::QuicheStringPiece("HT"));
   session_->OnStreamFrame(data1);
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst1(kInvalidControlFrameId,
@@ -258,13 +258,12 @@
   InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0),
                          QUIC_ERROR_PROCESSING_STREAM);
 
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
-
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   // Send the same two bytes of payload in a new packet.
   session_->OnStreamFrame(data1);
 
   // The stream should not be re-opened.
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(connection_->connected());
 }
 
@@ -289,15 +288,14 @@
   InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0),
                          QUIC_ERROR_PROCESSING_STREAM);
 
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
-
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   // Send two bytes of payload.
   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
                         quiche::QuicheStringPiece("HT"));
   session_->OnStreamFrame(data1);
 
   // The stream should never be opened, now that the reset is received.
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(connection_->connected());
 }
 
@@ -309,7 +307,7 @@
                          quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT"));
   session_->OnStreamFrame(frame1);
   session_->OnStreamFrame(frame2);
-  EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst(kInvalidControlFrameId,
@@ -341,7 +339,7 @@
   session_->OnStreamFrame(frame3);
   session_->OnStreamFrame(frame4);
   // The stream should never be opened, now that the reset is received.
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(connection_->connected());
 }
 
@@ -361,7 +359,7 @@
     EXPECT_EQ(kMaxStreamsForTest + kMaxStreamsMinimumIncrement,
               session_->max_open_incoming_bidirectional_streams());
   }
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   QuicStreamId stream_id = GetNthClientInitiatedBidirectionalId(0);
   // Open the max configured number of streams, should be no problem.
   for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
@@ -407,7 +405,7 @@
   const size_t kAvailableStreamLimit =
       session_->MaxAvailableBidirectionalStreams();
 
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateStream(
       session_.get(), GetNthClientInitiatedBidirectionalId(0)));
 
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index e09c9bc..705d45c 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -221,9 +221,9 @@
 
   TestStream* CreateIncomingStream(QuicStreamId id) override {
     // Enforce the limit on the number of open streams.
-    if (GetNumOpenIncomingStreams() + 1 >
-            max_open_incoming_bidirectional_streams() &&
-        !VersionHasIetfQuicFrames(connection()->transport_version())) {
+    if (!VersionHasIetfQuicFrames(connection()->transport_version()) &&
+        GetNumOpenIncomingStreams() + 1 >
+            max_open_incoming_bidirectional_streams()) {
       connection()->CloseConnection(
           QUIC_TOO_MANY_OPEN_STREAMS, "Too many streams!",
           ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1124,7 +1124,7 @@
   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
                         quiche::QuicheStringPiece("HT"));
   session_.OnStreamFrame(data1);
-  EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   if (!VersionHasIetfQuicFrames(transport_version())) {
     // For version99, OnStreamReset gets called because of the STOP_SENDING,
@@ -1161,7 +1161,7 @@
     session_.OnStopSendingFrame(stop_sending);
   }
 
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   // Connection should remain alive.
   EXPECT_TRUE(connection_->connected());
 }
@@ -1773,9 +1773,9 @@
   for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += IdDelta()) {
     QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT"));
     session_.OnStreamFrame(data1);
-    EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+    EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
     session_.StreamDraining(i, /*unidirectional=*/false);
-    EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+    EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   }
 }
 
@@ -1852,7 +1852,7 @@
     return;
   }
 
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   QuicStreamId stream_id1 =
       GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
   // A bad stream frame with no data and no fin.
@@ -1999,7 +1999,7 @@
     return;
   }
 
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   // Push unidirectional stream is type 0x01.
   std::string frame_type1 = quiche::QuicheTextUtils::HexDecode("01");
@@ -2008,7 +2008,7 @@
   session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false,
                                          /* offset = */ 0, frame_type1));
 
-  EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   QuicStream* stream = session_.GetOrCreateStream(stream_id1);
   EXPECT_EQ(1u, stream->flow_controller()->bytes_consumed());
   EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed());
@@ -2020,7 +2020,7 @@
   session_.OnStreamFrame(QuicStreamFrame(stream_id2, /* fin = */ false,
                                          /* offset = */ 0, frame_type2));
 
-  EXPECT_EQ(2u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   stream = session_.GetOrCreateStream(stream_id2);
   EXPECT_EQ(4u, stream->flow_controller()->bytes_consumed());
   EXPECT_EQ(5u, session_.flow_controller()->bytes_consumed());
@@ -2031,7 +2031,7 @@
     return;
   }
 
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   // Push unidirectional stream is type 0x01.
   std::string frame_type = quiche::QuicheTextUtils::HexDecode("01");
@@ -2049,10 +2049,10 @@
 
   // Receiving some stream data without stream type does not open the stream.
   session_.OnStreamFrame(data2);
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   session_.OnStreamFrame(data1);
-  EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   QuicStream* stream = session_.GetOrCreateStream(stream_id);
   EXPECT_EQ(3u, stream->flow_controller()->highest_received_byte_offset());
 }
@@ -2598,7 +2598,7 @@
   session_.OnStreamFrame(frame);
 
   // There are no active streams.
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   // The pending stream is still around, because it did not receive a FIN.
   PendingStream* pending =
diff --git a/quic/core/legacy_quic_stream_id_manager.cc b/quic/core/legacy_quic_stream_id_manager.cc
index 6e8f13a..9598aff 100644
--- a/quic/core/legacy_quic_stream_id_manager.cc
+++ b/quic/core/legacy_quic_stream_id_manager.cc
@@ -29,12 +29,23 @@
               ? (QuicVersionUsesCryptoFrames(transport_version_)
                      ? QuicUtils::GetInvalidStreamId(transport_version_)
                      : QuicUtils::GetCryptoStreamId(transport_version_))
-              : QuicUtils::GetInvalidStreamId(transport_version_)) {}
+              : QuicUtils::GetInvalidStreamId(transport_version_)),
+      num_open_incoming_streams_(0),
+      num_open_outgoing_streams_(0),
+      handles_accounting_(
+          GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) {}
 
 LegacyQuicStreamIdManager::~LegacyQuicStreamIdManager() {}
 
 bool LegacyQuicStreamIdManager::CanOpenNextOutgoingStream(
     size_t current_num_open_outgoing_streams) const {
+  if (handles_accounting_) {
+    DCHECK_LE(num_open_outgoing_streams_, max_open_outgoing_streams_);
+    QUIC_DLOG_IF(INFO, num_open_outgoing_streams_ == max_open_outgoing_streams_)
+        << "Failed to create a new outgoing stream. "
+        << "Already " << num_open_outgoing_streams_ << " open.";
+    return num_open_outgoing_streams_ < max_open_outgoing_streams_;
+  }
   if (current_num_open_outgoing_streams >= max_open_outgoing_streams_) {
     QUIC_DLOG(INFO) << "Failed to create a new outgoing stream. "
                     << "Already " << current_num_open_outgoing_streams
@@ -46,6 +57,9 @@
 
 bool LegacyQuicStreamIdManager::CanOpenIncomingStream(
     size_t current_num_open_incoming_streams) const {
+  if (handles_accounting_) {
+    return num_open_incoming_streams_ < max_open_incoming_streams_;
+  }
   // Check if the new number of open streams would cause the number of
   // open streams to exceed the limit.
   return current_num_open_incoming_streams < max_open_incoming_streams_;
@@ -102,6 +116,26 @@
   return id;
 }
 
+void LegacyQuicStreamIdManager::ActivateStream(bool is_incoming) {
+  DCHECK(handles_accounting_);
+  if (is_incoming) {
+    ++num_open_incoming_streams_;
+    return;
+  }
+  ++num_open_outgoing_streams_;
+}
+
+void LegacyQuicStreamIdManager::OnStreamClosed(bool is_incoming) {
+  DCHECK(handles_accounting_);
+  if (is_incoming) {
+    QUIC_BUG_IF(num_open_incoming_streams_ == 0);
+    --num_open_incoming_streams_;
+    return;
+  }
+  QUIC_BUG_IF(num_open_outgoing_streams_ == 0);
+  --num_open_outgoing_streams_;
+}
+
 bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
   if (!IsIncomingStream(id)) {
     // Stream IDs under next_ougoing_stream_id_ are either open or previously
diff --git a/quic/core/legacy_quic_stream_id_manager.h b/quic/core/legacy_quic_stream_id_manager.h
index 16daa64..6c1309e 100644
--- a/quic/core/legacy_quic_stream_id_manager.h
+++ b/quic/core/legacy_quic_stream_id_manager.h
@@ -46,6 +46,12 @@
   // underlying counter.
   QuicStreamId GetNextOutgoingStreamId();
 
+  // Called when a new stream is open.
+  void ActivateStream(bool is_incoming);
+
+  // Called when a stream ID is closed.
+  void OnStreamClosed(bool is_incoming);
+
   // Return true if |id| is peer initiated.
   bool IsIncomingStream(QuicStreamId id) const;
 
@@ -82,6 +88,15 @@
 
   size_t GetNumAvailableStreams() const;
 
+  size_t num_open_incoming_streams() const {
+    return num_open_incoming_streams_;
+  }
+  size_t num_open_outgoing_streams() const {
+    return num_open_outgoing_streams_;
+  }
+
+  bool handles_accounting() const { return handles_accounting_; }
+
  private:
   friend class test::QuicSessionPeer;
 
@@ -102,6 +117,17 @@
   QuicHashSet<QuicStreamId> available_streams_;
 
   QuicStreamId largest_peer_created_stream_id_;
+
+  // A counter for peer initiated open streams. Used when handles_accounting_ is
+  // true.
+  size_t num_open_incoming_streams_;
+
+  // A counter for self initiated open streams. Used when handles_accounting_ is
+  // true.
+  size_t num_open_outgoing_streams_;
+
+  // Latched value of quic_stream_id_manager_handles_accounting.
+  const bool handles_accounting_;
 };
 
 }  // namespace quic
diff --git a/quic/core/legacy_quic_stream_id_manager_test.cc b/quic/core/legacy_quic_stream_id_manager_test.cc
index bd37ffe..00654b4 100644
--- a/quic/core/legacy_quic_stream_id_manager_test.cc
+++ b/quic/core/legacy_quic_stream_id_manager_test.cc
@@ -78,15 +78,31 @@
                          ::testing::PrintToStringParamName());
 
 TEST_P(LegacyQuicStreamIdManagerTest, CanOpenNextOutgoingStream) {
+  if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) {
+    for (size_t i = 0; i < manager_.max_open_outgoing_streams() - 1; ++i) {
+      manager_.ActivateStream(/*is_incoming=*/false);
+    }
+  }
   EXPECT_TRUE(manager_.CanOpenNextOutgoingStream(
       manager_.max_open_outgoing_streams() - 1));
+  if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) {
+    manager_.ActivateStream(/*is_incoming=*/false);
+  }
   EXPECT_FALSE(
       manager_.CanOpenNextOutgoingStream(manager_.max_open_outgoing_streams()));
 }
 
 TEST_P(LegacyQuicStreamIdManagerTest, CanOpenIncomingStream) {
+  if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) {
+    for (size_t i = 0; i < manager_.max_open_incoming_streams() - 1; ++i) {
+      manager_.ActivateStream(/*is_incoming=*/true);
+    }
+  }
   EXPECT_TRUE(
       manager_.CanOpenIncomingStream(manager_.max_open_incoming_streams() - 1));
+  if (GetQuicReloadableFlag(quic_stream_id_manager_handles_accounting)) {
+    manager_.ActivateStream(/*is_incoming=*/true);
+  }
   EXPECT_FALSE(
       manager_.CanOpenIncomingStream(manager_.max_open_incoming_streams()));
 }
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 9172ed7..e85644d 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -939,6 +939,10 @@
       // Do not bother informing stream ID manager if connection is closed.
       v99_streamid_manager_.OnStreamClosed(stream_id);
     }
+  } else if (stream_id_manager_.handles_accounting() && had_fin_or_rst &&
+             connection_->connected()) {
+    stream_id_manager_.OnStreamClosed(
+        /*is_incoming=*/IsIncomingStream(stream_id));
   }
 
   stream->OnClose();
@@ -1023,6 +1027,11 @@
     // disconnected.
     return;
   }
+  if (stream_id_manager_.handles_accounting() &&
+      !VersionHasIetfQuicFrames(transport_version())) {
+    stream_id_manager_.OnStreamClosed(
+        /*is_incoming=*/IsIncomingStream(stream_id));
+  }
   if (IsIncomingStream(stream_id)) {
     // Stream Id manager is only interested in peer initiated stream IDs.
     if (VersionHasIetfQuicFrames(transport_version())) {
@@ -1037,10 +1046,9 @@
 
 void QuicSession::ClosePendingStream(QuicStreamId stream_id) {
   QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
-
+  DCHECK(VersionHasIetfQuicFrames(transport_version()));
   pending_stream_map_.erase(stream_id);
-  if (VersionHasIetfQuicFrames(transport_version()) &&
-      connection_->connected()) {
+  if (connection_->connected()) {
     v99_streamid_manager_.OnStreamClosed(stream_id);
   }
 }
@@ -1070,6 +1078,11 @@
 
   flow_controller_.AddBytesConsumed(offset_diff);
   locally_closed_streams_highest_offset_.erase(it);
+  if (stream_id_manager_.handles_accounting() &&
+      !VersionHasIetfQuicFrames(transport_version())) {
+    stream_id_manager_.OnStreamClosed(
+        /*is_incoming=*/IsIncomingStream(stream_id));
+  }
   if (IsIncomingStream(stream_id)) {
     --num_locally_closed_incoming_streams_highest_offset_;
     if (VersionHasIetfQuicFrames(transport_version())) {
@@ -1586,6 +1599,12 @@
   } else if (is_static) {
     ++num_outgoing_static_streams_;
   }
+  if (stream_id_manager_.handles_accounting() && !is_static &&
+      !VersionHasIetfQuicFrames(transport_version())) {
+    // Do not inform stream ID manager of static streams.
+    stream_id_manager_.ActivateStream(
+        /*is_incoming=*/IsIncomingStream(stream_id));
+  }
 
   if (VersionHasIetfQuicFrames(transport_version()) &&
       !QuicUtils::IsBidirectionalStreamId(stream_id) && is_static) {
@@ -1704,6 +1723,9 @@
     QUIC_DVLOG(1) << ENDPOINT << "Stream " << stream_id << " is draining";
     if (VersionHasIetfQuicFrames(transport_version())) {
       v99_streamid_manager_.OnStreamClosed(stream_id);
+    } else if (stream_id_manager_.handles_accounting()) {
+      stream_id_manager_.OnStreamClosed(
+          /*is_incoming=*/IsIncomingStream(stream_id));
     }
     if (IsIncomingStream(stream_id)) {
       ++num_draining_incoming_streams_;
@@ -1720,6 +1742,9 @@
     }
     if (VersionHasIetfQuicFrames(transport_version())) {
       v99_streamid_manager_.OnStreamClosed(stream_id);
+    } else if (stream_id_manager_.handles_accounting()) {
+      stream_id_manager_.OnStreamClosed(
+          /*is_incoming=*/IsIncomingStream(stream_id));
     }
   }
   if (!IsIncomingStream(stream_id)) {
@@ -1853,11 +1878,19 @@
 }
 
 size_t QuicSession::GetNumOpenIncomingStreams() const {
+  DCHECK(!VersionHasIetfQuicFrames(transport_version()));
+  if (stream_id_manager_.handles_accounting()) {
+    return stream_id_manager_.num_open_incoming_streams();
+  }
   return num_dynamic_incoming_streams_ - num_draining_incoming_streams_ +
          num_locally_closed_incoming_streams_highest_offset_;
 }
 
 size_t QuicSession::GetNumOpenOutgoingStreams() const {
+  DCHECK(!VersionHasIetfQuicFrames(transport_version()));
+  if (stream_id_manager_.handles_accounting()) {
+    return stream_id_manager_.num_open_outgoing_streams();
+  }
   DCHECK_GE(GetNumDynamicOutgoingStreams() +
                 GetNumLocallyClosedOutgoingStreamsHighestOffset(),
             GetNumDrainingOutgoingStreams());
@@ -1867,6 +1900,14 @@
 }
 
 size_t QuicSession::GetNumActiveStreams() const {
+  if (!VersionHasIetfQuicFrames(transport_version()) &&
+      stream_id_manager_.handles_accounting()) {
+    // Exclude locally_closed_streams when determine whether to keep connection
+    // alive.
+    return stream_id_manager_.num_open_incoming_streams() +
+           stream_id_manager_.num_open_outgoing_streams() -
+           locally_closed_streams_highest_offset_.size();
+  }
   return stream_map_.size() - GetNumDrainingStreams() -
          num_incoming_static_streams_ - num_outgoing_static_streams_;
 }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index 75e524f..85c1a5f 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -326,10 +326,16 @@
 
   // Returns the number of currently open peer initiated streams, excluding
   // static streams.
+  // TODO(fayang): remove this and instead use
+  // LegacyStreamIdManager::num_open_incoming_streams() in tests when
+  // deprecating quic_stream_id_manager_handles_accounting.
   size_t GetNumOpenIncomingStreams() const;
 
   // Returns the number of currently open self initiated streams, excluding
   // static streams.
+  // TODO(fayang): remove this and instead use
+  // LegacyStreamIdManager::num_open_outgoing_streams() in tests when
+  // deprecating quic_stream_id_manager_handles_accounting.
   size_t GetNumOpenOutgoingStreams() const;
 
   // Returns the number of open peer initiated static streams.
@@ -764,15 +770,21 @@
   UberQuicStreamIdManager v99_streamid_manager_;
 
   // A counter for peer initiated dynamic streams which are in the stream_map_.
+  // TODO(fayang): Remove this when deprecating
+  // quic_stream_id_manager_handles_accounting.
   size_t num_dynamic_incoming_streams_;
 
   // A counter for peer initiated streams which have sent and received FIN but
   // waiting for application to consume data.
+  // TODO(fayang): Remove this when deprecating
+  // quic_stream_id_manager_handles_accounting.
   size_t num_draining_incoming_streams_;
 
   // A counter for self initiated streams which have sent and received FIN but
   // waiting for application to consume data. Only used when
   // deprecate_draining_streams_ is true.
+  // TODO(fayang): Remove this when deprecating
+  // quic_stream_id_manager_handles_accounting.
   size_t num_draining_outgoing_streams_;
 
   // A counter for self initiated static streams which are in
@@ -785,6 +797,8 @@
 
   // A counter for peer initiated streams which are in the
   // locally_closed_streams_highest_offset_.
+  // TODO(fayang): Remove this when deprecating
+  // quic_stream_id_manager_handles_accounting.
   size_t num_locally_closed_incoming_streams_highest_offset_;
 
   // Received information for a connection close.
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 80ef0d5..36b55a1 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -213,9 +213,9 @@
 
   TestStream* CreateIncomingStream(QuicStreamId id) override {
     // Enforce the limit on the number of open streams.
-    if (GetNumOpenIncomingStreams() + 1 >
-            max_open_incoming_bidirectional_streams() &&
-        !VersionHasIetfQuicFrames(connection()->transport_version())) {
+    if (!VersionHasIetfQuicFrames(connection()->transport_version()) &&
+        GetNumOpenIncomingStreams() + 1 >
+            max_open_incoming_bidirectional_streams()) {
       // No need to do this test for version 99; it's done by
       // QuicSession::GetOrCreateStream.
       connection()->CloseConnection(
@@ -1936,20 +1936,20 @@
   session_.OnStreamFrame(data1);
   EXPECT_TRUE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
   EXPECT_EQ(0, session_.num_incoming_streams_created());
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   QuicRstStreamFrame rst1(kInvalidControlFrameId, stream_id,
                           QUIC_ERROR_PROCESSING_STREAM, 12);
   session_.OnRstStream(rst1);
   EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
   EXPECT_EQ(0, session_.num_incoming_streams_created());
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 
   QuicStreamFrame data2(stream_id, false, 0, quiche::QuicheStringPiece("HT"));
   session_.OnStreamFrame(data2);
   EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
   EXPECT_EQ(0, session_.num_incoming_streams_created());
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 }
 
 TEST_P(QuicSessionTestServer, OnFinPendingStreams) {
@@ -1965,7 +1965,7 @@
 
   EXPECT_FALSE(QuicSessionPeer::GetPendingStream(&session_, stream_id));
   EXPECT_EQ(0, session_.num_incoming_streams_created());
-  EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
 }
 
 TEST_P(QuicSessionTestServer, PendingStreamOnWindowUpdate) {
@@ -2018,9 +2018,9 @@
        i += QuicUtils::StreamIdDelta(connection_->transport_version())) {
     QuicStreamFrame data1(i, true, 0, quiche::QuicheStringPiece("HT"));
     session_.OnStreamFrame(data1);
-    EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
+    EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
     session_.StreamDraining(i, /*unidirectional=*/false);
-    EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
+    EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
   }
 }
 
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc
index ed8e0e4..fdff93b 100644
--- a/quic/core/quic_stream_test.cc
+++ b/quic/core/quic_stream_test.cc
@@ -754,7 +754,7 @@
   EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
   EXPECT_FALSE(stream_->reading_stopped());
 
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Outgoing data with FIN.
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
@@ -767,7 +767,7 @@
   EXPECT_TRUE(stream_->write_side_closed());
 
   EXPECT_EQ(1u, session_->GetNumDrainingStreams());
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 TEST_P(QuicStreamTest, SetDrainingOutgoingIncoming) {
@@ -784,7 +784,7 @@
                              nullptr);
   EXPECT_TRUE(stream_->write_side_closed());
 
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Incoming data with FIN.
   QuicStreamFrame stream_frame_with_fin(stream_->id(), true, 1234, ".");
@@ -795,7 +795,7 @@
   EXPECT_FALSE(stream_->reading_stopped());
 
   EXPECT_EQ(1u, session_->GetNumDrainingStreams());
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 TEST_P(QuicStreamTest, EarlyResponseFinHandling) {
diff --git a/quic/quic_transport/quic_transport_integration_test.cc b/quic/quic_transport/quic_transport_integration_test.cc
index 355f6cc..f1912e2 100644
--- a/quic/quic_transport/quic_transport_integration_test.cc
+++ b/quic/quic_transport/quic_transport_integration_test.cc
@@ -23,6 +23,7 @@
 #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_server_session.h"
 #include "net/third_party/quiche/src/quic/quic_transport/quic_transport_stream.h"
 #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
 #include "net/third_party/quiche/src/quic/test_tools/quic_transport_test_tools.h"
 #include "net/third_party/quiche/src/quic/test_tools/simulator/link.h"
@@ -254,7 +255,8 @@
   }
   ASSERT_TRUE(simulator_.RunUntilOrTimeout(
       [this]() {
-        return server_->session()->GetNumOpenIncomingStreams() == 10;
+        return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) ==
+               10;
       },
       kDefaultTimeout));
 
@@ -262,7 +264,10 @@
     ASSERT_TRUE(stream->SendFin());
   }
   ASSERT_TRUE(simulator_.RunUntilOrTimeout(
-      [this]() { return server_->session()->GetNumOpenIncomingStreams() == 0; },
+      [this]() {
+        return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) ==
+               0;
+      },
       kDefaultTimeout));
 }
 
@@ -284,7 +289,10 @@
 
   EXPECT_TRUE(stream->SendFin());
   ASSERT_TRUE(simulator_.RunUntilOrTimeout(
-      [this]() { return server_->session()->GetNumOpenIncomingStreams() == 0; },
+      [this]() {
+        return QuicSessionPeer::GetNumOpenDynamicStreams(server_->session()) ==
+               0;
+      },
       kDefaultTimeout));
 }
 
diff --git a/quic/test_tools/quic_session_peer.cc b/quic/test_tools/quic_session_peer.cc
index c23bc88..ab28828 100644
--- a/quic/test_tools/quic_session_peer.cc
+++ b/quic/test_tools/quic_session_peer.cc
@@ -233,5 +233,21 @@
   session->perspective_ = perspective;
 }
 
+// static
+size_t QuicSessionPeer::GetNumOpenDynamicStreams(QuicSession* session) {
+  size_t result = 0;
+  for (const auto& it : session->stream_map_) {
+    if (!it.second->is_static()) {
+      ++result;
+    }
+  }
+  // Exclude draining streams.
+  result -= session->GetNumDrainingStreams();
+  // Add locally closed streams.
+  result += session->locally_closed_streams_highest_offset_.size();
+
+  return result;
+}
+
 }  // namespace test
 }  // namespace quic
diff --git a/quic/test_tools/quic_session_peer.h b/quic/test_tools/quic_session_peer.h
index 5a58360..ffb6a46 100644
--- a/quic/test_tools/quic_session_peer.h
+++ b/quic/test_tools/quic_session_peer.h
@@ -81,6 +81,7 @@
                                          QuicStreamId stream_id);
   static void set_is_configured(QuicSession* session, bool value);
   static void SetPerspective(QuicSession* session, Perspective perspective);
+  static size_t GetNumOpenDynamicStreams(QuicSession* session);
 };
 
 }  // namespace test
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc
index bdcedbc..966128b 100644
--- a/quic/tools/quic_simple_server_session_test.cc
+++ b/quic/tools/quic_simple_server_session_test.cc
@@ -321,7 +321,7 @@
   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
                         quiche::QuicheStringPiece("HT"));
   session_->OnStreamFrame(data1);
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Receive a reset (and send a RST in response).
   QuicRstStreamFrame rst1(kInvalidControlFrameId,
@@ -341,13 +341,13 @@
   // a one-way close.
   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
                     QUIC_ERROR_PROCESSING_STREAM);
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Send the same two bytes of payload in a new packet.
   session_->OnStreamFrame(data1);
 
   // The stream should not be re-opened.
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(connection_->connected());
 }
 
@@ -371,7 +371,7 @@
   InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
                     QUIC_ERROR_PROCESSING_STREAM);
 
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Send two bytes of payload.
   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -379,7 +379,7 @@
   session_->OnStreamFrame(data1);
 
   // The stream should never be opened, now that the reset is received.
-  EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(connection_->connected());
 }
 
@@ -391,7 +391,7 @@
                          quiche::QuicheStringPiece("\2\0\0\0\0\0\0\0HT"));
   session_->OnStreamFrame(frame1);
   session_->OnStreamFrame(frame2);
-  EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 
   // Send a reset (and expect the peer to send a RST in response).
   QuicRstStreamFrame rst(kInvalidControlFrameId,
@@ -422,7 +422,7 @@
   session_->OnStreamFrame(frame3);
   session_->OnStreamFrame(frame4);
   // The stream should never be opened, now that the reset is received.
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
   EXPECT_TRUE(connection_->connected());
 }
 
@@ -433,12 +433,14 @@
   }
 
   // Tests that incoming stream creation fails when connection is not connected.
-  size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
+  size_t initial_num_open_stream =
+      QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
   QuicConnectionPeer::TearDownLocalConnectionState(connection_);
   EXPECT_QUIC_BUG(QuicSimpleServerSessionPeer::CreateIncomingStream(
                       session_.get(), GetNthClientInitiatedBidirectionalId(0)),
                   "ShouldCreateIncomingStream called when disconnected");
-  EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(initial_num_open_stream,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 TEST_P(QuicSimpleServerSessionTest, CreateIncomingStream) {
@@ -455,14 +457,16 @@
   }
 
   // Tests that outgoing stream creation fails when connection is not connected.
-  size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
+  size_t initial_num_open_stream =
+      QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
   QuicConnectionPeer::TearDownLocalConnectionState(connection_);
   EXPECT_QUIC_BUG(
       QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
           session_.get()),
       "ShouldCreateOutgoingUnidirectionalStream called when disconnected");
 
-  EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams());
+  EXPECT_EQ(initial_num_open_stream,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUnencrypted) {
@@ -473,12 +477,14 @@
 
   // Tests that outgoing stream creation fails when encryption has not yet been
   // established.
-  size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
+  size_t initial_num_open_stream =
+      QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
   EXPECT_QUIC_BUG(
       QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
           session_.get()),
       "Encryption not established so no outgoing stream created.");
-  EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenOutgoingStreams());
+  EXPECT_EQ(initial_num_open_stream,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
@@ -491,8 +497,9 @@
   QuicStreamFrame data1(GetNthClientInitiatedBidirectionalId(0), false, 0,
                         quiche::QuicheStringPiece("HT"));
   session_->OnStreamFrame(data1);
-  EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
-  EXPECT_EQ(0u, session_->GetNumOpenOutgoingStreams());
+  EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
+  EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) -
+                    /*incoming=*/1);
 
   if (!VersionUsesHttp3(transport_version())) {
     session_->UnregisterStreamPriority(
@@ -523,20 +530,24 @@
     } else {
       EXPECT_EQ(GetNthServerInitiatedUnidirectionalId(i), created_stream->id());
     }
-    EXPECT_EQ(i + 1, session_->GetNumOpenOutgoingStreams());
+    EXPECT_EQ(i + 1, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) -
+                         /*incoming=*/1);
   }
 
   // Continuing creating push stream would fail.
   EXPECT_EQ(nullptr,
             QuicSimpleServerSessionPeer::CreateOutgoingUnidirectionalStream(
                 session_.get()));
-  EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
+  EXPECT_EQ(kMaxStreamsForTest,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) -
+                /*incoming=*/1);
 
   // Create peer initiated stream should have no problem.
   QuicStreamFrame data2(GetNthClientInitiatedBidirectionalId(1), false, 0,
                         quiche::QuicheStringPiece("HT"));
   session_->OnStreamFrame(data2);
-  EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()) -
+                    /*outcoming=*/kMaxStreamsForTest);
 }
 
 TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
@@ -551,7 +562,8 @@
 // Tests that calling GetOrCreateStream() on an outgoing stream not promised yet
 // should result close connection.
 TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
-  const size_t initial_num_open_stream = session_->GetNumOpenIncomingStreams();
+  const size_t initial_num_open_stream =
+      QuicSessionPeer::GetNumOpenDynamicStreams(session_.get());
   const QuicErrorCode expected_error = VersionUsesHttp3(transport_version())
                                            ? QUIC_HTTP_STREAM_WRONG_DIRECTION
                                            : QUIC_INVALID_STREAM_ID;
@@ -560,7 +572,8 @@
   EXPECT_EQ(nullptr,
             QuicSessionPeer::GetOrCreateStream(
                 session_.get(), GetNthServerInitiatedUnidirectionalId(3)));
-  EXPECT_EQ(initial_num_open_stream, session_->GetNumOpenIncomingStreams());
+  EXPECT_EQ(initial_num_open_stream,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 // In order to test the case where server push stream creation goes beyond
@@ -759,7 +772,8 @@
   }
   size_t num_resources = kMaxStreamsForTest + 5;
   PromisePushResources(num_resources);
-  EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
+  EXPECT_EQ(kMaxStreamsForTest,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 // Tests that after promised stream queued up, when an opened stream is marked
@@ -833,7 +847,8 @@
   }
   // Number of open outgoing streams should still be the same, because a new
   // stream is opened. And the queue should be empty.
-  EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
+  EXPECT_EQ(kMaxStreamsForTest,
+            QuicSessionPeer::GetNumOpenDynamicStreams(session_.get()));
 }
 
 // Tests that after all resources are promised, a RST frame from client can