Let session methods that write data take argument of TransmissionType so that it's clear at which transmission type the data is written.

gfe-relnote: no behavior change. not protected.
PiperOrigin-RevId: 298673372
Change-Id: Ibe1e680be7bce0e6310f8b6db50f7f86c4c8a206
diff --git a/quic/core/http/quic_send_control_stream_test.cc b/quic/core/http/quic_send_control_stream_test.cc
index 9e72f23..a5ff591 100644
--- a/quic/core/http/quic_send_control_stream_test.cc
+++ b/quic/core/http/quic_send_control_stream_test.cc
@@ -135,7 +135,7 @@
   auto save_write_data =
       [&writer, this](QuicStreamId /*id*/, size_t write_length,
                       QuicStreamOffset offset, StreamSendingState /*state*/,
-                      bool /*is_retransmission*/,
+                      TransmissionType /*type*/,
                       quiche::QuicheOptional<EncryptionLevel> /*level*/) {
         send_control_stream_->WriteStreamData(offset, write_length, &writer);
         return QuicConsumedData(/* bytes_consumed = */ write_length,
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc
index a8ddc09..dc33775 100644
--- a/quic/core/http/quic_spdy_client_session_test.cc
+++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -231,8 +231,9 @@
   EXPECT_TRUE(session_->CreateOutgoingBidirectionalStream() == nullptr);
   // Verify that no data may be send on existing streams.
   char data[] = "hello world";
-  QuicConsumedData consumed = session_->WritevData(
-      stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN, false, QuicheNullOpt);
+  QuicConsumedData consumed =
+      session_->WritevData(stream->id(), QUICHE_ARRAYSIZE(data), 0, NO_FIN,
+                           NOT_RETRANSMISSION, QuicheNullOpt);
   EXPECT_FALSE(consumed.fin_consumed);
   EXPECT_EQ(0u, consumed.bytes_consumed);
 }
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 37b559c..2e46a5c 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -178,8 +178,8 @@
   void OnBodyAvailable() override {}
 
   MOCK_METHOD0(OnCanWrite, void());
-  MOCK_METHOD3(RetransmitStreamData,
-               bool(QuicStreamOffset, QuicByteCount, bool));
+  MOCK_METHOD4(RetransmitStreamData,
+               bool(QuicStreamOffset, QuicByteCount, bool, TransmissionType));
 
   MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
 };
@@ -272,13 +272,13 @@
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool is_retransmission,
+      TransmissionType type,
       quiche::QuicheOptional<EncryptionLevel> level) override {
     bool fin = state != NO_FIN;
     QuicConsumedData consumed(write_length, fin);
     if (!writev_consumes_all_data_) {
-      consumed = QuicSession::WritevData(id, write_length, offset, state,
-                                         is_retransmission, level);
+      consumed =
+          QuicSession::WritevData(id, write_length, offset, state, type, level);
     }
     QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
         id, consumed.bytes_consumed);
@@ -299,7 +299,7 @@
     MakeIOVector("not empty", &iov);
     QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
     QuicConsumedData consumed =
-        WritevData(stream->id(), 9, 0, FIN, false, QuicheNullOpt);
+        WritevData(stream->id(), 9, 0, FIN, NOT_RETRANSMISSION, QuicheNullOpt);
     QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
         consumed.bytes_consumed);
     return consumed;
@@ -307,7 +307,8 @@
 
   QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
     DCHECK(writev_consumes_all_data_);
-    return WritevData(stream->id(), bytes, 0, FIN, false, QuicheNullOpt);
+    return WritevData(stream->id(), bytes, 0, FIN, NOT_RETRANSMISSION,
+                      QuicheNullOpt);
   }
 
   using QuicSession::closed_streams;
@@ -2121,11 +2122,14 @@
   frames.push_back(QuicFrame(frame3));
   EXPECT_FALSE(session_.WillingAndAbleToWrite());
 
-  EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+  EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _, _))
+      .WillOnce(Return(true));
   EXPECT_CALL(*connection_, SendControlFrame(_))
       .WillOnce(Invoke(&ClearControlFrame));
-  EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
-  EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+  EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _, _))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _))
+      .WillOnce(Return(true));
   EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
   session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
 }
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index e1053f1..d615582 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -8,6 +8,7 @@
 
 #include "net/third_party/quiche/src/quic/core/quic_constants.h"
 #include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
@@ -254,7 +255,10 @@
   WriteBufferedFrames();
 }
 
-bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame) {
+bool QuicControlFrameManager::RetransmitControlFrame(const QuicFrame& frame,
+                                                     TransmissionType type) {
+  DCHECK(type == PTO_RETRANSMISSION || type == RTO_RETRANSMISSION ||
+         type == TLP_RETRANSMISSION || type == PROBING_RETRANSMISSION);
   QuicControlFrameId id = GetControlFrameId(frame);
   if (id == kInvalidControlFrameId) {
     // Frame does not have a valid control frame ID, ignore it. Returns true
@@ -277,7 +281,7 @@
   QuicFrame copy = CopyRetransmittableControlFrame(frame);
   QUIC_DVLOG(1) << "control frame manager is forced to retransmit frame: "
                 << frame;
-  if (session_->WriteControlFrame(copy)) {
+  if (session_->WriteControlFrame(copy, type)) {
     return true;
   }
   DeleteFrame(&copy);
@@ -292,7 +296,7 @@
     QuicFrame frame_to_send =
         control_frames_.at(least_unsent_ - least_unacked_);
     QuicFrame copy = CopyRetransmittableControlFrame(frame_to_send);
-    if (!session_->WriteControlFrame(copy)) {
+    if (!session_->WriteControlFrame(copy, NOT_RETRANSMISSION)) {
       // Connection is write blocked.
       DeleteFrame(&copy);
       break;
@@ -305,7 +309,7 @@
   while (HasPendingRetransmission()) {
     QuicFrame pending = NextPendingRetransmission();
     QuicFrame copy = CopyRetransmittableControlFrame(pending);
-    if (!session_->WriteControlFrame(copy)) {
+    if (!session_->WriteControlFrame(copy, LOSS_RETRANSMISSION)) {
       // Connection is write blocked.
       DeleteFrame(&copy);
       break;
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h
index 6ca7ea0..ffd378c 100644
--- a/quic/core/quic_control_frame_manager.h
+++ b/quic/core/quic_control_frame_manager.h
@@ -87,7 +87,7 @@
   // Retransmit |frame| if it is still outstanding. Returns false if the frame
   // does not get retransmitted because the connection is blocked. Otherwise,
   // returns true.
-  bool RetransmitControlFrame(const QuicFrame& frame);
+  bool RetransmitControlFrame(const QuicFrame& frame, TransmissionType type);
 
   // Returns true if |frame| is outstanding and waiting to be acked. Returns
   // false otherwise.
diff --git a/quic/core/quic_control_frame_manager_test.cc b/quic/core/quic_control_frame_manager_test.cc
index e76e09f..f8e9932 100644
--- a/quic/core/quic_control_frame_manager_test.cc
+++ b/quic/core/quic_control_frame_manager_test.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -192,16 +193,19 @@
   manager_->OnControlFrameAcked(QuicFrame(&goaway_));
   // Do not retransmit an acked frame.
   EXPECT_CALL(*connection_, SendControlFrame(_)).Times(0);
-  EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&goaway_)));
+  EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&goaway_),
+                                               PTO_RETRANSMISSION));
 
   // Retransmit control frame 3.
   EXPECT_CALL(*connection_, SendControlFrame(_))
       .WillOnce(Invoke(&ClearControlFrame));
-  EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&window_update_)));
+  EXPECT_TRUE(manager_->RetransmitControlFrame(QuicFrame(&window_update_),
+                                               PTO_RETRANSMISSION));
 
   // Retransmit control frame 4, and connection is write blocked.
   EXPECT_CALL(*connection_, SendControlFrame(_)).WillOnce(Return(false));
-  EXPECT_FALSE(manager_->RetransmitControlFrame(QuicFrame(&window_update_)));
+  EXPECT_FALSE(manager_->RetransmitControlFrame(QuicFrame(&window_update_),
+                                                PTO_RETRANSMISSION));
 }
 
 TEST_F(QuicControlFrameManagerTest, DonotSendPingWithBufferedFrames) {
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index 81d8547..da5d15f 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -173,8 +173,8 @@
     return;
   }
 
-  size_t bytes_consumed =
-      stream_delegate()->WriteCryptoData(level, data.length(), offset);
+  size_t bytes_consumed = stream_delegate()->WriteCryptoData(
+      level, data.length(), offset, NOT_RETRANSMISSION);
   send_buffer->OnStreamDataConsumed(bytes_consumed);
 }
 
@@ -249,7 +249,7 @@
     while (send_buffer->HasPendingRetransmission()) {
       auto pending = send_buffer->NextPendingRetransmission();
       size_t bytes_consumed = stream_delegate()->WriteCryptoData(
-          level, pending.length, pending.offset);
+          level, pending.length, pending.offset, HANDSHAKE_RETRANSMISSION);
       send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
       if (bytes_consumed < pending.length) {
         break;
@@ -287,7 +287,7 @@
           retransmission_encryption_level);
       consumed = stream_delegate()->WritevData(
           id(), pending.length, pending.offset, NO_FIN,
-          /*is_retransmission*/ true, QuicheNullOpt);
+          HANDSHAKE_RETRANSMISSION, QuicheNullOpt);
       QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
                     << " tries to retransmit stream data [" << pending.offset
                     << ", " << pending.offset + pending.length
@@ -302,7 +302,8 @@
     } else {
       QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 1, 2);
       consumed = RetransmitStreamDataAtLevel(pending.offset, pending.length,
-                                             retransmission_encryption_level);
+                                             retransmission_encryption_level,
+                                             HANDSHAKE_RETRANSMISSION);
     }
     if (consumed.bytes_consumed < pending.length) {
       // The connection is write blocked.
@@ -313,7 +314,9 @@
 
 bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
                                             QuicByteCount data_length,
-                                            bool /*fin*/) {
+                                            bool /*fin*/,
+                                            TransmissionType type) {
+  DCHECK_EQ(HANDSHAKE_RETRANSMISSION, type);
   QuicIntervalSet<QuicStreamOffset> retransmission(offset,
                                                    offset + data_length);
   // Determine the encryption level to send data. This only needs to be once as
@@ -335,9 +338,9 @@
     if (!writevdata_at_level_) {
       // Set appropriate encryption level.
       session()->connection()->SetDefaultEncryptionLevel(send_encryption_level);
-      consumed = stream_delegate()->WritevData(
-          id(), retransmission_length, retransmission_offset, NO_FIN,
-          /*is_retransmission*/ true, QuicheNullOpt);
+      consumed = stream_delegate()->WritevData(id(), retransmission_length,
+                                               retransmission_offset, NO_FIN,
+                                               type, QuicheNullOpt);
       QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
                     << " is forced to retransmit stream data ["
                     << retransmission_offset << ", "
@@ -351,8 +354,9 @@
           current_encryption_level);
     } else {
       QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 2, 2);
-      consumed = RetransmitStreamDataAtLevel(
-          retransmission_offset, retransmission_length, send_encryption_level);
+      consumed = RetransmitStreamDataAtLevel(retransmission_offset,
+                                             retransmission_length,
+                                             send_encryption_level, type);
     }
     if (consumed.bytes_consumed < retransmission_length) {
       // The connection is write blocked.
@@ -366,11 +370,13 @@
 QuicConsumedData QuicCryptoStream::RetransmitStreamDataAtLevel(
     QuicStreamOffset retransmission_offset,
     QuicByteCount retransmission_length,
-    EncryptionLevel encryption_level) {
+    EncryptionLevel encryption_level,
+    TransmissionType type) {
+  DCHECK_EQ(HANDSHAKE_RETRANSMISSION, type);
   DCHECK(writevdata_at_level_);
   const auto consumed = stream_delegate()->WritevData(
-      id(), retransmission_length, retransmission_offset, NO_FIN,
-      /*is_retransmission*/ true, encryption_level);
+      id(), retransmission_length, retransmission_offset, NO_FIN, type,
+      encryption_level);
   QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
                 << " is forced to retransmit stream data ["
                 << retransmission_offset << ", "
@@ -413,7 +419,8 @@
       crypto_frame->offset, crypto_frame->data_length);
 }
 
-void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame) {
+void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame,
+                                      TransmissionType type) {
   QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
       << "Versions less than 47 don't retransmit CRYPTO frames";
   QuicIntervalSet<QuicStreamOffset> retransmission(
@@ -428,7 +435,8 @@
     size_t retransmission_offset = interval.min();
     size_t retransmission_length = interval.max() - interval.min();
     size_t bytes_consumed = stream_delegate()->WriteCryptoData(
-        crypto_frame->level, retransmission_length, retransmission_offset);
+        crypto_frame->level, retransmission_length, retransmission_offset,
+        type);
     send_buffer->OnStreamDataRetransmitted(retransmission_offset,
                                            bytes_consumed);
     if (bytes_consumed < retransmission_length) {
@@ -450,7 +458,8 @@
       continue;
     }
     size_t bytes_consumed = stream_delegate()->WriteCryptoData(
-        level, data_length, send_buffer->stream_bytes_written());
+        level, data_length, send_buffer->stream_bytes_written(),
+        NOT_RETRANSMISSION);
     send_buffer->OnStreamDataConsumed(bytes_consumed);
     if (bytes_consumed < data_length) {
       // Connection is write blocked.
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h
index d07a4e7..425d8c6 100644
--- a/quic/core/quic_crypto_stream.h
+++ b/quic/core/quic_crypto_stream.h
@@ -119,13 +119,15 @@
   // Override to send unacked crypto data with the appropriate encryption level.
   bool RetransmitStreamData(QuicStreamOffset offset,
                             QuicByteCount data_length,
-                            bool fin) override;
+                            bool fin,
+                            TransmissionType type) override;
 
   // Sends stream retransmission data at |encryption_level|.
   QuicConsumedData RetransmitStreamDataAtLevel(
       QuicStreamOffset retransmission_offset,
       QuicByteCount retransmission_length,
-      EncryptionLevel encryption_level);
+      EncryptionLevel encryption_level,
+      TransmissionType type);
 
   // Returns the number of bytes of handshake data that have been received from
   // the peer in either CRYPTO or STREAM frames.
@@ -149,7 +151,7 @@
 
   // Called to retransmit any outstanding data in the range indicated by the
   // encryption level, offset, and length in |crypto_frame|.
-  void RetransmitData(QuicCryptoFrame* crypto_frame);
+  void RetransmitData(QuicCryptoFrame* crypto_frame, TransmissionType type);
 
   // Called to write buffered crypto frames.
   void WriteBufferedCryptoFrames();
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc
index e3ba21c..436e572 100644
--- a/quic/core/quic_crypto_stream_test.cc
+++ b/quic/core/quic_crypto_stream_test.cc
@@ -376,10 +376,11 @@
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_.ConsumeData(
             QuicUtils::GetCryptoStreamId(connection_->transport_version()), 150,
-            1350, NO_FIN, 1350, QuicheNullOpt);
+            1350, NO_FIN, HANDSHAKE_RETRANSMISSION, QuicheNullOpt);
       }));
 
-  EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false));
+  EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false,
+                                             HANDSHAKE_RETRANSMISSION));
   // Verify connection's encryption level has restored.
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
 
@@ -394,13 +395,15 @@
       WritevData(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
                  200, 2500, _, _, _))
       .WillOnce(Invoke(&session_, &MockQuicSpdySession::ConsumeData));
-  EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false));
+  EXPECT_TRUE(stream_->RetransmitStreamData(1350, 1350, false,
+                                            HANDSHAKE_RETRANSMISSION));
   // Verify connection's encryption level has restored.
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
 
   EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(0);
   // Force to send an empty frame.
-  EXPECT_TRUE(stream_->RetransmitStreamData(0, 0, false));
+  EXPECT_TRUE(
+      stream_->RetransmitStreamData(0, 0, false, HANDSHAKE_RETRANSMISSION));
 }
 
 TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) {
@@ -438,7 +441,7 @@
       .WillOnce(Invoke(connection_,
                        &MockQuicConnection::QuicConnection_SendCryptoData));
   QuicCryptoFrame frame_to_retransmit(ENCRYPTION_ZERO_RTT, 0, 150);
-  stream_->RetransmitData(&frame_to_retransmit);
+  stream_->RetransmitData(&frame_to_retransmit, HANDSHAKE_RETRANSMISSION);
 
   // Verify connection's encryption level has restored.
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
@@ -451,14 +454,14 @@
       .WillOnce(Invoke(connection_,
                        &MockQuicConnection::QuicConnection_SendCryptoData));
   frame_to_retransmit = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 1350);
-  stream_->RetransmitData(&frame_to_retransmit);
+  stream_->RetransmitData(&frame_to_retransmit, HANDSHAKE_RETRANSMISSION);
   // Verify connection's encryption level has restored.
   EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
 
   EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
   // Force to send an empty frame.
   QuicCryptoFrame empty_frame(ENCRYPTION_FORWARD_SECURE, 0, 0);
-  stream_->RetransmitData(&empty_frame);
+  stream_->RetransmitData(&empty_frame, HANDSHAKE_RETRANSMISSION);
 }
 
 // Regression test for b/115926584.
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 891e6cc..26a4356 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -737,7 +737,7 @@
     size_t write_length,
     QuicStreamOffset offset,
     StreamSendingState state,
-    bool is_retransmission,
+    TransmissionType type,
     quiche::QuicheOptional<EncryptionLevel> level) {
   DCHECK(connection_->connected())
       << ENDPOINT << "Try to write stream data when connection is closed.";
@@ -755,7 +755,7 @@
 
   QuicConsumedData data =
       connection_->SendStreamData(id, write_length, offset, state);
-  if (!is_retransmission) {
+  if (type == NOT_RETRANSMISSION) {
     // This is new stream data.
     write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
   }
@@ -770,8 +770,10 @@
 
 size_t QuicSession::WriteCryptoData(EncryptionLevel level,
                                     size_t write_length,
-                                    QuicStreamOffset offset) {
+                                    QuicStreamOffset offset,
+                                    TransmissionType /*type*/) {
   DCHECK(QuicVersionUsesCryptoFrames(transport_version()));
+  // TODO(b/136274541): Set the transmission type here.
   const auto current_level = connection()->encryption_level();
   connection_->SetDefaultEncryptionLevel(level);
   const auto bytes_consumed =
@@ -781,7 +783,9 @@
   return bytes_consumed;
 }
 
-bool QuicSession::WriteControlFrame(const QuicFrame& frame) {
+bool QuicSession::WriteControlFrame(const QuicFrame& frame,
+                                    TransmissionType /*type*/) {
+  // TODO(b/136274541): Set the transmission type here.
   return connection_->SendControlFrame(frame);
 }
 
@@ -1956,11 +1960,11 @@
       continue;
     }
     if (frame.type == CRYPTO_FRAME) {
-      GetMutableCryptoStream()->RetransmitData(frame.crypto_frame);
+      GetMutableCryptoStream()->RetransmitData(frame.crypto_frame, type);
       continue;
     }
     if (frame.type != STREAM_FRAME) {
-      if (!control_frame_manager_.RetransmitControlFrame(frame)) {
+      if (!control_frame_manager_.RetransmitControlFrame(frame, type)) {
         break;
       }
       continue;
@@ -1969,7 +1973,7 @@
     if (stream != nullptr &&
         !stream->RetransmitStreamData(frame.stream_frame.offset,
                                       frame.stream_frame.data_length,
-                                      frame.stream_frame.fin)) {
+                                      frame.stream_frame.fin, type)) {
       break;
     }
   }
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index 84b1500..7f8e251 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -199,8 +199,9 @@
   virtual void OnMessageLost(QuicMessageId message_id);
 
   // Called by control frame manager when it wants to write control frames to
-  // the peer. Returns true if |frame| is consumed, false otherwise.
-  virtual bool WriteControlFrame(const QuicFrame& frame);
+  // the peer. Returns true if |frame| is consumed, false otherwise. The frame
+  // will be sent in specified transmission |type|.
+  bool WriteControlFrame(const QuicFrame& frame, TransmissionType type);
 
   // Close the stream in both directions.
   // TODO(renjietang): rename this method as it sends both RST_STREAM and
@@ -273,12 +274,13 @@
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool is_retransmission,
+      TransmissionType type,
       quiche::QuicheOptional<EncryptionLevel> level) override;
 
   size_t WriteCryptoData(EncryptionLevel level,
                          size_t write_length,
-                         QuicStreamOffset offset) override;
+                         QuicStreamOffset offset,
+                         TransmissionType type) override;
 
   // Called by the QuicCryptoStream when a handshake message is sent.
   virtual void OnCryptoHandshakeMessageSent(
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 93c3a9b..152e159 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -150,8 +150,8 @@
   void OnDataAvailable() override {}
 
   MOCK_METHOD0(OnCanWrite, void());
-  MOCK_METHOD3(RetransmitStreamData,
-               bool(QuicStreamOffset, QuicByteCount, bool));
+  MOCK_METHOD4(RetransmitStreamData,
+               bool(QuicStreamOffset, QuicByteCount, bool, TransmissionType));
 
   MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
 };
@@ -267,13 +267,13 @@
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool is_retransmission,
+      TransmissionType type,
       quiche::QuicheOptional<EncryptionLevel> level) override {
     bool fin = state != NO_FIN;
     QuicConsumedData consumed(write_length, fin);
     if (!writev_consumes_all_data_) {
-      consumed = QuicSession::WritevData(id, write_length, offset, state,
-                                         is_retransmission, level);
+      consumed =
+          QuicSession::WritevData(id, write_length, offset, state, type, level);
     }
     QuicSessionPeer::GetWriteBlockedStreams(this)->UpdateBytesForStream(
         id, consumed.bytes_consumed);
@@ -295,8 +295,8 @@
     }
     MakeIOVector("not empty", &iov);
     QuicStreamPeer::SendBuffer(stream).SaveStreamData(&iov, 1, 0, 9);
-    QuicConsumedData consumed = WritevData(
-        stream->id(), 9, 0, FIN, /*is_retransmission*/ false, QuicheNullOpt);
+    QuicConsumedData consumed =
+        WritevData(stream->id(), 9, 0, FIN, NOT_RETRANSMISSION, QuicheNullOpt);
     QuicStreamPeer::SendBuffer(stream).OnStreamDataConsumed(
         consumed.bytes_consumed);
     return consumed;
@@ -312,8 +312,8 @@
 
   QuicConsumedData SendLargeFakeData(QuicStream* stream, int bytes) {
     DCHECK(writev_consumes_all_data_);
-    return WritevData(stream->id(), bytes, 0, FIN,
-                      /*is_retransmission*/ false, QuicheNullOpt);
+    return WritevData(stream->id(), bytes, 0, FIN, NOT_RETRANSMISSION,
+                      QuicheNullOpt);
   }
 
   bool UsesPendingStreams() const override { return uses_pending_streams_; }
@@ -2307,11 +2307,14 @@
   frames.push_back(QuicFrame(frame3));
   EXPECT_FALSE(session_.WillingAndAbleToWrite());
 
-  EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+  EXPECT_CALL(*stream2, RetransmitStreamData(_, _, _, _))
+      .WillOnce(Return(true));
   EXPECT_CALL(*connection_, SendControlFrame(_))
       .WillOnce(Invoke(&ClearControlFrame));
-  EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
-  EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _)).WillOnce(Return(true));
+  EXPECT_CALL(*stream4, RetransmitStreamData(_, _, _, _))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*stream6, RetransmitStreamData(_, _, _, _))
+      .WillOnce(Return(true));
   EXPECT_CALL(*send_algorithm, OnApplicationLimited(_));
   session_.RetransmitFrames(frames, TLP_RETRANSMISSION);
 }
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc
index d952cc0..dbf9e66 100644
--- a/quic/core/quic_stream.cc
+++ b/quic/core/quic_stream.cc
@@ -912,7 +912,10 @@
 
 bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
                                       QuicByteCount data_length,
-                                      bool fin) {
+                                      bool fin,
+                                      TransmissionType type) {
+  DCHECK(type == PTO_RETRANSMISSION || type == RTO_RETRANSMISSION ||
+         type == TLP_RETRANSMISSION || type == PROBING_RETRANSMISSION);
   if (HasDeadlinePassed()) {
     OnDeadlinePassed();
     return true;
@@ -933,8 +936,7 @@
                            stream_bytes_written());
     consumed = stream_delegate_->WritevData(
         id_, retransmission_length, retransmission_offset,
-        can_bundle_fin ? FIN : NO_FIN, /*is_retransmission*/ true,
-        QuicheNullOpt);
+        can_bundle_fin ? FIN : NO_FIN, type, QuicheNullOpt);
     QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                   << " is forced to retransmit stream data ["
                   << retransmission_offset << ", "
@@ -955,9 +957,8 @@
   if (retransmit_fin) {
     QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                   << " retransmits fin only frame.";
-    consumed =
-        stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
-                                     /*is_retransmission*/ true, QuicheNullOpt);
+    consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
+                                            type, QuicheNullOpt);
     if (!consumed.fin_consumed) {
       return false;
     }
@@ -1027,9 +1028,9 @@
   if (fin && add_random_padding_after_fin_) {
     state = FIN_AND_PADDING;
   }
-  QuicConsumedData consumed_data = stream_delegate_->WritevData(
-      id(), write_length, stream_bytes_written(), state,
-      /*is_retransmission*/ false, QuicheNullOpt);
+  QuicConsumedData consumed_data =
+      stream_delegate_->WritevData(id(), write_length, stream_bytes_written(),
+                                   state, NOT_RETRANSMISSION, QuicheNullOpt);
 
   OnStreamDataConsumed(consumed_data.bytes_consumed);
 
@@ -1103,9 +1104,9 @@
     if (!send_buffer_.HasPendingRetransmission()) {
       QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                     << " retransmits fin only frame.";
-      consumed = stream_delegate_->WritevData(
-          id_, 0, stream_bytes_written(), FIN,
-          /*is_retransmission*/ true, QuicheNullOpt);
+      consumed =
+          stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
+                                       LOSS_RETRANSMISSION, QuicheNullOpt);
       fin_lost_ = !consumed.fin_consumed;
       if (fin_lost_) {
         // Connection is write blocked.
@@ -1120,7 +1121,7 @@
           (pending.offset + pending.length == stream_bytes_written());
       consumed = stream_delegate_->WritevData(
           id_, pending.length, pending.offset, can_bundle_fin ? FIN : NO_FIN,
-          /*is_retransmission*/ true, QuicheNullOpt);
+          LOSS_RETRANSMISSION, QuicheNullOpt);
       QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
                     << " tries to retransmit stream data [" << pending.offset
                     << ", " << pending.offset + pending.length
diff --git a/quic/core/quic_stream.h b/quic/core/quic_stream.h
index 9efbe50..36aec05 100644
--- a/quic/core/quic_stream.h
+++ b/quic/core/quic_stream.h
@@ -313,10 +313,12 @@
                                  bool fin_lost);
 
   // Called to retransmit outstanding portion in data [offset, offset +
-  // data_length) and |fin|. Returns true if all data gets retransmitted.
+  // data_length) and |fin| with Transmission |type|.
+  // Returns true if all data gets retransmitted.
   virtual bool RetransmitStreamData(QuicStreamOffset offset,
                                     QuicByteCount data_length,
-                                    bool fin);
+                                    bool fin,
+                                    TransmissionType type);
 
   // Sets deadline of this stream to be now + |ttl|, returns true if the setting
   // succeeds.
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc
index 4055b4c..eea7b15 100644
--- a/quic/core/quic_stream_test.cc
+++ b/quic/core/quic_stream_test.cc
@@ -128,7 +128,7 @@
       size_t /*write_length*/,
       QuicStreamOffset /*offset*/,
       StreamSendingState /*state*/,
-      QuicByteCount /*bytes_written*/,
+      TransmissionType /*type*/,
       quiche::QuicheOptional<EncryptionLevel> /*level*/) {
     session_->CloseStream(id);
     return QuicConsumedData(1, false);
@@ -304,8 +304,8 @@
   // we should be write blocked a not all the data was consumed.
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), false,
                              nullptr);
@@ -323,8 +323,8 @@
   // last data)
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
                              nullptr);
@@ -372,7 +372,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), kDataLen - 1, 0u, NO_FIN,
-                                     false, QuicheNullOpt);
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(kData1, false, nullptr);
 
@@ -388,7 +388,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), kDataLen - 1, kDataLen - 1,
-                                     NO_FIN, false, QuicheNullOpt);
+                                     NO_FIN, NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData());
   stream_->OnCanWrite();
@@ -398,7 +398,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 2u, 2 * kDataLen - 2,
-                                     NO_FIN, false, QuicheNullOpt);
+                                     NO_FIN, NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData());
   stream_->OnCanWrite();
@@ -444,8 +444,8 @@
   // Write some data, with no FIN.
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), false,
                              nullptr);
@@ -473,8 +473,8 @@
   // Write some data, with FIN.
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 1u, 0u, FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 1u, 0u, FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 1), true,
                              nullptr);
@@ -739,8 +739,8 @@
   // Outgoing data with FIN.
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 2u, 0u, FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
                              nullptr);
@@ -758,8 +758,8 @@
   // Outgoing data with FIN.
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 2u, 0u, FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 2u, 0u, FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(quiche::QuicheStringPiece(kData1, 2), true,
                              nullptr);
@@ -1035,8 +1035,8 @@
   // Testing WriteOrBufferData.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->WriteOrBufferData(data, false, nullptr);
   stream_->WriteOrBufferData(data, false, nullptr);
@@ -1048,8 +1048,8 @@
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   // Buffered data size > threshold, do not ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
@@ -1063,7 +1063,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
         return session_->ConsumeData(stream_->id(), data_to_write, 200u, NO_FIN,
-                                     false, QuicheNullOpt);
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   // Buffered data size < threshold, ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1113,7 +1113,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
         return session_->ConsumeData(stream_->id(), data_to_write, 0u, NO_FIN,
-                                     false, QuicheNullOpt);
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
 
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1174,8 +1174,8 @@
 
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   // There is no buffered data before, all data should be consumed.
   QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
@@ -1197,7 +1197,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
         return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN,
-                                     false, QuicheNullOpt);
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
@@ -1233,8 +1233,8 @@
   QuicMemSliceSpan span1 = vector1.span();
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   // There is no buffered data before, all data should be consumed.
   QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
@@ -1371,8 +1371,8 @@
   // be bundled with data.
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 9u, 18u, FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 9u, 18u, FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   stream_->OnCanWrite();
   EXPECT_FALSE(stream_->HasPendingRetransmission());
@@ -1401,8 +1401,8 @@
   InSequence s;
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(0, true)));
@@ -1490,24 +1490,24 @@
   // Retransmit [0, 18) with fin, and only [0, 8) is consumed.
   EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
-        return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN, false,
-                                     QuicheNullOpt);
+        return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN,
+                                     NOT_RETRANSMISSION, QuicheNullOpt);
       }));
-  EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true));
+  EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true, PTO_RETRANSMISSION));
 
   // Retransmit [0, 18) with fin, and all is consumed.
   EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _))
       .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_CALL(*session_, WritevData(stream_->id(), 5, 13, FIN, _, _))
       .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
-  EXPECT_TRUE(stream_->RetransmitStreamData(0, 18, true));
+  EXPECT_TRUE(stream_->RetransmitStreamData(0, 18, true, PTO_RETRANSMISSION));
 
   // Retransmit [0, 8) with fin, and all is consumed.
   EXPECT_CALL(*session_, WritevData(stream_->id(), 8, 0, NO_FIN, _, _))
       .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
   EXPECT_CALL(*session_, WritevData(stream_->id(), 0, 18, FIN, _, _))
       .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
-  EXPECT_TRUE(stream_->RetransmitStreamData(0, 8, true));
+  EXPECT_TRUE(stream_->RetransmitStreamData(0, 8, true, PTO_RETRANSMISSION));
 }
 
 TEST_P(QuicStreamTest, ResetStreamOnTtlExpiresRetransmitLostData) {
@@ -1524,7 +1524,7 @@
   // Verify data gets retransmitted because TTL does not expire.
   EXPECT_CALL(*session_, WritevData(stream_->id(), 100, 0, NO_FIN, _, _))
       .WillOnce(Invoke(session_.get(), &MockQuicSession::ConsumeData));
-  EXPECT_TRUE(stream_->RetransmitStreamData(0, 100, false));
+  EXPECT_TRUE(stream_->RetransmitStreamData(0, 100, false, PTO_RETRANSMISSION));
   stream_->OnStreamFrameLost(100, 100, true);
   EXPECT_TRUE(stream_->HasPendingRetransmission());
 
@@ -1549,7 +1549,7 @@
   connection_->AdvanceTime(QuicTime::Delta::FromSeconds(1));
   // Verify stream gets reset because TTL expires.
   EXPECT_CALL(*session_, SendRstStream(_, QUIC_STREAM_TTL_EXPIRED, _)).Times(1);
-  stream_->RetransmitStreamData(0, 100, false);
+  stream_->RetransmitStreamData(0, 100, false, PTO_RETRANSMISSION);
 }
 
 // Test that QuicStream::StopSending A) is a no-op if the connection is not in
diff --git a/quic/core/stream_delegate_interface.h b/quic/core/stream_delegate_interface.h
index 440b01a..3fc584d 100644
--- a/quic/core/stream_delegate_interface.h
+++ b/quic/core/stream_delegate_interface.h
@@ -22,18 +22,20 @@
   virtual void OnStreamError(QuicErrorCode error_code,
                              std::string error_details) = 0;
   // Called when the stream needs to write data. If |level| is present, the data
-  // will be written at the specified |level|.
+  // will be written at the specified |level|. The data will be written
+  // at specified transmission |type|.
   virtual QuicConsumedData WritevData(
       QuicStreamId id,
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool is_retransmission,
+      TransmissionType type,
       quiche::QuicheOptional<EncryptionLevel> level) = 0;
   // Called to write crypto data.
   virtual size_t WriteCryptoData(EncryptionLevel level,
                                  size_t write_length,
-                                 QuicStreamOffset offset) = 0;
+                                 QuicStreamOffset offset,
+                                 TransmissionType type) = 0;
   // Called on stream creation.
   virtual void RegisterStreamPriority(
       QuicStreamId id,
diff --git a/quic/qbone/qbone_stream_test.cc b/quic/qbone/qbone_stream_test.cc
index df25f6b..42840be 100644
--- a/quic/qbone/qbone_stream_test.cc
+++ b/quic/qbone/qbone_stream_test.cc
@@ -45,7 +45,7 @@
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool is_retransmission,
+      TransmissionType type,
       quiche::QuicheOptional<EncryptionLevel> level) override {
     if (!writable_) {
       return QuicConsumedData(0, false);
diff --git a/quic/quartc/quartc_stream_test.cc b/quic/quartc/quartc_stream_test.cc
index d0a527c..f1de032 100644
--- a/quic/quartc/quartc_stream_test.cc
+++ b/quic/quartc/quartc_stream_test.cc
@@ -82,7 +82,7 @@
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool /*is_retransmission*/,
+      TransmissionType /*type*/,
       quiche::QuicheOptional<EncryptionLevel> /*level*/) override {
     if (!writable_) {
       return QuicConsumedData(0, false);
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index 680b16c..bfbf512 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -582,7 +582,7 @@
     size_t write_length,
     QuicStreamOffset offset,
     StreamSendingState state,
-    bool /*is_retransmission*/,
+    TransmissionType /*type*/,
     quiche::QuicheOptional<EncryptionLevel> /*level*/) {
   if (write_length > 0) {
     auto buf = std::make_unique<char[]>(write_length);
@@ -656,7 +656,7 @@
     size_t write_length,
     QuicStreamOffset offset,
     StreamSendingState state,
-    bool /*is_retransmission*/,
+    TransmissionType /*type*/,
     quiche::QuicheOptional<EncryptionLevel> /*level*/) {
   if (write_length > 0) {
     auto buf = std::make_unique<char[]>(write_length);
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index 7440c4d..b20f90e 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -638,7 +638,7 @@
                                 size_t write_length,
                                 QuicStreamOffset offset,
                                 StreamSendingState state,
-                                bool is_retransmission,
+                                TransmissionType type,
                                 quiche::QuicheOptional<EncryptionLevel> level));
 
   MOCK_METHOD3(SendRstStream,
@@ -669,7 +669,7 @@
                                size_t write_length,
                                QuicStreamOffset offset,
                                StreamSendingState state,
-                               bool is_retransmission,
+                               TransmissionType type,
                                quiche::QuicheOptional<EncryptionLevel> level);
 
   void ReallySendRstStream(QuicStreamId id,
@@ -739,7 +739,7 @@
                                 size_t write_length,
                                 QuicStreamOffset offset,
                                 StreamSendingState state,
-                                bool is_retransmission,
+                                TransmissionType type,
                                 quiche::QuicheOptional<EncryptionLevel> level));
 
   MOCK_METHOD3(SendRstStream,
@@ -787,7 +787,7 @@
                                size_t write_length,
                                QuicStreamOffset offset,
                                StreamSendingState state,
-                               bool is_retransmission,
+                               TransmissionType type,
                                quiche::QuicheOptional<EncryptionLevel> level);
 
   using QuicSession::ActivateStream;
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc
index 1c71af1..06e8866 100644
--- a/quic/tools/quic_simple_server_stream_test.cc
+++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -129,7 +129,7 @@
                                 size_t write_length,
                                 QuicStreamOffset offset,
                                 StreamSendingState state,
-                                bool is_retransmission,
+                                TransmissionType type,
                                 quiche::QuicheOptional<EncryptionLevel> level));
   MOCK_METHOD4(OnStreamHeaderList,
                void(QuicStreamId stream_id,
@@ -171,7 +171,7 @@
       size_t write_length,
       QuicStreamOffset offset,
       StreamSendingState state,
-      bool /*is_retransmission*/,
+      TransmissionType /*type*/,
       quiche::QuicheOptional<EncryptionLevel> /*level*/) {
     if (write_length > 0) {
       auto buf = std::make_unique<char[]>(write_length);