Fix ping policy
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
index 79a9ed8..3a28762 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c
@@ -557,8 +557,8 @@
     }
   }
 
-  t->ping_state.pings_before_data_required =
-      t->ping_policy.max_pings_without_data;
+  /* No pings allowed before receiving a header or data frame. */
+  t->ping_state.pings_before_data_required = 0;
   t->ping_state.is_delayed_ping_timer_set = false;
 
   t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c
index 6c12c91..e52e19f 100644
--- a/src/core/ext/transport/chttp2/transport/parsing.c
+++ b/src/core/ext/transport/chttp2/transport/parsing.c
@@ -383,6 +383,8 @@
     /* t->parser = grpc_chttp2_data_parser_parse;*/
     t->parser = grpc_chttp2_data_parser_parse;
     t->parser_data = &s->data_parser;
+    t->ping_state.pings_before_data_required =
+        t->ping_policy.max_pings_without_data;
     return GRPC_ERROR_NONE;
   } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
     /* handle stream errors by closing the stream */
@@ -559,6 +561,9 @@
         (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
   }
 
+  t->ping_state.pings_before_data_required =
+      t->ping_policy.max_pings_without_data;
+
   /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
   s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
   if (s == NULL) {
diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c
index 3ded801..d369930 100644
--- a/src/core/ext/transport/chttp2/transport/writing.c
+++ b/src/core/ext/transport/chttp2/transport/writing.c
@@ -66,9 +66,17 @@
     }
     return;
   }
+  if (t->keepalive_permit_without_calls == 0 &&
+      grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
+    if (GRPC_TRACER_ON(grpc_http_trace) ||
+        GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
+      gpr_log(GPR_DEBUG, "Ping delayed [%p]: no active stream", t->peer_string);
+    }
+    return;
+  }
   if (t->ping_state.pings_before_data_required == 0 &&
       t->ping_policy.max_pings_without_data != 0) {
-    /* need to send something of substance before sending a ping again */
+    /* need to receive something of substance before sending a ping again */
     if (GRPC_TRACER_ON(grpc_http_trace) ||
         GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
       gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d",
@@ -297,8 +305,6 @@
       grpc_slice_buffer_add(
           &t->outbuf, grpc_chttp2_window_update_create(s->id, stream_announce,
                                                        &s->stats.outgoing));
-      t->ping_state.pings_before_data_required =
-          t->ping_policy.max_pings_without_data;
       if (!t->is_client) {
         t->ping_recv_state.last_ping_recv_time =
             gpr_inf_past(GPR_CLOCK_MONOTONIC);
@@ -375,8 +381,6 @@
                                           send_bytes);
             s->sending_bytes += send_bytes;
           }
-          t->ping_state.pings_before_data_required =
-              t->ping_policy.max_pings_without_data;
           if (!t->is_client) {
             t->ping_recv_state.last_ping_recv_time =
                 gpr_inf_past(GPR_CLOCK_MONOTONIC);
@@ -487,8 +491,6 @@
     grpc_slice_buffer_add(
         &t->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
                                                      &throwaway_stats));
-    t->ping_state.pings_before_data_required =
-        t->ping_policy.max_pings_without_data;
     if (!t->is_client) {
       t->ping_recv_state.last_ping_recv_time =
           gpr_inf_past(GPR_CLOCK_MONOTONIC);
diff --git a/test/core/end2end/tests/bad_ping.c b/test/core/end2end/tests/bad_ping.c
index 12aceda..6713597 100644
--- a/test/core/end2end/tests/bad_ping.c
+++ b/test/core/end2end/tests/bad_ping.c
@@ -71,7 +71,7 @@
                           .value.integer = 0},
                          {.type = GRPC_ARG_INTEGER,
                           .key = GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA,
-                          .value.integer = 20},
+                          .value.integer = 0},
                          {.type = GRPC_ARG_INTEGER,
                           .key = GRPC_ARG_HTTP2_BDP_PROBE,
                           .value.integer = 0}};
diff --git a/test/core/end2end/tests/ping.c b/test/core/end2end/tests/ping.c
index 112ad9d..b4d9b13 100644
--- a/test/core/end2end/tests/ping.c
+++ b/test/core/end2end/tests/ping.c
@@ -42,7 +42,10 @@
                           .value.integer = 0},
                          {.type = GRPC_ARG_INTEGER,
                           .key = GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA,
-                          .value.integer = 20}};
+                          .value.integer = 0},
+                         {.type = GRPC_ARG_INTEGER,
+                          .key = GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS,
+                          .value.integer = 1}};
   grpc_arg server_a[] = {
       {.type = GRPC_ARG_INTEGER,
        .key = GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS,