Merge github.com:grpc/grpc into slice_with_exec_ctx
diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc
index 12209f3..61f3953 100644
--- a/examples/cpp/helloworld/greeter_client.cc
+++ b/examples/cpp/helloworld/greeter_client.cc
@@ -51,7 +51,7 @@
   GreeterClient(std::shared_ptr<Channel> channel)
       : stub_(Greeter::NewStub(channel)) {}
 
-  // Assambles the client's payload, sends it and presents the response back
+  // Assembles the client's payload, sends it and presents the response back
   // from the server.
   std::string SayHello(const std::string& user) {
     // Data we are sending to the server.
diff --git a/examples/python/multiplex/run_codegen.py b/examples/python/multiplex/run_codegen.py
index 7922a0f..89ac9c8 100755
--- a/examples/python/multiplex/run_codegen.py
+++ b/examples/python/multiplex/run_codegen.py
@@ -29,7 +29,7 @@
 
 """Generates protocol messages and gRPC stubs."""
 
-from grpc.tools import protoc
+from grpc_tools import protoc
 
 protoc.main(
     (
diff --git a/examples/python/route_guide/run_codegen.py b/examples/python/route_guide/run_codegen.py
index c7c6008..3751e01 100644
--- a/examples/python/route_guide/run_codegen.py
+++ b/examples/python/route_guide/run_codegen.py
@@ -29,7 +29,7 @@
 
 """Runs protoc with the gRPC plugin to generate messages and gRPC stubs."""
 
-from grpc.tools import protoc
+from grpc_tools import protoc
 
 protoc.main(
     (
diff --git a/src/compiler/csharp_generator.cc b/src/compiler/csharp_generator.cc
index a3af258..cc7a7a9 100644
--- a/src/compiler/csharp_generator.cc
+++ b/src/compiler/csharp_generator.cc
@@ -68,13 +68,13 @@
 // Currently, we cannot easily reuse the functionality as
 // google/protobuf/compiler/csharp/csharp_doc_comment.h is not a public header.
 // TODO(jtattermusch): reuse the functionality from google/protobuf.
-void GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer *printer,
+bool GenerateDocCommentBodyImpl(grpc::protobuf::io::Printer *printer,
                                 grpc::protobuf::SourceLocation location) {
   grpc::string comments = location.leading_comments.empty()
                               ? location.trailing_comments
                               : location.leading_comments;
   if (comments.empty()) {
-    return;
+    return false;
   }
   // XML escaping... no need for apostrophes etc as the whole text is going to
   // be a child
@@ -107,18 +107,84 @@
         printer->Print("///\n");
       }
       last_was_empty = false;
-      printer->Print("/// $line$\n", "line", *it);
+      printer->Print("///$line$\n", "line", *it);
     }
   }
   printer->Print("/// </summary>\n");
+  return true;
 }
 
 template <typename DescriptorType>
-void GenerateDocCommentBody(grpc::protobuf::io::Printer *printer,
+bool GenerateDocCommentBody(grpc::protobuf::io::Printer *printer,
                             const DescriptorType *descriptor) {
   grpc::protobuf::SourceLocation location;
-  if (descriptor->GetSourceLocation(&location)) {
-    GenerateDocCommentBodyImpl(printer, location);
+  if (!descriptor->GetSourceLocation(&location)) {
+    return false;
+  }
+  return GenerateDocCommentBodyImpl(printer, location);
+}
+
+void GenerateDocCommentServerMethod(grpc::protobuf::io::Printer *printer,
+                                    const MethodDescriptor *method) {
+  if (GenerateDocCommentBody(printer, method)) {
+    if (method->client_streaming()) {
+      printer->Print(
+          "/// <param name=\"requestStream\">Used for reading requests from "
+          "the client.</param>\n");
+    } else {
+      printer->Print(
+          "/// <param name=\"request\">The request received from the "
+          "client.</param>\n");
+    }
+    if (method->server_streaming()) {
+      printer->Print(
+          "/// <param name=\"responseStream\">Used for sending responses back "
+          "to the client.</param>\n");
+    }
+    printer->Print(
+        "/// <param name=\"context\">The context of the server-side call "
+        "handler being invoked.</param>\n");
+    if (method->server_streaming()) {
+      printer->Print(
+          "/// <returns>A task indicating completion of the "
+          "handler.</returns>\n");
+    } else {
+      printer->Print(
+          "/// <returns>The response to send back to the client (wrapped by a "
+          "task).</returns>\n");
+    }
+  }
+}
+
+void GenerateDocCommentClientMethod(grpc::protobuf::io::Printer *printer,
+                                    const MethodDescriptor *method,
+                                    bool is_sync, bool use_call_options) {
+  if (GenerateDocCommentBody(printer, method)) {
+    if (!method->client_streaming()) {
+      printer->Print(
+          "/// <param name=\"request\">The request to send to the "
+          "server.</param>\n");
+    }
+    if (!use_call_options) {
+      printer->Print(
+          "/// <param name=\"headers\">The initial metadata to send with the "
+          "call. This parameter is optional.</param>\n");
+      printer->Print(
+          "/// <param name=\"deadline\">An optional deadline for the call. The "
+          "call will be cancelled if deadline is hit.</param>\n");
+      printer->Print(
+          "/// <param name=\"cancellationToken\">An optional token for "
+          "canceling the call.</param>\n");
+    } else {
+      printer->Print(
+          "/// <param name=\"options\">The options for the call.</param>\n");
+    }
+    if (is_sync) {
+      printer->Print(
+          "/// <returns>The response received from the server.</returns>\n");
+    } else {
+      printer->Print("/// <returns>The call object.</returns>\n");
+    }
   }
 }
 
@@ -319,7 +385,7 @@
   out->Indent();
   for (int i = 0; i < service->method_count(); i++) {
     const MethodDescriptor *method = service->method(i);
-    GenerateDocCommentBody(out, method);
+    GenerateDocCommentServerMethod(out, method);
     out->Print(
         "public virtual $returntype$ "
         "$methodname$($request$$response_stream_maybe$, "
@@ -393,7 +459,7 @@
 
     if (method_type == METHODTYPE_NO_STREAMING) {
       // unary calls have an extra synchronous stub method
-      GenerateDocCommentBody(out, method);
+      GenerateDocCommentClientMethod(out, method, true, false);
       out->Print(
           "public virtual $response$ $methodname$($request$ request, Metadata "
           "headers = null, DateTime? deadline = null, CancellationToken "
@@ -411,7 +477,7 @@
       out->Print("}\n");
 
       // overload taking CallOptions as a param
-      GenerateDocCommentBody(out, method);
+      GenerateDocCommentClientMethod(out, method, true, true);
       out->Print(
           "public virtual $response$ $methodname$($request$ request, "
           "CallOptions options)\n",
@@ -432,7 +498,7 @@
     if (method_type == METHODTYPE_NO_STREAMING) {
       method_name += "Async";  // prevent name clash with synchronous method.
     }
-    GenerateDocCommentBody(out, method);
+    GenerateDocCommentClientMethod(out, method, false, false);
     out->Print(
         "public virtual $returntype$ $methodname$($request_maybe$Metadata "
         "headers = null, DateTime? deadline = null, CancellationToken "
@@ -452,7 +518,7 @@
     out->Print("}\n");
 
     // overload taking CallOptions as a param
-    GenerateDocCommentBody(out, method);
+    GenerateDocCommentClientMethod(out, method, false, true);
     out->Print(
         "public virtual $returntype$ $methodname$($request_maybe$CallOptions "
         "options)\n",
@@ -518,6 +584,9 @@
       "/// <summary>Creates service definition that can be registered with a "
       "server</summary>\n");
   out->Print(
+      "/// <param name=\"serviceImpl\">An object implementing the server-side"
+      " handling logic.</param>\n");
+  out->Print(
       "public static ServerServiceDefinition BindService($implclass$ "
       "serviceImpl)\n",
       "implclass", GetServerClassName(service));
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 0e2ec47..f80d655 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -687,9 +687,15 @@
                                      "Failed to create subchannel", &error, 1));
   } else if (GET_CALL(calld) == CANCELLED_CALL) {
     /* already cancelled before subchannel became ready */
-    fail_locked(exec_ctx, calld,
-                GRPC_ERROR_CREATE_REFERENCING(
-                    "Cancelled before creating subchannel", &error, 1));
+    grpc_error *cancellation_error = GRPC_ERROR_CREATE_REFERENCING(
+        "Cancelled before creating subchannel", &error, 1);
+    /* if due to deadline, attach the deadline exceeded status to the error */
+    if (gpr_time_cmp(calld->deadline, gpr_now(GPR_CLOCK_MONOTONIC)) < 0) {
+      cancellation_error =
+          grpc_error_set_int(cancellation_error, GRPC_ERROR_INT_GRPC_STATUS,
+                             GRPC_STATUS_DEADLINE_EXCEEDED);
+    }
+    fail_locked(exec_ctx, calld, cancellation_error);
   } else {
     /* Create call on subchannel. */
     grpc_subchannel_call *subchannel_call = NULL;
@@ -813,7 +819,6 @@
         initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY;
       }
     }
-    // TODO(dgq): make this deadline configurable somehow.
     const grpc_lb_policy_pick_args inputs = {
         initial_metadata, initial_metadata_flags, &calld->lb_token_mdelem,
         gpr_inf_future(GPR_CLOCK_MONOTONIC)};
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index 8b431c7..3364b8c 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -85,39 +85,53 @@
     public abstract partial class MathBase
     {
       /// <summary>
-      ///  Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
-      ///  and remainder.
+      /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
+      /// and remainder.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Math.DivReply> Div(global::Math.DivArgs request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  DivMany accepts an arbitrary number of division args from the client stream
-      ///  and sends back the results in the reply stream.  The stream continues until
-      ///  the client closes its end; the server does the same after sending all the
-      ///  replies.  The stream ends immediately if either end aborts.
+      /// DivMany accepts an arbitrary number of division args from the client stream
+      /// and sends back the results in the reply stream.  The stream continues until
+      /// the client closes its end; the server does the same after sending all the
+      /// replies.  The stream ends immediately if either end aborts.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task DivMany(IAsyncStreamReader<global::Math.DivArgs> requestStream, IServerStreamWriter<global::Math.DivReply> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
-      ///  generates up to limit numbers; otherwise it continues until the call is
-      ///  canceled.  Unlike Fib above, Fib has no final FibReply.
+      /// Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
+      /// generates up to limit numbers; otherwise it continues until the call is
+      /// canceled.  Unlike Fib above, Fib has no final FibReply.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task Fib(global::Math.FibArgs request, IServerStreamWriter<global::Math.Num> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  Sum sums a stream of numbers, returning the final result once the stream
-      ///  is closed.
+      /// Sum sums a stream of numbers, returning the final result once the stream
+      /// is closed.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Math.Num> Sum(IAsyncStreamReader<global::Math.Num> requestStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -149,87 +163,123 @@
       }
 
       /// <summary>
-      ///  Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
-      ///  and remainder.
+      /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
+      /// and remainder.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Math.DivReply Div(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return Div(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
-      ///  and remainder.
+      /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
+      /// and remainder.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Math.DivReply Div(global::Math.DivArgs request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_Div, null, options, request);
       }
       /// <summary>
-      ///  Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
-      ///  and remainder.
+      /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
+      /// and remainder.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return DivAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
-      ///  and remainder.
+      /// Div divides DivArgs.dividend by DivArgs.divisor and returns the quotient
+      /// and remainder.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Math.DivReply> DivAsync(global::Math.DivArgs request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_Div, null, options, request);
       }
       /// <summary>
-      ///  DivMany accepts an arbitrary number of division args from the client stream
-      ///  and sends back the results in the reply stream.  The stream continues until
-      ///  the client closes its end; the server does the same after sending all the
-      ///  replies.  The stream ends immediately if either end aborts.
+      /// DivMany accepts an arbitrary number of division args from the client stream
+      /// and sends back the results in the reply stream.  The stream continues until
+      /// the client closes its end; the server does the same after sending all the
+      /// replies.  The stream ends immediately if either end aborts.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return DivMany(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  DivMany accepts an arbitrary number of division args from the client stream
-      ///  and sends back the results in the reply stream.  The stream continues until
-      ///  the client closes its end; the server does the same after sending all the
-      ///  replies.  The stream ends immediately if either end aborts.
+      /// DivMany accepts an arbitrary number of division args from the client stream
+      /// and sends back the results in the reply stream.  The stream continues until
+      /// the client closes its end; the server does the same after sending all the
+      /// replies.  The stream ends immediately if either end aborts.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Math.DivArgs, global::Math.DivReply> DivMany(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_DivMany, null, options);
       }
       /// <summary>
-      ///  Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
-      ///  generates up to limit numbers; otherwise it continues until the call is
-      ///  canceled.  Unlike Fib above, Fib has no final FibReply.
+      /// Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
+      /// generates up to limit numbers; otherwise it continues until the call is
+      /// canceled.  Unlike Fib above, Fib has no final FibReply.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return Fib(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
-      ///  generates up to limit numbers; otherwise it continues until the call is
-      ///  canceled.  Unlike Fib above, Fib has no final FibReply.
+      /// Fib generates numbers in the Fibonacci sequence.  If FibArgs.limit > 0, Fib
+      /// generates up to limit numbers; otherwise it continues until the call is
+      /// canceled.  Unlike Fib above, Fib has no final FibReply.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncServerStreamingCall<global::Math.Num> Fib(global::Math.FibArgs request, CallOptions options)
       {
         return CallInvoker.AsyncServerStreamingCall(__Method_Fib, null, options, request);
       }
       /// <summary>
-      ///  Sum sums a stream of numbers, returning the final result once the stream
-      ///  is closed.
+      /// Sum sums a stream of numbers, returning the final result once the stream
+      /// is closed.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return Sum(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Sum sums a stream of numbers, returning the final result once the stream
-      ///  is closed.
+      /// Sum sums a stream of numbers, returning the final result once the stream
+      /// is closed.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncClientStreamingCall<global::Math.Num, global::Math.Num> Sum(CallOptions options)
       {
         return CallInvoker.AsyncClientStreamingCall(__Method_Sum, null, options);
@@ -242,6 +292,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(MathBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index ad5cf11..020c2df 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -115,6 +115,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(HealthBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
diff --git a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
index d0bf0af..8b58622 100644
--- a/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
@@ -76,17 +76,24 @@
     public abstract partial class MetricsServiceBase
     {
       /// <summary>
-      ///  Returns the values of all the gauges that are currently being maintained by
-      ///  the service
+      /// Returns the values of all the gauges that are currently being maintained by
+      /// the service
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task GetAllGauges(global::Grpc.Testing.EmptyMessage request, IServerStreamWriter<global::Grpc.Testing.GaugeResponse> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  Returns the value of one gauge
+      /// Returns the value of one gauge
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.GaugeResponse> GetGauge(global::Grpc.Testing.GaugeRequest request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -118,45 +125,69 @@
       }
 
       /// <summary>
-      ///  Returns the values of all the gauges that are currently being maintained by
-      ///  the service
+      /// Returns the values of all the gauges that are currently being maintained by
+      /// the service
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return GetAllGauges(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Returns the values of all the gauges that are currently being maintained by
-      ///  the service
+      /// Returns the values of all the gauges that are currently being maintained by
+      /// the service
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncServerStreamingCall<global::Grpc.Testing.GaugeResponse> GetAllGauges(global::Grpc.Testing.EmptyMessage request, CallOptions options)
       {
         return CallInvoker.AsyncServerStreamingCall(__Method_GetAllGauges, null, options, request);
       }
       /// <summary>
-      ///  Returns the value of one gauge
+      /// Returns the value of one gauge
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return GetGauge(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Returns the value of one gauge
+      /// Returns the value of one gauge
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.GaugeResponse GetGauge(global::Grpc.Testing.GaugeRequest request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_GetGauge, null, options, request);
       }
       /// <summary>
-      ///  Returns the value of one gauge
+      /// Returns the value of one gauge
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return GetGaugeAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Returns the value of one gauge
+      /// Returns the value of one gauge
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.GaugeResponse> GetGaugeAsync(global::Grpc.Testing.GaugeRequest request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_GetGauge, null, options, request);
@@ -169,6 +200,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(MetricsServiceBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
index 3cc4ed9..5135d9a 100644
--- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
@@ -71,18 +71,25 @@
     public abstract partial class BenchmarkServiceBase
     {
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task StreamingCall(IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -114,49 +121,71 @@
       }
 
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return StreamingCall(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response.
-      ///  The server returns the client payload as-is.
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
@@ -169,6 +198,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
@@ -227,42 +257,56 @@
     public abstract partial class WorkerServiceBase
     {
       /// <summary>
-      ///  Start server with specified workload.
-      ///  First request sent specifies the ServerConfig followed by ServerStatus
-      ///  response. After that, a "Mark" can be sent anytime to request the latest
-      ///  stats. Closing the stream will initiate shutdown of the test server
-      ///  and once the shutdown has finished, the OK status is sent to terminate
-      ///  this RPC.
+      /// Start server with specified workload.
+      /// First request sent specifies the ServerConfig followed by ServerStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test server
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task RunServer(IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  Start client with specified workload.
-      ///  First request sent specifies the ClientConfig followed by ClientStatus
-      ///  response. After that, a "Mark" can be sent anytime to request the latest
-      ///  stats. Closing the stream will initiate shutdown of the test client
-      ///  and once the shutdown has finished, the OK status is sent to terminate
-      ///  this RPC.
+      /// Start client with specified workload.
+      /// First request sent specifies the ClientConfig followed by ClientStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test client
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task RunClient(IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  Just return the core count - unary call
+      /// Just return the core count - unary call
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  Quit this worker
+      /// Quit this worker
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -294,105 +338,149 @@
       }
 
       /// <summary>
-      ///  Start server with specified workload.
-      ///  First request sent specifies the ServerConfig followed by ServerStatus
-      ///  response. After that, a "Mark" can be sent anytime to request the latest
-      ///  stats. Closing the stream will initiate shutdown of the test server
-      ///  and once the shutdown has finished, the OK status is sent to terminate
-      ///  this RPC.
+      /// Start server with specified workload.
+      /// First request sent specifies the ServerConfig followed by ServerStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test server
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return RunServer(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Start server with specified workload.
-      ///  First request sent specifies the ServerConfig followed by ServerStatus
-      ///  response. After that, a "Mark" can be sent anytime to request the latest
-      ///  stats. Closing the stream will initiate shutdown of the test server
-      ///  and once the shutdown has finished, the OK status is sent to terminate
-      ///  this RPC.
+      /// Start server with specified workload.
+      /// First request sent specifies the ServerConfig followed by ServerStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test server
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
       }
       /// <summary>
-      ///  Start client with specified workload.
-      ///  First request sent specifies the ClientConfig followed by ClientStatus
-      ///  response. After that, a "Mark" can be sent anytime to request the latest
-      ///  stats. Closing the stream will initiate shutdown of the test client
-      ///  and once the shutdown has finished, the OK status is sent to terminate
-      ///  this RPC.
+      /// Start client with specified workload.
+      /// First request sent specifies the ClientConfig followed by ClientStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test client
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return RunClient(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Start client with specified workload.
-      ///  First request sent specifies the ClientConfig followed by ClientStatus
-      ///  response. After that, a "Mark" can be sent anytime to request the latest
-      ///  stats. Closing the stream will initiate shutdown of the test client
-      ///  and once the shutdown has finished, the OK status is sent to terminate
-      ///  this RPC.
+      /// Start client with specified workload.
+      /// First request sent specifies the ClientConfig followed by ClientStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test client
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
       }
       /// <summary>
-      ///  Just return the core count - unary call
+      /// Just return the core count - unary call
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return CoreCount(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Just return the core count - unary call
+      /// Just return the core count - unary call
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
       }
       /// <summary>
-      ///  Just return the core count - unary call
+      /// Just return the core count - unary call
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return CoreCountAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Just return the core count - unary call
+      /// Just return the core count - unary call
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
       }
       /// <summary>
-      ///  Quit this worker
+      /// Quit this worker
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return QuitWorker(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Quit this worker
+      /// Quit this worker
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
       }
       /// <summary>
-      ///  Quit this worker
+      /// Quit this worker
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return QuitWorkerAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  Quit this worker
+      /// Quit this worker
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
@@ -405,6 +493,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
diff --git a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
index 43dbc28..0265f8e 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
@@ -42,8 +42,8 @@
 
 namespace Grpc.Testing {
   /// <summary>
-  ///  A simple service to test the various types of RPCs and experiment with
-  ///  performance with various types of payload.
+  /// A simple service to test the various types of RPCs and experiment with
+  /// performance with various types of payload.
   /// </summary>
   public static partial class TestService
   {
@@ -123,74 +123,101 @@
     public abstract partial class TestServiceBase
     {
       /// <summary>
-      ///  One empty request followed by one empty response.
+      /// One empty request followed by one empty response.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> EmptyCall(global::Grpc.Testing.Empty request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  One request followed by one response.
+      /// One request followed by one response.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  One request followed by one response. Response has cache control
-      ///  headers set such that a caching HTTP proxy (such as GFE) can
-      ///  satisfy subsequent requests.
+      /// One request followed by one response. Response has cache control
+      /// headers set such that a caching HTTP proxy (such as GFE) can
+      /// satisfy subsequent requests.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  One request followed by a sequence of responses (streamed download).
-      ///  The server returns the payload with client desired type and sizes.
+      /// One request followed by a sequence of responses (streamed download).
+      /// The server returns the payload with client desired type and sizes.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  A sequence of requests followed by one response (streamed upload).
-      ///  The server returns the aggregated size of client payload as the result.
+      /// A sequence of requests followed by one response (streamed upload).
+      /// The server returns the aggregated size of client payload as the result.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(IAsyncStreamReader<global::Grpc.Testing.StreamingInputCallRequest> requestStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  A sequence of requests with each request served by the server immediately.
-      ///  As one request could lead to multiple responses, this interface
-      ///  demonstrates the idea of full duplexing.
+      /// A sequence of requests with each request served by the server immediately.
+      /// As one request could lead to multiple responses, this interface
+      /// demonstrates the idea of full duplexing.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task FullDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  A sequence of requests followed by a sequence of responses.
-      ///  The server buffers all the client requests and then serves them in order. A
-      ///  stream of responses are returned to the client when the server starts with
-      ///  first request.
+      /// A sequence of requests followed by a sequence of responses.
+      /// The server buffers all the client requests and then serves them in order. A
+      /// stream of responses are returned to the client when the server starts with
+      /// first request.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task HalfDuplexCall(IAsyncStreamReader<global::Grpc.Testing.StreamingOutputCallRequest> requestStream, IServerStreamWriter<global::Grpc.Testing.StreamingOutputCallResponse> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
       }
 
       /// <summary>
-      ///  The test server will not implement this method. It will be used
-      ///  to test the behavior when clients call unimplemented methods.
+      /// The test server will not implement this method. It will be used
+      /// to test the behavior when clients call unimplemented methods.
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -222,195 +249,285 @@
       }
 
       /// <summary>
-      ///  One empty request followed by one empty response.
+      /// One empty request followed by one empty response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return EmptyCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One empty request followed by one empty response.
+      /// One empty request followed by one empty response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Empty EmptyCall(global::Grpc.Testing.Empty request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_EmptyCall, null, options, request);
       }
       /// <summary>
-      ///  One empty request followed by one empty response.
+      /// One empty request followed by one empty response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return EmptyCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One empty request followed by one empty response.
+      /// One empty request followed by one empty response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> EmptyCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_EmptyCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by one response.
+      /// One request followed by one response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response.
+      /// One request followed by one response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by one response.
+      /// One request followed by one response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response.
+      /// One request followed by one response.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by one response. Response has cache control
-      ///  headers set such that a caching HTTP proxy (such as GFE) can
-      ///  satisfy subsequent requests.
+      /// One request followed by one response. Response has cache control
+      /// headers set such that a caching HTTP proxy (such as GFE) can
+      /// satisfy subsequent requests.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return CacheableUnaryCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response. Response has cache control
-      ///  headers set such that a caching HTTP proxy (such as GFE) can
-      ///  satisfy subsequent requests.
+      /// One request followed by one response. Response has cache control
+      /// headers set such that a caching HTTP proxy (such as GFE) can
+      /// satisfy subsequent requests.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.SimpleResponse CacheableUnaryCall(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_CacheableUnaryCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by one response. Response has cache control
-      ///  headers set such that a caching HTTP proxy (such as GFE) can
-      ///  satisfy subsequent requests.
+      /// One request followed by one response. Response has cache control
+      /// headers set such that a caching HTTP proxy (such as GFE) can
+      /// satisfy subsequent requests.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return CacheableUnaryCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by one response. Response has cache control
-      ///  headers set such that a caching HTTP proxy (such as GFE) can
-      ///  satisfy subsequent requests.
+      /// One request followed by one response. Response has cache control
+      /// headers set such that a caching HTTP proxy (such as GFE) can
+      /// satisfy subsequent requests.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> CacheableUnaryCallAsync(global::Grpc.Testing.SimpleRequest request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_CacheableUnaryCall, null, options, request);
       }
       /// <summary>
-      ///  One request followed by a sequence of responses (streamed download).
-      ///  The server returns the payload with client desired type and sizes.
+      /// One request followed by a sequence of responses (streamed download).
+      /// The server returns the payload with client desired type and sizes.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return StreamingOutputCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  One request followed by a sequence of responses (streamed download).
-      ///  The server returns the payload with client desired type and sizes.
+      /// One request followed by a sequence of responses (streamed download).
+      /// The server returns the payload with client desired type and sizes.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncServerStreamingCall<global::Grpc.Testing.StreamingOutputCallResponse> StreamingOutputCall(global::Grpc.Testing.StreamingOutputCallRequest request, CallOptions options)
       {
         return CallInvoker.AsyncServerStreamingCall(__Method_StreamingOutputCall, null, options, request);
       }
       /// <summary>
-      ///  A sequence of requests followed by one response (streamed upload).
-      ///  The server returns the aggregated size of client payload as the result.
+      /// A sequence of requests followed by one response (streamed upload).
+      /// The server returns the aggregated size of client payload as the result.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return StreamingInputCall(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  A sequence of requests followed by one response (streamed upload).
-      ///  The server returns the aggregated size of client payload as the result.
+      /// A sequence of requests followed by one response (streamed upload).
+      /// The server returns the aggregated size of client payload as the result.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncClientStreamingCall<global::Grpc.Testing.StreamingInputCallRequest, global::Grpc.Testing.StreamingInputCallResponse> StreamingInputCall(CallOptions options)
       {
         return CallInvoker.AsyncClientStreamingCall(__Method_StreamingInputCall, null, options);
       }
       /// <summary>
-      ///  A sequence of requests with each request served by the server immediately.
-      ///  As one request could lead to multiple responses, this interface
-      ///  demonstrates the idea of full duplexing.
+      /// A sequence of requests with each request served by the server immediately.
+      /// As one request could lead to multiple responses, this interface
+      /// demonstrates the idea of full duplexing.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return FullDuplexCall(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  A sequence of requests with each request served by the server immediately.
-      ///  As one request could lead to multiple responses, this interface
-      ///  demonstrates the idea of full duplexing.
+      /// A sequence of requests with each request served by the server immediately.
+      /// As one request could lead to multiple responses, this interface
+      /// demonstrates the idea of full duplexing.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> FullDuplexCall(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_FullDuplexCall, null, options);
       }
       /// <summary>
-      ///  A sequence of requests followed by a sequence of responses.
-      ///  The server buffers all the client requests and then serves them in order. A
-      ///  stream of responses are returned to the client when the server starts with
-      ///  first request.
+      /// A sequence of requests followed by a sequence of responses.
+      /// The server buffers all the client requests and then serves them in order. A
+      /// stream of responses are returned to the client when the server starts with
+      /// first request.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return HalfDuplexCall(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  A sequence of requests followed by a sequence of responses.
-      ///  The server buffers all the client requests and then serves them in order. A
-      ///  stream of responses are returned to the client when the server starts with
-      ///  first request.
+      /// A sequence of requests followed by a sequence of responses.
+      /// The server buffers all the client requests and then serves them in order. A
+      /// stream of responses are returned to the client when the server starts with
+      /// first request.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Testing.StreamingOutputCallRequest, global::Grpc.Testing.StreamingOutputCallResponse> HalfDuplexCall(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_HalfDuplexCall, null, options);
       }
       /// <summary>
-      ///  The test server will not implement this method. It will be used
-      ///  to test the behavior when clients call unimplemented methods.
+      /// The test server will not implement this method. It will be used
+      /// to test the behavior when clients call unimplemented methods.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  The test server will not implement this method. It will be used
-      ///  to test the behavior when clients call unimplemented methods.
+      /// The test server will not implement this method. It will be used
+      /// to test the behavior when clients call unimplemented methods.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
       }
       /// <summary>
-      ///  The test server will not implement this method. It will be used
-      ///  to test the behavior when clients call unimplemented methods.
+      /// The test server will not implement this method. It will be used
+      /// to test the behavior when clients call unimplemented methods.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  The test server will not implement this method. It will be used
-      ///  to test the behavior when clients call unimplemented methods.
+      /// The test server will not implement this method. It will be used
+      /// to test the behavior when clients call unimplemented methods.
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
@@ -423,6 +540,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(TestServiceBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
@@ -438,8 +556,8 @@
 
   }
   /// <summary>
-  ///  A simple service NOT implemented at servers so clients can test for
-  ///  that case.
+  /// A simple service NOT implemented at servers so clients can test for
+  /// that case.
   /// </summary>
   public static partial class UnimplementedService
   {
@@ -464,8 +582,11 @@
     public abstract partial class UnimplementedServiceBase
     {
       /// <summary>
-      ///  A call that no server should implement
+      /// A call that no server should implement
       /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Empty> UnimplementedCall(global::Grpc.Testing.Empty request, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -497,29 +618,45 @@
       }
 
       /// <summary>
-      ///  A call that no server should implement
+      /// A call that no server should implement
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnimplementedCall(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  A call that no server should implement
+      /// A call that no server should implement
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Testing.Empty UnimplementedCall(global::Grpc.Testing.Empty request, CallOptions options)
       {
         return CallInvoker.BlockingUnaryCall(__Method_UnimplementedCall, null, options, request);
       }
       /// <summary>
-      ///  A call that no server should implement
+      /// A call that no server should implement
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return UnimplementedCallAsync(request, new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  A call that no server should implement
+      /// A call that no server should implement
       /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncUnaryCall<global::Grpc.Testing.Empty> UnimplementedCallAsync(global::Grpc.Testing.Empty request, CallOptions options)
       {
         return CallInvoker.AsyncUnaryCall(__Method_UnimplementedCall, null, options, request);
@@ -532,6 +669,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(UnimplementedServiceBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
@@ -540,7 +678,7 @@
 
   }
   /// <summary>
-  ///  A service used to control reconnect server.
+  /// A service used to control reconnect server.
   /// </summary>
   public static partial class ReconnectService
   {
@@ -648,6 +786,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(ReconnectServiceBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
diff --git a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs
index 1b6f96c..5bd7558 100644
--- a/src/csharp/Grpc.Reflection/ReflectionGrpc.cs
+++ b/src/csharp/Grpc.Reflection/ReflectionGrpc.cs
@@ -64,9 +64,13 @@
     public abstract partial class ServerReflectionBase
     {
       /// <summary>
-      ///  The reflection service is structured as a bidirectional stream, ensuring
-      ///  all related requests go to a single server.
+      /// The reflection service is structured as a bidirectional stream, ensuring
+      /// all related requests go to a single server.
       /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
       public virtual global::System.Threading.Tasks.Task ServerReflectionInfo(IAsyncStreamReader<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest> requestStream, IServerStreamWriter<global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> responseStream, ServerCallContext context)
       {
         throw new RpcException(new Status(StatusCode.Unimplemented, ""));
@@ -98,17 +102,23 @@
       }
 
       /// <summary>
-      ///  The reflection service is structured as a bidirectional stream, ensuring
-      ///  all related requests go to a single server.
+      /// The reflection service is structured as a bidirectional stream, ensuring
+      /// all related requests go to a single server.
       /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(Metadata headers = null, DateTime? deadline = null, CancellationToken cancellationToken = default(CancellationToken))
       {
         return ServerReflectionInfo(new CallOptions(headers, deadline, cancellationToken));
       }
       /// <summary>
-      ///  The reflection service is structured as a bidirectional stream, ensuring
-      ///  all related requests go to a single server.
+      /// The reflection service is structured as a bidirectional stream, ensuring
+      /// all related requests go to a single server.
       /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual AsyncDuplexStreamingCall<global::Grpc.Reflection.V1Alpha.ServerReflectionRequest, global::Grpc.Reflection.V1Alpha.ServerReflectionResponse> ServerReflectionInfo(CallOptions options)
       {
         return CallInvoker.AsyncDuplexStreamingCall(__Method_ServerReflectionInfo, null, options);
@@ -121,6 +131,7 @@
     }
 
     /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
     public static ServerServiceDefinition BindService(ServerReflectionBase serviceImpl)
     {
       return ServerServiceDefinition.CreateBuilder()
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index cfad7de..9defb31 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -31,6 +31,7 @@
 
 import abc
 import enum
+import sys
 
 import six
 
@@ -925,21 +926,6 @@
     raise NotImplementedError()
 
   @abc.abstractmethod
-  def add_shutdown_handler(self, shutdown_handler):
-    """Adds a handler to be called on server shutdown.
-
-    Shutdown handlers are run on server stop() or in the event that a running
-    server is destroyed unexpectedly.  The handlers are run in series before
-    the stop grace period.
-
-    Args:
-      shutdown_handler:  A function taking a single arg, a time in seconds
-      within which the handler should complete.  None indicates the handler can
-      run for any duration.
-    """
-    raise NotImplementedError()
-
-  @abc.abstractmethod
   def start(self):
     """Starts this Server's service of RPCs.
 
@@ -949,7 +935,7 @@
     raise NotImplementedError()
 
   @abc.abstractmethod
-  def stop(self, grace, shutdown_handler_grace=None):
+  def stop(self, grace):
     """Stops this Server's service of RPCs.
 
     All calls to this method immediately stop service of new RPCs. When existing
@@ -972,8 +958,6 @@
         aborted by this Server's stopping. If None, all RPCs will be aborted
         immediately and this method will block until this Server is completely
         stopped.
-      shutdown_handler_grace:  A duration of time in seconds or None.  This
-        value is passed to all shutdown handlers.
 
     Returns:
       A threading.Event that will be set when this Server has completely
@@ -1268,8 +1252,7 @@
                           credentials._credentials)
 
 
-def server(thread_pool, handlers=None, options=None, exit_grace=None,
-           exit_shutdown_handler_grace=None):
+def server(thread_pool, handlers=None, options=None):
   """Creates a Server with which RPCs can be serviced.
 
   Args:
@@ -1282,19 +1265,13 @@
       returned Server is started.
     options: A sequence of string-value pairs according to which to configure
       the created server.
-    exit_grace:  The grace period to use when terminating
-      running servers at interpreter exit.  None indicates unspecified.
-    exit_shutdown_handler_grace:  The shutdown handler grace to use when
-      terminating running servers at interpreter exit.  None indicates
-      unspecified.
 
   Returns:
     A Server with which RPCs can be serviced.
   """
   from grpc import _server
   return _server.Server(thread_pool, () if handlers is None else handlers,
-                        () if options is None else options, exit_grace,
-                        exit_shutdown_handler_grace)
+                        () if options is None else options)
 
 
 ###################################  __all__  #################################
@@ -1342,3 +1319,24 @@
     'secure_channel',
     'server',
 )
+
+
+############################### Extension Shims ################################
+
+
+# Here to maintain backwards compatibility; avoid using these in new code!
+try:
+  import grpc_tools
+  sys.modules.update({'grpc.tools': grpc_tools})
+except ImportError:
+  pass
+try:
+  import grpc_health
+  sys.modules.update({'grpc.health': grpc_health})
+except ImportError:
+  pass
+try:
+  import grpc_reflection
+  sys.modules.update({'grpc.reflection': grpc_reflection})
+except ImportError:
+  pass
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index d83a2e6..5223712 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -60,8 +60,7 @@
 _EMPTY_FLAGS = 0
 _EMPTY_METADATA = cygrpc.Metadata(())
 
-_DEFAULT_EXIT_GRACE = 1.0
-_DEFAULT_EXIT_SHUTDOWN_HANDLER_GRACE = 5.0
+_UNEXPECTED_EXIT_SERVER_GRACE = 1.0
 
 
 def _serialized_request(request_event):
@@ -596,18 +595,14 @@
 
 class _ServerState(object):
 
-  def __init__(self, completion_queue, server, generic_handlers, thread_pool,
-               exit_grace, exit_shutdown_handler_grace):
+  def __init__(self, completion_queue, server, generic_handlers, thread_pool):
     self.lock = threading.Lock()
     self.completion_queue = completion_queue
     self.server = server
     self.generic_handlers = list(generic_handlers)
     self.thread_pool = thread_pool
-    self.exit_grace = exit_grace
-    self.exit_shutdown_handler_grace = exit_shutdown_handler_grace
     self.stage = _ServerStage.STOPPED
     self.shutdown_events = None
-    self.shutdown_handlers = []
 
     # TODO(https://github.com/grpc/grpc/issues/6597): eliminate these fields.
     self.rpc_states = set()
@@ -677,45 +672,41 @@
             return
 
 
-def _stop(state, grace, shutdown_handler_grace):
-  shutdown_event = threading.Event()
-
-  def cancel_all_calls_after_grace():
-    with state.lock:
-      if state.stage is _ServerStage.STOPPED:
-        shutdown_event.set()
-        return
-      elif state.stage is _ServerStage.STARTED:
-        do_shutdown = True
-        state.stage = _ServerStage.GRACE
-        state.shutdown_events = []
-      else:
-        do_shutdown = False
-      state.shutdown_events.append(shutdown_event)
-
-    if do_shutdown:
-      # Run Shutdown Handlers without the lock
-      for handler in state.shutdown_handlers:
-        handler(shutdown_handler_grace)
-      with state.lock:
+def _stop(state, grace):
+  with state.lock:
+    if state.stage is _ServerStage.STOPPED:
+      shutdown_event = threading.Event()
+      shutdown_event.set()
+      return shutdown_event
+    else:
+      if state.stage is _ServerStage.STARTED:
         state.server.shutdown(state.completion_queue, _SHUTDOWN_TAG)
         state.stage = _ServerStage.GRACE
+        state.shutdown_events = []
         state.due.add(_SHUTDOWN_TAG)
-
-    if not shutdown_event.wait(timeout=grace):
-      with state.lock:
+      shutdown_event = threading.Event()
+      state.shutdown_events.append(shutdown_event)
+      if grace is None:
         state.server.cancel_all_calls()
         # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop.
         for rpc_state in state.rpc_states:
           with rpc_state.condition:
             rpc_state.client = _CANCELLED
             rpc_state.condition.notify_all()
-
-  if grace is None:
-    cancel_all_calls_after_grace()
-  else:
-    threading.Thread(target=cancel_all_calls_after_grace).start()
-
+      else:
+        def cancel_all_calls_after_grace():
+          shutdown_event.wait(timeout=grace)
+          with state.lock:
+            state.server.cancel_all_calls()
+            # TODO(https://github.com/grpc/grpc/issues/6597): delete this loop.
+            for rpc_state in state.rpc_states:
+              with rpc_state.condition:
+                rpc_state.client = _CANCELLED
+                rpc_state.condition.notify_all()
+        thread = threading.Thread(target=cancel_all_calls_after_grace)
+        thread.start()
+        return shutdown_event
+  shutdown_event.wait()
   return shutdown_event
 
 
@@ -725,12 +716,12 @@
       raise ValueError('Cannot start already-started server!')
     state.server.start()
     state.stage = _ServerStage.STARTED
-    _request_call(state)
+    _request_call(state)    
     def cleanup_server(timeout):
       if timeout is None:
-        _stop(state, state.exit_grace, state.exit_shutdown_handler_grace).wait()
+        _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait()
       else:
-        _stop(state, timeout, 0).wait()
+        _stop(state, timeout).wait()
 
     thread = _common.CleanupThread(
         cleanup_server, target=_serve, args=(state,))
@@ -738,16 +729,12 @@
 
 class Server(grpc.Server):
 
-  def __init__(self, thread_pool, generic_handlers, options, exit_grace,
-               exit_shutdown_handler_grace):
+  def __init__(self, thread_pool, generic_handlers, options):
     completion_queue = cygrpc.CompletionQueue()
     server = cygrpc.Server(_common.channel_args(options))
     server.register_completion_queue(completion_queue)
     self._state = _ServerState(
-        completion_queue, server, generic_handlers, thread_pool,
-        _DEFAULT_EXIT_GRACE if exit_grace is None else exit_grace,
-        _DEFAULT_EXIT_SHUTDOWN_HANDLER_GRACE if exit_shutdown_handler_grace
-        is None else exit_shutdown_handler_grace)
+        completion_queue, server, generic_handlers, thread_pool)
 
   def add_generic_rpc_handlers(self, generic_rpc_handlers):
     _add_generic_handlers(self._state, generic_rpc_handlers)
@@ -758,14 +745,11 @@
   def add_secure_port(self, address, server_credentials):
     return _add_secure_port(self._state, _common.encode(address), server_credentials)
 
-  def add_shutdown_handler(self, handler):
-    self._state.shutdown_handlers.append(handler)
-
   def start(self):
     _start(self._state)
 
-  def stop(self, grace, shutdown_handler_grace=None):
-    return _stop(self._state, grace, shutdown_handler_grace)
+  def stop(self, grace):
+    return _stop(self._state, grace)
 
   def __del__(self):
-    _stop(self._state, None, None)
+    _stop(self._state, None)
diff --git a/src/python/grpcio_health_checking/grpc/__init__.py b/src/python/grpcio_health_checking/grpc/__init__.py
deleted file mode 100644
index fcc7048..0000000
--- a/src/python/grpcio_health_checking/grpc/__init__.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2015, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-__import__('pkg_resources').declare_namespace(__name__)
diff --git a/src/python/grpcio_health_checking/grpc/health/__init__.py b/src/python/grpcio_health_checking/grpc_health/__init__.py
similarity index 100%
rename from src/python/grpcio_health_checking/grpc/health/__init__.py
rename to src/python/grpcio_health_checking/grpc_health/__init__.py
diff --git a/src/python/grpcio_health_checking/grpc/health/v1/__init__.py b/src/python/grpcio_health_checking/grpc_health/v1/__init__.py
similarity index 100%
rename from src/python/grpcio_health_checking/grpc/health/v1/__init__.py
rename to src/python/grpcio_health_checking/grpc_health/v1/__init__.py
diff --git a/src/python/grpcio_health_checking/grpc/health/v1/health.py b/src/python/grpcio_health_checking/grpc_health/v1/health.py
similarity index 98%
rename from src/python/grpcio_health_checking/grpc/health/v1/health.py
rename to src/python/grpcio_health_checking/grpc_health/v1/health.py
index 8108ac1..0df679b 100644
--- a/src/python/grpcio_health_checking/grpc/health/v1/health.py
+++ b/src/python/grpcio_health_checking/grpc_health/v1/health.py
@@ -33,7 +33,7 @@
 
 import grpc
 
-from grpc.health.v1 import health_pb2
+from grpc_health.v1 import health_pb2
 
 
 class HealthServicer(health_pb2.HealthServicer):
diff --git a/src/python/grpcio_health_checking/health_commands.py b/src/python/grpcio_health_checking/health_commands.py
index 66df25d..0c420a6 100644
--- a/src/python/grpcio_health_checking/health_commands.py
+++ b/src/python/grpcio_health_checking/health_commands.py
@@ -54,7 +54,7 @@
     if os.path.isfile(HEALTH_PROTO):
       shutil.copyfile(
           HEALTH_PROTO,
-          os.path.join(ROOT_DIR, 'grpc/health/v1/health.proto'))
+          os.path.join(ROOT_DIR, 'grpc_health/v1/health.proto'))
 
 
 class BuildPackageProtos(setuptools.Command):
@@ -74,5 +74,5 @@
     # directory is provided as an 'include' directory. We assume it's the '' key
     # to `self.distribution.package_dir` (and get a key error if it's not
     # there).
-    from grpc.tools import command
+    from grpc_tools import command
     command.build_package_protos(self.distribution.package_dir[''])
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 8c92ee1..e88f389 100644
--- a/src/python/grpcio_health_checking/setup.py
+++ b/src/python/grpcio_health_checking/setup.py
@@ -66,7 +66,6 @@
     license='3-clause BSD',
     package_dir=PACKAGE_DIRECTORIES,
     packages=setuptools.find_packages('.'),
-    namespace_packages=['grpc'],
     install_requires=INSTALL_REQUIRES,
     setup_requires=SETUP_REQUIRES,
     cmdclass=COMMAND_CLASS
diff --git a/src/python/grpcio_reflection/grpc/__init__.py b/src/python/grpcio_reflection/grpc/__init__.py
deleted file mode 100644
index 70ac5ed..0000000
--- a/src/python/grpcio_reflection/grpc/__init__.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2016, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-__import__('pkg_resources').declare_namespace(__name__)
diff --git a/src/python/grpcio_reflection/grpc/reflection/__init__.py b/src/python/grpcio_reflection/grpc_reflection/__init__.py
similarity index 100%
rename from src/python/grpcio_reflection/grpc/reflection/__init__.py
rename to src/python/grpcio_reflection/grpc_reflection/__init__.py
diff --git a/src/python/grpcio_reflection/grpc/reflection/v1alpha/__init__.py b/src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py
similarity index 100%
rename from src/python/grpcio_reflection/grpc/reflection/v1alpha/__init__.py
rename to src/python/grpcio_reflection/grpc_reflection/v1alpha/__init__.py
diff --git a/src/python/grpcio_reflection/grpc/reflection/v1alpha/reflection.py b/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py
similarity index 98%
rename from src/python/grpcio_reflection/grpc/reflection/v1alpha/reflection.py
rename to src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py
index 3c399b0..bfcbce8 100644
--- a/src/python/grpcio_reflection/grpc/reflection/v1alpha/reflection.py
+++ b/src/python/grpcio_reflection/grpc_reflection/v1alpha/reflection.py
@@ -35,7 +35,7 @@
 from google.protobuf import descriptor_pb2
 from google.protobuf import descriptor_pool
 
-from grpc.reflection.v1alpha import reflection_pb2
+from grpc_reflection.v1alpha import reflection_pb2
 
 _POOL = descriptor_pool.Default()
 
diff --git a/src/python/grpcio_reflection/reflection_commands.py b/src/python/grpcio_reflection/reflection_commands.py
index d189aee..dee5491 100644
--- a/src/python/grpcio_reflection/reflection_commands.py
+++ b/src/python/grpcio_reflection/reflection_commands.py
@@ -54,7 +54,7 @@
     if os.path.isfile(HEALTH_PROTO):
       shutil.copyfile(
           HEALTH_PROTO,
-          os.path.join(ROOT_DIR, 'grpc/reflection/v1alpha/reflection.proto'))
+          os.path.join(ROOT_DIR, 'grpc_reflection/v1alpha/reflection.proto'))
 
 
 class BuildPackageProtos(setuptools.Command):
@@ -74,5 +74,5 @@
     # directory is provided as an 'include' directory. We assume it's the '' key
     # to `self.distribution.package_dir` (and get a key error if it's not
     # there).
-    from grpc.tools import command
+    from grpc_tools import command
     command.build_package_protos(self.distribution.package_dir[''])
diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py
index df95af4..cfc41f4 100644
--- a/src/python/grpcio_reflection/setup.py
+++ b/src/python/grpcio_reflection/setup.py
@@ -66,7 +66,6 @@
     license='3-clause BSD',
     package_dir=PACKAGE_DIRECTORIES,
     packages=setuptools.find_packages('.'),
-    namespace_packages=['grpc'],
     install_requires=INSTALL_REQUIRES,
     setup_requires=SETUP_REQUIRES,
     cmdclass=COMMAND_CLASS
diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py
index 5ee551c..e822971 100644
--- a/src/python/grpcio_tests/commands.py
+++ b/src/python/grpcio_tests/commands.py
@@ -100,7 +100,7 @@
     pass
 
   def run(self):
-    import grpc.tools.protoc as protoc
+    import grpc_tools.protoc as protoc
 
     include_regex = re.compile(self.include)
     exclude_regex = re.compile(self.exclude) if self.exclude else None
@@ -116,7 +116,7 @@
     # but we currently have name conflicts in src/proto
     for path in paths:
       command = [
-          'grpc.tools.protoc',
+          'grpc_tools.protoc',
           '-I {}'.format(PROTO_STEM),
           '--python_out={}'.format(PROTO_STEM),
           '--grpc_python_out={}'.format(PROTO_STEM),
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 01d5fa8..375fbd6 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -35,7 +35,7 @@
 
 import setuptools
 
-import grpc.tools.command
+import grpc_tools.command
 
 PY3 = sys.version_info.major == 3
 
@@ -68,7 +68,7 @@
     # Run `preprocess` *before* doing any packaging!
     'preprocess': commands.GatherProto,
 
-    'build_package_protos': grpc.tools.command.BuildPackageProtos,
+    'build_package_protos': grpc_tools.command.BuildPackageProtos,
     'build_py': commands.BuildPy,
     'run_interop': commands.RunInterop,
     'test_lite': commands.TestLite
diff --git a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
index 80300d1..5dde72b 100644
--- a/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
+++ b/src/python/grpcio_tests/tests/health_check/_health_servicer_test.py
@@ -27,14 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-"""Tests of grpc.health.v1.health."""
+"""Tests of grpc_health.v1.health."""
 
 import unittest
 
 import grpc
 from grpc.framework.foundation import logging_pool
-from grpc.health.v1 import health
-from grpc.health.v1 import health_pb2
+from grpc_health.v1 import health
+from grpc_health.v1 import health_pb2
 
 from tests.unit.framework.common import test_constants
 
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
index 64fd972..f8ae05b 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
@@ -44,7 +44,7 @@
 import unittest
 
 import grpc
-from grpc.tools import protoc
+from grpc_tools import protoc
 from tests.unit.framework.common import test_constants
 
 _MESSAGES_IMPORT = b'import "messages.proto";'
diff --git a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
index 87264cf..c7bfeae 100644
--- a/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
+++ b/src/python/grpcio_tests/tests/reflection/_reflection_servicer_test.py
@@ -27,14 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-"""Tests of grpc.reflection.v1alpha.reflection."""
+"""Tests of grpc_reflection.v1alpha.reflection."""
 
 import unittest
 
 import grpc
 from grpc.framework.foundation import logging_pool
-from grpc.reflection.v1alpha import reflection
-from grpc.reflection.v1alpha import reflection_pb2
+from grpc_reflection.v1alpha import reflection
+from grpc_reflection.v1alpha import reflection_pb2
 
 from google.protobuf import descriptor_pool
 from google.protobuf import descriptor_pb2
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index 04a2e44..dd4a025 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -27,7 +27,6 @@
   "unit._cython.cygrpc_test.TypeSmokeTest",
   "unit._empty_message_test.EmptyMessageTest",
   "unit._exit_test.ExitTest",
-  "unit._exit_test.ShutdownHandlerTest",
   "unit._metadata_code_details_test.MetadataCodeDetailsTest",
   "unit._metadata_test.MetadataTest",
   "unit._rpc_test.RPCTest",
diff --git a/src/python/grpcio_tests/tests/unit/_exit_test.py b/src/python/grpcio_tests/tests/unit/_exit_test.py
index 342f5fc..5a4a328 100644
--- a/src/python/grpcio_tests/tests/unit/_exit_test.py
+++ b/src/python/grpcio_tests/tests/unit/_exit_test.py
@@ -43,8 +43,6 @@
 import time
 import unittest
 
-import grpc
-from grpc.framework.foundation import logging_pool
 from tests.unit import _exit_scenarios
 
 SCENARIO_FILE = os.path.abspath(os.path.join(
@@ -54,7 +52,7 @@
 BASE_SIGTERM_COMMAND = BASE_COMMAND + ['--wait_for_interrupt']
 
 INIT_TIME = 1.0
-SHUTDOWN_GRACE = 5.0
+
 
 processes = []
 process_lock = threading.Lock()
@@ -184,24 +182,5 @@
     interrupt_and_wait(process)
 
 
-class _ShutDownHandler(object):
-
-  def __init__(self):
-    self.seen_handler_grace = None
-
-  def shutdown_handler(self, handler_grace):
-    self.seen_handler_grace = handler_grace
-
-  
-class ShutdownHandlerTest(unittest.TestCase):
-
-  def test_shutdown_handler(self):
-    server = grpc.server(logging_pool.pool(1))
-    handler = _ShutDownHandler()
-    server.add_shutdown_handler(handler.shutdown_handler)
-    server.start()
-    server.stop(0, shutdown_handler_grace=SHUTDOWN_GRACE).wait()
-    self.assertEqual(SHUTDOWN_GRACE, handler.seen_handler_grace)
-
 if __name__ == '__main__':
   unittest.main(verbosity=2)
diff --git a/tools/distrib/python/grpcio_tools/grpc/__init__.py b/tools/distrib/python/grpcio_tools/grpc/__init__.py
deleted file mode 100644
index 70ac5ed..0000000
--- a/tools/distrib/python/grpcio_tools/grpc/__init__.py
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2016, Google Inc.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-#     * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-#     * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-#     * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-__import__('pkg_resources').declare_namespace(__name__)
diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/__init__.py b/tools/distrib/python/grpcio_tools/grpc_tools/__init__.py
similarity index 100%
rename from tools/distrib/python/grpcio_tools/grpc/tools/__init__.py
rename to tools/distrib/python/grpcio_tools/grpc_tools/__init__.py
diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/_protoc_compiler.pyx b/tools/distrib/python/grpcio_tools/grpc_tools/_protoc_compiler.pyx
similarity index 97%
rename from tools/distrib/python/grpcio_tools/grpc/tools/_protoc_compiler.pyx
rename to tools/distrib/python/grpcio_tools/grpc_tools/_protoc_compiler.pyx
index a653012..81034fa 100644
--- a/tools/distrib/python/grpcio_tools/grpc/tools/_protoc_compiler.pyx
+++ b/tools/distrib/python/grpcio_tools/grpc_tools/_protoc_compiler.pyx
@@ -29,7 +29,7 @@
 
 from libc cimport stdlib
 
-cdef extern from "grpc/tools/main.h":
+cdef extern from "grpc_tools/main.h":
   int protoc_main(int argc, char *argv[])
 
 def run_main(list args not None):
diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/command.py b/tools/distrib/python/grpcio_tools/grpc_tools/command.py
similarity index 97%
rename from tools/distrib/python/grpcio_tools/grpc/tools/command.py
rename to tools/distrib/python/grpcio_tools/grpc_tools/command.py
index 424fd90..43ec8c2 100644
--- a/tools/distrib/python/grpcio_tools/grpc/tools/command.py
+++ b/tools/distrib/python/grpcio_tools/grpc_tools/command.py
@@ -33,7 +33,7 @@
 
 import setuptools
 
-from grpc.tools import protoc
+from grpc_tools import protoc
 
 
 def build_package_protos(package_root):
@@ -45,7 +45,7 @@
         proto_files.append(os.path.abspath(os.path.join(root, filename)))
 
   well_known_protos_include = pkg_resources.resource_filename(
-      'grpc.tools', '_proto')
+      'grpc_tools', '_proto')
 
   for proto_file in proto_files:
     command = [
diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/main.cc b/tools/distrib/python/grpcio_tools/grpc_tools/main.cc
similarity index 98%
rename from tools/distrib/python/grpcio_tools/grpc/tools/main.cc
rename to tools/distrib/python/grpcio_tools/grpc_tools/main.cc
index 8391839..0c2fa31 100644
--- a/tools/distrib/python/grpcio_tools/grpc/tools/main.cc
+++ b/tools/distrib/python/grpcio_tools/grpc_tools/main.cc
@@ -32,7 +32,7 @@
 
 #include "src/compiler/python_generator.h"
 
-#include "grpc/tools/main.h"
+#include "grpc_tools/main.h"
 
 int protoc_main(int argc, char* argv[]) {
   google::protobuf::compiler::CommandLineInterface cli;
diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/main.h b/tools/distrib/python/grpcio_tools/grpc_tools/main.h
similarity index 100%
rename from tools/distrib/python/grpcio_tools/grpc/tools/main.h
rename to tools/distrib/python/grpcio_tools/grpc_tools/main.h
diff --git a/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py b/tools/distrib/python/grpcio_tools/grpc_tools/protoc.py
similarity index 97%
rename from tools/distrib/python/grpcio_tools/grpc/tools/protoc.py
rename to tools/distrib/python/grpcio_tools/grpc_tools/protoc.py
index e1256a7..7d5892d 100644
--- a/tools/distrib/python/grpcio_tools/grpc/tools/protoc.py
+++ b/tools/distrib/python/grpcio_tools/grpc_tools/protoc.py
@@ -32,7 +32,7 @@
 import pkg_resources
 import sys
 
-from grpc.tools import _protoc_compiler
+from grpc_tools import _protoc_compiler
 
 def main(command_arguments):
   """Run the protocol buffer compiler with the given command-line arguments.
diff --git a/tools/distrib/python/grpcio_tools/setup.py b/tools/distrib/python/grpcio_tools/setup.py
index a07a586..581ecc4 100644
--- a/tools/distrib/python/grpcio_tools/setup.py
+++ b/tools/distrib/python/grpcio_tools/setup.py
@@ -108,7 +108,7 @@
 CC_INCLUDE = os.path.normpath(protoc_lib_deps.CC_INCLUDE)
 PROTO_INCLUDE = os.path.normpath(protoc_lib_deps.PROTO_INCLUDE)
 
-GRPC_PYTHON_TOOLS_PACKAGE = 'grpc.tools'
+GRPC_PYTHON_TOOLS_PACKAGE = 'grpc_tools'
 GRPC_PYTHON_PROTO_RESOURCES_NAME = '_proto'
 
 DEFINE_MACROS = ()
@@ -154,16 +154,16 @@
 
 def extension_modules():
   if BUILD_WITH_CYTHON:
-    plugin_sources = [os.path.join('grpc', 'tools', '_protoc_compiler.pyx')]
+    plugin_sources = [os.path.join('grpc_tools', '_protoc_compiler.pyx')]
   else:
-    plugin_sources = [os.path.join('grpc', 'tools', '_protoc_compiler.cpp')]
+    plugin_sources = [os.path.join('grpc_tools', '_protoc_compiler.cpp')]
   plugin_sources += [
-    os.path.join('grpc', 'tools', 'main.cc'),
+    os.path.join('grpc_tools', 'main.cc'),
     os.path.join('grpc_root', 'src', 'compiler', 'python_generator.cc')] + [
     os.path.join(CC_INCLUDE, cc_file)
     for cc_file in CC_FILES]
   plugin_ext = extension.Extension(
-      name='grpc.tools._protoc_compiler',
+      name='grpc_tools._protoc_compiler',
       sources=plugin_sources,
       include_dirs=[
           '.',
@@ -189,7 +189,6 @@
   license='3-clause BSD',
   ext_modules=extension_modules(),
   packages=setuptools.find_packages('.'),
-  namespace_packages=['grpc'],
   install_requires=[
     'protobuf>=3.0.0',
     'grpcio>={version}'.format(version=grpc_version.VERSION),