Merge pull request #21352 from yang-g/client_handoff

Support client side handshaker handoff fd
diff --git a/include/grpcpp/generic/generic_stub_impl.h b/include/grpcpp/generic/generic_stub_impl.h
index e670fca..72d2989 100644
--- a/include/grpcpp/generic/generic_stub_impl.h
+++ b/include/grpcpp/generic/generic_stub_impl.h
@@ -28,8 +28,6 @@
 #include <grpcpp/support/client_callback_impl.h>
 #include <grpcpp/support/status.h>
 
-#include <functional>
-
 namespace grpc {
 
 typedef ::grpc_impl::ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
@@ -92,15 +90,15 @@
     void UnaryCall(grpc_impl::ClientContext* context,
                    const grpc::string& method, const grpc::ByteBuffer* request,
                    grpc::ByteBuffer* response,
-                   grpc_impl::experimental::ClientUnaryReactor* reactor);
+                   grpc_impl::ClientUnaryReactor* reactor);
 
     /// Setup a call to a named method \a method using \a context and tied to
     /// \a reactor . Like any other bidi streaming RPC, it will not be activated
     /// until StartCall is invoked on its reactor.
     void PrepareBidiStreamingCall(
         grpc_impl::ClientContext* context, const grpc::string& method,
-        grpc_impl::experimental::ClientBidiReactor<grpc::ByteBuffer,
-                                                   grpc::ByteBuffer>* reactor);
+        grpc_impl::ClientBidiReactor<grpc::ByteBuffer, grpc::ByteBuffer>*
+            reactor);
 
    private:
     GenericStub* stub_;
diff --git a/include/grpcpp/impl/codegen/async_generic_service.h b/include/grpcpp/impl/codegen/async_generic_service.h
index 934f619..8515e00 100644
--- a/include/grpcpp/impl/codegen/async_generic_service.h
+++ b/include/grpcpp/impl/codegen/async_generic_service.h
@@ -93,10 +93,10 @@
 /// invoked on a CallbackGenericService. It is just a ServerBidi reactor with
 /// ByteBuffer arguments.
 using ServerGenericBidiReactor =
-    ::grpc_impl::experimental::ServerBidiReactor<ByteBuffer, ByteBuffer>;
+    ::grpc_impl::ServerBidiReactor<ByteBuffer, ByteBuffer>;
 
 class GenericCallbackServerContext final
-    : public ::grpc_impl::experimental::CallbackServerContext {
+    : public ::grpc_impl::CallbackServerContext {
  public:
   const grpc::string& method() const { return method_; }
   const grpc::string& host() const { return host_; }
@@ -108,7 +108,7 @@
   void Clear() {
     method_.clear();
     host_.clear();
-    ::grpc_impl::experimental::CallbackServerContext::Clear();
+    ::grpc_impl::CallbackServerContext::Clear();
   }
 
   grpc::string method_;
@@ -143,7 +143,7 @@
   Handler() {
     return new ::grpc_impl::internal::CallbackBidiHandler<ByteBuffer,
                                                           ByteBuffer>(
-        [this](::grpc_impl::experimental::CallbackServerContext* ctx) {
+        [this](::grpc_impl::CallbackServerContext* ctx) {
           return CreateReactor(static_cast<GenericCallbackServerContext*>(ctx));
         });
   }
diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h
index 9d18372..7893a6f 100644
--- a/include/grpcpp/impl/codegen/client_callback.h
+++ b/include/grpcpp/impl/codegen/client_callback.h
@@ -25,30 +25,25 @@
 namespace experimental {
 
 template <class Response>
-using ClientCallbackReader =
-    ::grpc_impl::experimental::ClientCallbackReader<Response>;
+using ClientCallbackReader = ::grpc_impl::ClientCallbackReader<Response>;
 
 template <class Request>
-using ClientCallbackWriter =
-    ::grpc_impl::experimental::ClientCallbackWriter<Request>;
+using ClientCallbackWriter = ::grpc_impl::ClientCallbackWriter<Request>;
 
 template <class Request, class Response>
 using ClientCallbackReaderWriter =
-    ::grpc_impl::experimental::ClientCallbackReaderWriter<Request, Response>;
+    ::grpc_impl::ClientCallbackReaderWriter<Request, Response>;
 
 template <class Response>
-using ClientReadReactor =
-    ::grpc_impl::experimental::ClientReadReactor<Response>;
+using ClientReadReactor = ::grpc_impl::ClientReadReactor<Response>;
 
 template <class Request>
-using ClientWriteReactor =
-    ::grpc_impl::experimental::ClientWriteReactor<Request>;
+using ClientWriteReactor = ::grpc_impl::ClientWriteReactor<Request>;
 
 template <class Request, class Response>
-using ClientBidiReactor =
-    ::grpc_impl::experimental::ClientBidiReactor<Request, Response>;
+using ClientBidiReactor = ::grpc_impl::ClientBidiReactor<Request, Response>;
 
-typedef ::grpc_impl::experimental::ClientUnaryReactor ClientUnaryReactor;
+typedef ::grpc_impl::ClientUnaryReactor ClientUnaryReactor;
 }  // namespace experimental
 }  // namespace grpc
 
diff --git a/include/grpcpp/impl/codegen/client_callback_impl.h b/include/grpcpp/impl/codegen/client_callback_impl.h
index 7d42132..1a2bae1 100644
--- a/include/grpcpp/impl/codegen/client_callback_impl.h
+++ b/include/grpcpp/impl/codegen/client_callback_impl.h
@@ -103,8 +103,6 @@
 };
 }  // namespace internal
 
-namespace experimental {
-
 // Forward declarations
 template <class Request, class Response>
 class ClientBidiReactor;
@@ -404,8 +402,6 @@
   reactor->BindCall(this);
 }
 
-}  // namespace experimental
-
 namespace internal {
 
 // Forward declare factory classes for friendship
@@ -418,7 +414,7 @@
 
 template <class Request, class Response>
 class ClientCallbackReaderWriterImpl
-    : public experimental::ClientCallbackReaderWriter<Request, Response> {
+    : public ClientCallbackReaderWriter<Request, Response> {
  public:
   // always allocated against a call arena, no memory free required
   static void operator delete(void* /*ptr*/, std::size_t size) {
@@ -562,9 +558,9 @@
  private:
   friend class ClientCallbackReaderWriterFactory<Request, Response>;
 
-  ClientCallbackReaderWriterImpl(
-      grpc::internal::Call call, ::grpc_impl::ClientContext* context,
-      experimental::ClientBidiReactor<Request, Response>* reactor)
+  ClientCallbackReaderWriterImpl(grpc::internal::Call call,
+                                 ::grpc_impl::ClientContext* context,
+                                 ClientBidiReactor<Request, Response>* reactor)
       : context_(context),
         call_(call),
         reactor_(reactor),
@@ -574,7 +570,7 @@
 
   ::grpc_impl::ClientContext* const context_;
   grpc::internal::Call call_;
-  experimental::ClientBidiReactor<Request, Response>* const reactor_;
+  ClientBidiReactor<Request, Response>* const reactor_;
 
   grpc::internal::CallOpSet<grpc::internal::CallOpSendInitialMetadata,
                             grpc::internal::CallOpRecvInitialMetadata>
@@ -612,11 +608,10 @@
 template <class Request, class Response>
 class ClientCallbackReaderWriterFactory {
  public:
-  static void Create(
-      ::grpc::ChannelInterface* channel,
-      const ::grpc::internal::RpcMethod& method,
-      ::grpc_impl::ClientContext* context,
-      experimental::ClientBidiReactor<Request, Response>* reactor) {
+  static void Create(::grpc::ChannelInterface* channel,
+                     const ::grpc::internal::RpcMethod& method,
+                     ::grpc_impl::ClientContext* context,
+                     ClientBidiReactor<Request, Response>* reactor) {
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
 
@@ -629,8 +624,7 @@
 };
 
 template <class Response>
-class ClientCallbackReaderImpl
-    : public experimental::ClientCallbackReader<Response> {
+class ClientCallbackReaderImpl : public ClientCallbackReader<Response> {
  public:
   // always allocated against a call arena, no memory free required
   static void operator delete(void* /*ptr*/, std::size_t size) {
@@ -716,7 +710,7 @@
   ClientCallbackReaderImpl(::grpc::internal::Call call,
                            ::grpc_impl::ClientContext* context,
                            Request* request,
-                           experimental::ClientReadReactor<Response>* reactor)
+                           ClientReadReactor<Response>* reactor)
       : context_(context), call_(call), reactor_(reactor) {
     this->BindReactor(reactor);
     // TODO(vjpai): don't assert
@@ -726,7 +720,7 @@
 
   ::grpc_impl::ClientContext* const context_;
   grpc::internal::Call call_;
-  experimental::ClientReadReactor<Response>* const reactor_;
+  ClientReadReactor<Response>* const reactor_;
 
   grpc::internal::CallOpSet<grpc::internal::CallOpSendInitialMetadata,
                             grpc::internal::CallOpSendMessage,
@@ -757,7 +751,7 @@
                      const ::grpc::internal::RpcMethod& method,
                      ::grpc_impl::ClientContext* context,
                      const Request* request,
-                     experimental::ClientReadReactor<Response>* reactor) {
+                     ClientReadReactor<Response>* reactor) {
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
 
@@ -769,8 +763,7 @@
 };
 
 template <class Request>
-class ClientCallbackWriterImpl
-    : public experimental::ClientCallbackWriter<Request> {
+class ClientCallbackWriterImpl : public ClientCallbackWriter<Request> {
  public:
   // always allocated against a call arena, no memory free required
   static void operator delete(void* /*ptr*/, std::size_t size) {
@@ -896,7 +889,7 @@
   ClientCallbackWriterImpl(::grpc::internal::Call call,
                            ::grpc_impl::ClientContext* context,
                            Response* response,
-                           experimental::ClientWriteReactor<Request>* reactor)
+                           ClientWriteReactor<Request>* reactor)
       : context_(context),
         call_(call),
         reactor_(reactor),
@@ -908,7 +901,7 @@
 
   ::grpc_impl::ClientContext* const context_;
   grpc::internal::Call call_;
-  experimental::ClientWriteReactor<Request>* const reactor_;
+  ClientWriteReactor<Request>* const reactor_;
 
   grpc::internal::CallOpSet<grpc::internal::CallOpSendInitialMetadata,
                             grpc::internal::CallOpRecvInitialMetadata>
@@ -947,7 +940,7 @@
   static void Create(::grpc::ChannelInterface* channel,
                      const ::grpc::internal::RpcMethod& method,
                      ::grpc_impl::ClientContext* context, Response* response,
-                     experimental::ClientWriteReactor<Request>* reactor) {
+                     ClientWriteReactor<Request>* reactor) {
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
 
@@ -958,7 +951,7 @@
   }
 };
 
-class ClientCallbackUnaryImpl final : public experimental::ClientCallbackUnary {
+class ClientCallbackUnaryImpl final : public ClientCallbackUnary {
  public:
   // always allocated against a call arena, no memory free required
   static void operator delete(void* /*ptr*/, std::size_t size) {
@@ -1015,8 +1008,7 @@
   template <class Request, class Response>
   ClientCallbackUnaryImpl(::grpc::internal::Call call,
                           ::grpc_impl::ClientContext* context, Request* request,
-                          Response* response,
-                          experimental::ClientUnaryReactor* reactor)
+                          Response* response, ClientUnaryReactor* reactor)
       : context_(context), call_(call), reactor_(reactor) {
     this->BindReactor(reactor);
     // TODO(vjpai): don't assert
@@ -1028,7 +1020,7 @@
 
   ::grpc_impl::ClientContext* const context_;
   grpc::internal::Call call_;
-  experimental::ClientUnaryReactor* const reactor_;
+  ClientUnaryReactor* const reactor_;
 
   grpc::internal::CallOpSet<grpc::internal::CallOpSendInitialMetadata,
                             grpc::internal::CallOpSendMessage,
@@ -1055,7 +1047,7 @@
                      const ::grpc::internal::RpcMethod& method,
                      ::grpc_impl::ClientContext* context,
                      const Request* request, Response* response,
-                     experimental::ClientUnaryReactor* reactor) {
+                     ClientUnaryReactor* reactor) {
     grpc::internal::Call call =
         channel->CreateCall(method, context, channel->CallbackCQ());
 
diff --git a/include/grpcpp/impl/codegen/client_context_impl.h b/include/grpcpp/impl/codegen/client_context_impl.h
index 48a02db..b8e9072 100644
--- a/include/grpcpp/impl/codegen/client_context_impl.h
+++ b/include/grpcpp/impl/codegen/client_context_impl.h
@@ -107,10 +107,8 @@
 template <class R>
 class ClientAsyncResponseReader;
 
-namespace experimental {
 class ServerContextBase;
 class CallbackServerContext;
-}  // namespace experimental
 
 /// Options for \a ClientContext::FromServerContext specifying which traits from
 /// the \a ServerContext to propagate (copy) from it into a new \a
@@ -202,7 +200,7 @@
       const grpc_impl::ServerContext& server_context,
       PropagationOptions options = PropagationOptions());
   static std::unique_ptr<ClientContext> FromCallbackServerContext(
-      const grpc_impl::experimental::CallbackServerContext& server_context,
+      const grpc_impl::CallbackServerContext& server_context,
       PropagationOptions options = PropagationOptions());
 
   /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with
@@ -484,7 +482,7 @@
   void SendCancelToInterceptors();
 
   static std::unique_ptr<ClientContext> FromInternalServerContext(
-      const grpc_impl::experimental::ServerContextBase& server_context,
+      const grpc_impl::ServerContextBase& server_context,
       PropagationOptions options);
 
   bool initial_metadata_received_;
diff --git a/include/grpcpp/impl/codegen/completion_queue_impl.h b/include/grpcpp/impl/codegen/completion_queue_impl.h
index 04b9300..4549aa3 100644
--- a/include/grpcpp/impl/codegen/completion_queue_impl.h
+++ b/include/grpcpp/impl/codegen/completion_queue_impl.h
@@ -56,9 +56,7 @@
 class ServerReader;
 template <class W>
 class ServerWriter;
-namespace experimental {
 class ServerContextBase;
-}  // namespace experimental
 namespace internal {
 template <class W, class R>
 class ServerReaderWriterBody;
@@ -277,7 +275,7 @@
   template <::grpc::StatusCode code>
   friend class ::grpc_impl::internal::ErrorMethodHandler;
   friend class ::grpc_impl::Server;
-  friend class ::grpc_impl::experimental::ServerContextBase;
+  friend class ::grpc_impl::ServerContextBase;
   friend class ::grpc::ServerInterface;
   template <class InputMessage, class OutputMessage>
   friend class ::grpc::internal::BlockingUnaryCallImpl;
diff --git a/include/grpcpp/impl/codegen/method_handler_impl.h b/include/grpcpp/impl/codegen/method_handler_impl.h
index c7545fd..6368b63 100644
--- a/include/grpcpp/impl/codegen/method_handler_impl.h
+++ b/include/grpcpp/impl/codegen/method_handler_impl.h
@@ -345,8 +345,7 @@
 class ErrorMethodHandler : public ::grpc::internal::MethodHandler {
  public:
   template <class T>
-  static void FillOps(::grpc_impl::experimental::ServerContextBase* context,
-                      T* ops) {
+  static void FillOps(::grpc_impl::ServerContextBase* context, T* ops) {
     ::grpc::Status status(code, "");
     if (!context->sent_initial_metadata_) {
       ops->SendInitialMetadata(&context->initial_metadata_,
diff --git a/include/grpcpp/impl/codegen/rpc_service_method.h b/include/grpcpp/impl/codegen/rpc_service_method.h
index 7c5b8bf..da0e5b6 100644
--- a/include/grpcpp/impl/codegen/rpc_service_method.h
+++ b/include/grpcpp/impl/codegen/rpc_service_method.h
@@ -32,9 +32,7 @@
 #include <grpcpp/impl/codegen/status.h>
 
 namespace grpc_impl {
-namespace experimental {
 class ServerContextBase;
-}
 }  // namespace grpc_impl
 
 namespace grpc {
@@ -54,8 +52,7 @@
     /// \param requester : used only by the callback API. It is a function
     ///        called by the RPC Controller to request another RPC (and also
     ///        to set up the state required to make that request possible)
-    HandlerParameter(Call* c,
-                     ::grpc_impl::experimental::ServerContextBase* context,
+    HandlerParameter(Call* c, ::grpc_impl::ServerContextBase* context,
                      void* req, Status req_status, void* handler_data,
                      std::function<void()> requester)
         : call(c),
@@ -66,7 +63,7 @@
           call_requester(std::move(requester)) {}
     ~HandlerParameter() {}
     Call* const call;
-    ::grpc_impl::experimental::ServerContextBase* const server_context;
+    ::grpc_impl::ServerContextBase* const server_context;
     void* const request;
     const Status status;
     void* const internal_data;
diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h
index d33a224..3ddd8f6 100644
--- a/include/grpcpp/impl/codegen/server_callback.h
+++ b/include/grpcpp/impl/codegen/server_callback.h
@@ -24,17 +24,15 @@
 namespace grpc {
 namespace experimental {
 template <class Request>
-using ServerReadReactor = ::grpc_impl::experimental::ServerReadReactor<Request>;
+using ServerReadReactor = ::grpc_impl::ServerReadReactor<Request>;
 
 template <class Response>
-using ServerWriteReactor =
-    ::grpc_impl::experimental::ServerWriteReactor<Response>;
+using ServerWriteReactor = ::grpc_impl::ServerWriteReactor<Response>;
 
 template <class Request, class Response>
-using ServerBidiReactor =
-    ::grpc_impl::experimental::ServerBidiReactor<Request, Response>;
+using ServerBidiReactor = ::grpc_impl::ServerBidiReactor<Request, Response>;
 
-using ServerUnaryReactor = ::grpc_impl::experimental::ServerUnaryReactor;
+using ServerUnaryReactor = ::grpc_impl::ServerUnaryReactor;
 
 }  // namespace experimental
 }  // namespace grpc
diff --git a/include/grpcpp/impl/codegen/server_callback_handlers.h b/include/grpcpp/impl/codegen/server_callback_handlers.h
index 32d19d7..7752864 100644
--- a/include/grpcpp/impl/codegen/server_callback_handlers.h
+++ b/include/grpcpp/impl/codegen/server_callback_handlers.h
@@ -31,9 +31,8 @@
 class CallbackUnaryHandler : public ::grpc::internal::MethodHandler {
  public:
   explicit CallbackUnaryHandler(
-      std::function<experimental::ServerUnaryReactor*(
-          ::grpc_impl::experimental::CallbackServerContext*, const RequestType*,
-          ResponseType*)>
+      std::function<ServerUnaryReactor*(::grpc_impl::CallbackServerContext*,
+                                        const RequestType*, ResponseType*)>
           get_reactor)
       : get_reactor_(std::move(get_reactor)) {}
 
@@ -53,18 +52,17 @@
     auto* call = new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
         param.call->call(), sizeof(ServerCallbackUnaryImpl)))
         ServerCallbackUnaryImpl(
-            static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+            static_cast<::grpc_impl::CallbackServerContext*>(
                 param.server_context),
             param.call, allocator_state, std::move(param.call_requester));
     param.server_context->BeginCompletionOp(
         param.call, [call](bool) { call->MaybeDone(); }, call);
 
-    experimental::ServerUnaryReactor* reactor = nullptr;
+    ServerUnaryReactor* reactor = nullptr;
     if (param.status.ok()) {
-      reactor = ::grpc::internal::CatchingReactorGetter<
-          experimental::ServerUnaryReactor>(
+      reactor = ::grpc::internal::CatchingReactorGetter<ServerUnaryReactor>(
           get_reactor_,
-          static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+          static_cast<::grpc_impl::CallbackServerContext*>(
               param.server_context),
           call->request(), call->response());
     }
@@ -110,14 +108,13 @@
   }
 
  private:
-  std::function<experimental::ServerUnaryReactor*(
-      ::grpc_impl::experimental::CallbackServerContext*, const RequestType*,
-      ResponseType*)>
+  std::function<ServerUnaryReactor*(::grpc_impl::CallbackServerContext*,
+                                    const RequestType*, ResponseType*)>
       get_reactor_;
   ::grpc::experimental::MessageAllocator<RequestType, ResponseType>*
       allocator_ = nullptr;
 
-  class ServerCallbackUnaryImpl : public experimental::ServerCallbackUnary {
+  class ServerCallbackUnaryImpl : public ServerCallbackUnary {
    public:
     void Finish(::grpc::Status s) override {
       finish_tag_.Set(
@@ -168,8 +165,7 @@
     friend class CallbackUnaryHandler<RequestType, ResponseType>;
 
     ServerCallbackUnaryImpl(
-        ::grpc_impl::experimental::CallbackServerContext* ctx,
-        ::grpc::internal::Call* call,
+        ::grpc_impl::CallbackServerContext* ctx, ::grpc::internal::Call* call,
         ::grpc::experimental::MessageHolder<RequestType, ResponseType>*
             allocator_state,
         std::function<void()> call_requester)
@@ -184,7 +180,7 @@
     /// operations), maybe calls OnCancel if possible/needed, and maybe marks
     /// the completion of the RPC. This should be the last component of the
     /// handler.
-    void SetupReactor(experimental::ServerUnaryReactor* reactor) {
+    void SetupReactor(ServerUnaryReactor* reactor) {
       reactor_.store(reactor, std::memory_order_relaxed);
       this->BindReactor(reactor);
       this->MaybeCallOnCancel(reactor);
@@ -219,7 +215,7 @@
         finish_ops_;
     ::grpc::internal::CallbackWithSuccessTag finish_tag_;
 
-    ::grpc_impl::experimental::CallbackServerContext* const ctx_;
+    ::grpc_impl::CallbackServerContext* const ctx_;
     ::grpc::internal::Call call_;
     ::grpc::experimental::MessageHolder<RequestType, ResponseType>* const
         allocator_state_;
@@ -234,7 +230,7 @@
     // change after that and it only gets used by actions caused, directly or
     // indirectly, by that setup. This comment also applies to the reactor_
     // variables of the other streaming objects in this file.
-    std::atomic<experimental::ServerUnaryReactor*> reactor_;
+    std::atomic<ServerUnaryReactor*> reactor_;
     // callbacks_outstanding_ follows a refcount pattern
     std::atomic<intptr_t> callbacks_outstanding_{
         3};  // reserve for start, Finish, and CompletionOp
@@ -245,8 +241,8 @@
 class CallbackClientStreamingHandler : public ::grpc::internal::MethodHandler {
  public:
   explicit CallbackClientStreamingHandler(
-      std::function<experimental::ServerReadReactor<RequestType>*(
-          ::grpc_impl::experimental::CallbackServerContext*, ResponseType*)>
+      std::function<ServerReadReactor<RequestType>*(
+          ::grpc_impl::CallbackServerContext*, ResponseType*)>
           get_reactor)
       : get_reactor_(std::move(get_reactor)) {}
   void RunHandler(const HandlerParameter& param) final {
@@ -256,18 +252,18 @@
     auto* reader = new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
         param.call->call(), sizeof(ServerCallbackReaderImpl)))
         ServerCallbackReaderImpl(
-            static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+            static_cast<::grpc_impl::CallbackServerContext*>(
                 param.server_context),
             param.call, std::move(param.call_requester));
     param.server_context->BeginCompletionOp(
         param.call, [reader](bool) { reader->MaybeDone(); }, reader);
 
-    experimental::ServerReadReactor<RequestType>* reactor = nullptr;
+    ServerReadReactor<RequestType>* reactor = nullptr;
     if (param.status.ok()) {
       reactor = ::grpc::internal::CatchingReactorGetter<
-          experimental::ServerReadReactor<RequestType>>(
+          ServerReadReactor<RequestType>>(
           get_reactor_,
-          static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+          static_cast<::grpc_impl::CallbackServerContext*>(
               param.server_context),
           reader->response());
     }
@@ -284,12 +280,11 @@
   }
 
  private:
-  std::function<experimental::ServerReadReactor<RequestType>*(
-      ::grpc_impl::experimental::CallbackServerContext*, ResponseType*)>
+  std::function<ServerReadReactor<RequestType>*(
+      ::grpc_impl::CallbackServerContext*, ResponseType*)>
       get_reactor_;
 
-  class ServerCallbackReaderImpl
-      : public experimental::ServerCallbackReader<RequestType> {
+  class ServerCallbackReaderImpl : public ServerCallbackReader<RequestType> {
    public:
     void Finish(::grpc::Status s) override {
       finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, &finish_ops_,
@@ -342,12 +337,12 @@
    private:
     friend class CallbackClientStreamingHandler<RequestType, ResponseType>;
 
-    ServerCallbackReaderImpl(
-        ::grpc_impl::experimental::CallbackServerContext* ctx,
-        ::grpc::internal::Call* call, std::function<void()> call_requester)
+    ServerCallbackReaderImpl(::grpc_impl::CallbackServerContext* ctx,
+                             ::grpc::internal::Call* call,
+                             std::function<void()> call_requester)
         : ctx_(ctx), call_(*call), call_requester_(std::move(call_requester)) {}
 
-    void SetupReactor(experimental::ServerReadReactor<RequestType>* reactor) {
+    void SetupReactor(ServerReadReactor<RequestType>* reactor) {
       reactor_.store(reactor, std::memory_order_relaxed);
       read_tag_.Set(call_.call(),
                     [this](bool ok) {
@@ -393,12 +388,12 @@
         read_ops_;
     ::grpc::internal::CallbackWithSuccessTag read_tag_;
 
-    ::grpc_impl::experimental::CallbackServerContext* const ctx_;
+    ::grpc_impl::CallbackServerContext* const ctx_;
     ::grpc::internal::Call call_;
     ResponseType resp_;
     std::function<void()> call_requester_;
     // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
-    std::atomic<experimental::ServerReadReactor<RequestType>*> reactor_;
+    std::atomic<ServerReadReactor<RequestType>*> reactor_;
     // callbacks_outstanding_ follows a refcount pattern
     std::atomic<intptr_t> callbacks_outstanding_{
         3};  // reserve for OnStarted, Finish, and CompletionOp
@@ -409,9 +404,8 @@
 class CallbackServerStreamingHandler : public ::grpc::internal::MethodHandler {
  public:
   explicit CallbackServerStreamingHandler(
-      std::function<experimental::ServerWriteReactor<ResponseType>*(
-          ::grpc_impl::experimental::CallbackServerContext*,
-          const RequestType*)>
+      std::function<ServerWriteReactor<ResponseType>*(
+          ::grpc_impl::CallbackServerContext*, const RequestType*)>
           get_reactor)
       : get_reactor_(std::move(get_reactor)) {}
   void RunHandler(const HandlerParameter& param) final {
@@ -421,19 +415,19 @@
     auto* writer = new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
         param.call->call(), sizeof(ServerCallbackWriterImpl)))
         ServerCallbackWriterImpl(
-            static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+            static_cast<::grpc_impl::CallbackServerContext*>(
                 param.server_context),
             param.call, static_cast<RequestType*>(param.request),
             std::move(param.call_requester));
     param.server_context->BeginCompletionOp(
         param.call, [writer](bool) { writer->MaybeDone(); }, writer);
 
-    experimental::ServerWriteReactor<ResponseType>* reactor = nullptr;
+    ServerWriteReactor<ResponseType>* reactor = nullptr;
     if (param.status.ok()) {
       reactor = ::grpc::internal::CatchingReactorGetter<
-          experimental::ServerWriteReactor<ResponseType>>(
+          ServerWriteReactor<ResponseType>>(
           get_reactor_,
-          static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+          static_cast<::grpc_impl::CallbackServerContext*>(
               param.server_context),
           writer->request());
     }
@@ -466,12 +460,11 @@
   }
 
  private:
-  std::function<experimental::ServerWriteReactor<ResponseType>*(
-      ::grpc_impl::experimental::CallbackServerContext*, const RequestType*)>
+  std::function<ServerWriteReactor<ResponseType>*(
+      ::grpc_impl::CallbackServerContext*, const RequestType*)>
       get_reactor_;
 
-  class ServerCallbackWriterImpl
-      : public experimental::ServerCallbackWriter<ResponseType> {
+  class ServerCallbackWriterImpl : public ServerCallbackWriter<ResponseType> {
    public:
     void Finish(::grpc::Status s) override {
       finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, &finish_ops_,
@@ -543,16 +536,16 @@
    private:
     friend class CallbackServerStreamingHandler<RequestType, ResponseType>;
 
-    ServerCallbackWriterImpl(
-        ::grpc_impl::experimental::CallbackServerContext* ctx,
-        ::grpc::internal::Call* call, const RequestType* req,
-        std::function<void()> call_requester)
+    ServerCallbackWriterImpl(::grpc_impl::CallbackServerContext* ctx,
+                             ::grpc::internal::Call* call,
+                             const RequestType* req,
+                             std::function<void()> call_requester)
         : ctx_(ctx),
           call_(*call),
           req_(req),
           call_requester_(std::move(call_requester)) {}
 
-    void SetupReactor(experimental::ServerWriteReactor<ResponseType>* reactor) {
+    void SetupReactor(ServerWriteReactor<ResponseType>* reactor) {
       reactor_.store(reactor, std::memory_order_relaxed);
       write_tag_.Set(
           call_.call(),
@@ -598,12 +591,12 @@
         write_ops_;
     ::grpc::internal::CallbackWithSuccessTag write_tag_;
 
-    ::grpc_impl::experimental::CallbackServerContext* const ctx_;
+    ::grpc_impl::CallbackServerContext* const ctx_;
     ::grpc::internal::Call call_;
     const RequestType* req_;
     std::function<void()> call_requester_;
     // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
-    std::atomic<experimental::ServerWriteReactor<ResponseType>*> reactor_;
+    std::atomic<ServerWriteReactor<ResponseType>*> reactor_;
     // callbacks_outstanding_ follows a refcount pattern
     std::atomic<intptr_t> callbacks_outstanding_{
         3};  // reserve for OnStarted, Finish, and CompletionOp
@@ -614,8 +607,8 @@
 class CallbackBidiHandler : public ::grpc::internal::MethodHandler {
  public:
   explicit CallbackBidiHandler(
-      std::function<experimental::ServerBidiReactor<RequestType, ResponseType>*(
-          ::grpc_impl::experimental::CallbackServerContext*)>
+      std::function<ServerBidiReactor<RequestType, ResponseType>*(
+          ::grpc_impl::CallbackServerContext*)>
           get_reactor)
       : get_reactor_(std::move(get_reactor)) {}
   void RunHandler(const HandlerParameter& param) final {
@@ -624,20 +617,18 @@
     auto* stream = new (::grpc::g_core_codegen_interface->grpc_call_arena_alloc(
         param.call->call(), sizeof(ServerCallbackReaderWriterImpl)))
         ServerCallbackReaderWriterImpl(
-            static_cast<::grpc_impl::experimental::CallbackServerContext*>(
+            static_cast<::grpc_impl::CallbackServerContext*>(
                 param.server_context),
             param.call, std::move(param.call_requester));
     param.server_context->BeginCompletionOp(
         param.call, [stream](bool) { stream->MaybeDone(); }, stream);
 
-    experimental::ServerBidiReactor<RequestType, ResponseType>* reactor =
-        nullptr;
+    ServerBidiReactor<RequestType, ResponseType>* reactor = nullptr;
     if (param.status.ok()) {
       reactor = ::grpc::internal::CatchingReactorGetter<
-          experimental::ServerBidiReactor<RequestType, ResponseType>>(
-          get_reactor_,
-          static_cast<::grpc_impl::experimental::CallbackServerContext*>(
-              param.server_context));
+          ServerBidiReactor<RequestType, ResponseType>>(
+          get_reactor_, static_cast<::grpc_impl::CallbackServerContext*>(
+                            param.server_context));
     }
 
     if (reactor == nullptr) {
@@ -653,13 +644,12 @@
   }
 
  private:
-  std::function<experimental::ServerBidiReactor<RequestType, ResponseType>*(
-      ::grpc_impl::experimental::CallbackServerContext*)>
+  std::function<ServerBidiReactor<RequestType, ResponseType>*(
+      ::grpc_impl::CallbackServerContext*)>
       get_reactor_;
 
   class ServerCallbackReaderWriterImpl
-      : public experimental::ServerCallbackReaderWriter<RequestType,
-                                                        ResponseType> {
+      : public ServerCallbackReaderWriter<RequestType, ResponseType> {
    public:
     void Finish(::grpc::Status s) override {
       finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); }, &finish_ops_,
@@ -736,13 +726,12 @@
    private:
     friend class CallbackBidiHandler<RequestType, ResponseType>;
 
-    ServerCallbackReaderWriterImpl(
-        ::grpc_impl::experimental::CallbackServerContext* ctx,
-        ::grpc::internal::Call* call, std::function<void()> call_requester)
+    ServerCallbackReaderWriterImpl(::grpc_impl::CallbackServerContext* ctx,
+                                   ::grpc::internal::Call* call,
+                                   std::function<void()> call_requester)
         : ctx_(ctx), call_(*call), call_requester_(std::move(call_requester)) {}
 
-    void SetupReactor(
-        experimental::ServerBidiReactor<RequestType, ResponseType>* reactor) {
+    void SetupReactor(ServerBidiReactor<RequestType, ResponseType>* reactor) {
       reactor_.store(reactor, std::memory_order_relaxed);
       write_tag_.Set(
           call_.call(),
@@ -796,12 +785,11 @@
         read_ops_;
     ::grpc::internal::CallbackWithSuccessTag read_tag_;
 
-    ::grpc_impl::experimental::CallbackServerContext* const ctx_;
+    ::grpc_impl::CallbackServerContext* const ctx_;
     ::grpc::internal::Call call_;
     std::function<void()> call_requester_;
     // The memory ordering of reactor_ follows ServerCallbackUnaryImpl.
-    std::atomic<experimental::ServerBidiReactor<RequestType, ResponseType>*>
-        reactor_;
+    std::atomic<ServerBidiReactor<RequestType, ResponseType>*> reactor_;
     // callbacks_outstanding_ follows a refcount pattern
     std::atomic<intptr_t> callbacks_outstanding_{
         3};  // reserve for OnStarted, Finish, and CompletionOp
diff --git a/include/grpcpp/impl/codegen/server_callback_impl.h b/include/grpcpp/impl/codegen/server_callback_impl.h
index 4e899f5..ccdcb6a 100644
--- a/include/grpcpp/impl/codegen/server_callback_impl.h
+++ b/include/grpcpp/impl/codegen/server_callback_impl.h
@@ -136,8 +136,6 @@
 
 }  // namespace internal
 
-namespace experimental {
-
 // Forward declarations
 class ServerUnaryReactor;
 template <class Request>
@@ -723,8 +721,6 @@
   ::grpc::Status status_wanted_ /* GUARDED_BY(writer_mu_) */;
 };
 
-}  // namespace experimental
-
 namespace internal {
 
 template <class Base>
@@ -734,17 +730,15 @@
   void OnDone() override { this->~FinishOnlyReactor(); }
 };
 
-using UnimplementedUnaryReactor =
-    FinishOnlyReactor<experimental::ServerUnaryReactor>;
+using UnimplementedUnaryReactor = FinishOnlyReactor<ServerUnaryReactor>;
 template <class Request>
-using UnimplementedReadReactor =
-    FinishOnlyReactor<experimental::ServerReadReactor<Request>>;
+using UnimplementedReadReactor = FinishOnlyReactor<ServerReadReactor<Request>>;
 template <class Response>
 using UnimplementedWriteReactor =
-    FinishOnlyReactor<experimental::ServerWriteReactor<Response>>;
+    FinishOnlyReactor<ServerWriteReactor<Response>>;
 template <class Request, class Response>
 using UnimplementedBidiReactor =
-    FinishOnlyReactor<experimental::ServerBidiReactor<Request, Response>>;
+    FinishOnlyReactor<ServerBidiReactor<Request, Response>>;
 
 }  // namespace internal
 }  // namespace grpc_impl
diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h
index 0976d8d..b04a4ce 100644
--- a/include/grpcpp/impl/codegen/server_context.h
+++ b/include/grpcpp/impl/codegen/server_context.h
@@ -27,8 +27,8 @@
 
 namespace experimental {
 
-typedef ::grpc_impl::experimental::ServerContextBase ServerContextBase;
-typedef ::grpc_impl::experimental::CallbackServerContext CallbackServerContext;
+typedef ::grpc_impl::ServerContextBase ServerContextBase;
+typedef ::grpc_impl::CallbackServerContext CallbackServerContext;
 
 }  // namespace experimental
 }  // namespace grpc
diff --git a/include/grpcpp/impl/codegen/server_context_impl.h b/include/grpcpp/impl/codegen/server_context_impl.h
index 47ac70e..25673c6 100644
--- a/include/grpcpp/impl/codegen/server_context_impl.h
+++ b/include/grpcpp/impl/codegen/server_context_impl.h
@@ -112,7 +112,6 @@
 }  // namespace grpc
 
 namespace grpc_impl {
-namespace experimental {
 
 /// Base class of ServerContext. Experimental until callback API is final.
 class ServerContextBase {
@@ -297,7 +296,7 @@
   /// from the method handler.
   ///
   /// WARNING: This is experimental API and could be changed or removed.
-  ::grpc_impl::experimental::ServerUnaryReactor* DefaultReactor() {
+  ::grpc_impl::ServerUnaryReactor* DefaultReactor() {
     auto reactor = &default_reactor_;
     default_reactor_used_.store(true, std::memory_order_relaxed);
     return reactor;
@@ -415,7 +414,7 @@
   ::grpc::experimental::ServerRpcInfo* rpc_info_;
   ::grpc::experimental::RpcAllocatorState* message_allocator_state_ = nullptr;
 
-  class Reactor : public experimental::ServerUnaryReactor {
+  class Reactor : public ServerUnaryReactor {
    public:
     void OnCancel() override {}
     void OnDone() override {}
@@ -434,8 +433,7 @@
   }
   ::grpc::Status test_status() const { return test_unary_->status(); }
 
-  class TestServerCallbackUnary
-      : public ::grpc_impl::experimental::ServerCallbackUnary {
+  class TestServerCallbackUnary : public ::grpc_impl::ServerCallbackUnary {
    public:
     TestServerCallbackUnary(ServerContextBase* ctx,
                             std::function<void(::grpc::Status)> func)
@@ -460,7 +458,7 @@
       return reactor_;
     }
 
-    ::grpc_impl::experimental::ServerUnaryReactor* const reactor_;
+    ::grpc_impl::ServerUnaryReactor* const reactor_;
     std::atomic_bool status_set_{false};
     ::grpc::Status status_;
     const std::function<void(::grpc::Status s)> func_;
@@ -471,8 +469,6 @@
   std::unique_ptr<TestServerCallbackUnary> test_unary_;
 };
 
-}  // namespace experimental
-
 /// A ServerContext or CallbackServerContext allows the code implementing a
 /// service handler to:
 ///
@@ -489,48 +485,46 @@
 /// to a \a grpc::ServerBuilder, via \a ServerBuilder::AddChannelArgument.
 ///
 /// \warning ServerContext instances should \em not be reused across rpcs.
-class ServerContext : public experimental::ServerContextBase {
+class ServerContext : public ServerContextBase {
  public:
   ServerContext() {}  // for async calls
 
-  using experimental::ServerContextBase::AddInitialMetadata;
-  using experimental::ServerContextBase::AddTrailingMetadata;
-  using experimental::ServerContextBase::IsCancelled;
-  using experimental::ServerContextBase::SetLoadReportingCosts;
-  using experimental::ServerContextBase::TryCancel;
-  using experimental::ServerContextBase::auth_context;
-  using experimental::ServerContextBase::c_call;
-  using experimental::ServerContextBase::census_context;
-  using experimental::ServerContextBase::client_metadata;
-  using experimental::ServerContextBase::compression_algorithm;
-  using experimental::ServerContextBase::compression_level;
-  using experimental::ServerContextBase::compression_level_set;
-  using experimental::ServerContextBase::deadline;
-  using experimental::ServerContextBase::peer;
-  using experimental::ServerContextBase::raw_deadline;
-  using experimental::ServerContextBase::set_compression_algorithm;
-  using experimental::ServerContextBase::set_compression_level;
+  using ServerContextBase::AddInitialMetadata;
+  using ServerContextBase::AddTrailingMetadata;
+  using ServerContextBase::IsCancelled;
+  using ServerContextBase::SetLoadReportingCosts;
+  using ServerContextBase::TryCancel;
+  using ServerContextBase::auth_context;
+  using ServerContextBase::c_call;
+  using ServerContextBase::census_context;
+  using ServerContextBase::client_metadata;
+  using ServerContextBase::compression_algorithm;
+  using ServerContextBase::compression_level;
+  using ServerContextBase::compression_level_set;
+  using ServerContextBase::deadline;
+  using ServerContextBase::peer;
+  using ServerContextBase::raw_deadline;
+  using ServerContextBase::set_compression_algorithm;
+  using ServerContextBase::set_compression_level;
 
   // Sync/CQ-based Async ServerContext only
-  using experimental::ServerContextBase::AsyncNotifyWhenDone;
+  using ServerContextBase::AsyncNotifyWhenDone;
 
  private:
   // Constructor for internal use by server only
   friend class ::grpc_impl::Server;
   ServerContext(gpr_timespec deadline, grpc_metadata_array* arr)
-      : experimental::ServerContextBase(deadline, arr) {}
+      : ServerContextBase(deadline, arr) {}
 
   // CallbackServerContext only
-  using experimental::ServerContextBase::DefaultReactor;
-  using experimental::ServerContextBase::GetRpcAllocatorState;
+  using ServerContextBase::DefaultReactor;
+  using ServerContextBase::GetRpcAllocatorState;
 
   /// Prevent copying.
   ServerContext(const ServerContext&) = delete;
   ServerContext& operator=(const ServerContext&) = delete;
 };
 
-namespace experimental {
-
 class CallbackServerContext : public ServerContextBase {
  public:
   /// Public constructors are for direct use only by mocking tests. In practice,
@@ -568,21 +562,19 @@
   CallbackServerContext& operator=(const CallbackServerContext&) = delete;
 };
 
-}  // namespace experimental
 }  // namespace grpc_impl
 
-static_assert(std::is_base_of<::grpc_impl::experimental::ServerContextBase,
+static_assert(std::is_base_of<::grpc_impl::ServerContextBase,
                               ::grpc_impl::ServerContext>::value,
               "improper base class");
-static_assert(
-    std::is_base_of<::grpc_impl::experimental::ServerContextBase,
-                    ::grpc_impl::experimental::CallbackServerContext>::value,
-    "improper base class");
-static_assert(sizeof(::grpc_impl::experimental::ServerContextBase) ==
+static_assert(std::is_base_of<::grpc_impl::ServerContextBase,
+                              ::grpc_impl::CallbackServerContext>::value,
+              "improper base class");
+static_assert(sizeof(::grpc_impl::ServerContextBase) ==
                   sizeof(::grpc_impl::ServerContext),
               "wrong size");
-static_assert(sizeof(::grpc_impl::experimental::ServerContextBase) ==
-                  sizeof(::grpc_impl::experimental::CallbackServerContext),
+static_assert(sizeof(::grpc_impl::ServerContextBase) ==
+                  sizeof(::grpc_impl::CallbackServerContext),
               "wrong size");
 
 #endif  // GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_IMPL_H
diff --git a/include/grpcpp/impl/codegen/server_interceptor.h b/include/grpcpp/impl/codegen/server_interceptor.h
index 66c4417..cee6869 100644
--- a/include/grpcpp/impl/codegen/server_interceptor.h
+++ b/include/grpcpp/impl/codegen/server_interceptor.h
@@ -27,9 +27,7 @@
 #include <grpcpp/impl/codegen/string_ref.h>
 
 namespace grpc_impl {
-namespace experimental {
 class ServerContextBase;
-}
 }  // namespace grpc_impl
 
 namespace grpc {
@@ -82,7 +80,7 @@
 
   /// Return a pointer to the underlying ServerContext structure associated
   /// with the RPC to support features that apply to it
-  grpc_impl::experimental::ServerContextBase* server_context() { return ctx_; }
+  grpc_impl::ServerContextBase* server_context() { return ctx_; }
 
  private:
   static_assert(Type::UNARY ==
@@ -98,8 +96,8 @@
                     static_cast<Type>(internal::RpcMethod::BIDI_STREAMING),
                 "violated expectation about Type enum");
 
-  ServerRpcInfo(grpc_impl::experimental::ServerContextBase* ctx,
-                const char* method, internal::RpcMethod::RpcType type)
+  ServerRpcInfo(grpc_impl::ServerContextBase* ctx, const char* method,
+                internal::RpcMethod::RpcType type)
       : ctx_(ctx), method_(method), type_(static_cast<Type>(type)) {}
 
   // Runs interceptor at pos \a pos.
@@ -129,14 +127,14 @@
     }
   }
 
-  grpc_impl::experimental::ServerContextBase* ctx_ = nullptr;
+  grpc_impl::ServerContextBase* ctx_ = nullptr;
   const char* method_ = nullptr;
   const Type type_;
   std::atomic<intptr_t> ref_{1};
   std::vector<std::unique_ptr<experimental::Interceptor>> interceptors_;
 
   friend class internal::InterceptorBatchMethodsImpl;
-  friend class grpc_impl::experimental::ServerContextBase;
+  friend class grpc_impl::ServerContextBase;
 };
 
 }  // namespace experimental
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index 563c3e8..6865758 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -89,8 +89,7 @@
 }
 
 std::unique_ptr<ClientContext> ClientContext::FromInternalServerContext(
-    const grpc_impl::experimental::ServerContextBase& context,
-    PropagationOptions options) {
+    const grpc_impl::ServerContextBase& context, PropagationOptions options) {
   std::unique_ptr<ClientContext> ctx(new ClientContext);
   ctx->propagate_from_call_ = context.call_;
   ctx->propagation_options_ = options;
@@ -104,7 +103,7 @@
 }
 
 std::unique_ptr<ClientContext> ClientContext::FromCallbackServerContext(
-    const grpc_impl::experimental::CallbackServerContext& server_context,
+    const grpc_impl::CallbackServerContext& server_context,
     PropagationOptions options) {
   return FromInternalServerContext(server_context, options);
 }
diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc
index e7d3df7..7175b34 100644
--- a/src/cpp/client/generic_stub.cc
+++ b/src/cpp/client/generic_stub.cc
@@ -80,8 +80,7 @@
 
 void GenericStub::experimental_type::PrepareBidiStreamingCall(
     grpc::ClientContext* context, const grpc::string& method,
-    experimental::ClientBidiReactor<grpc::ByteBuffer, grpc::ByteBuffer>*
-        reactor) {
+    ClientBidiReactor<grpc::ByteBuffer, grpc::ByteBuffer>* reactor) {
   internal::ClientCallbackReaderWriterFactory<
       grpc::ByteBuffer,
       grpc::ByteBuffer>::Create(stub_->channel_.get(),
diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc
index 983a51b..590a3d5 100644
--- a/src/cpp/server/server_context.cc
+++ b/src/cpp/server/server_context.cc
@@ -36,7 +36,6 @@
 #include "src/core/lib/surface/call.h"
 
 namespace grpc_impl {
-namespace experimental {
 
 // CompletionOp
 
@@ -379,5 +378,4 @@
   }
 }
 
-}  // namespace experimental
 }  // namespace grpc_impl
diff --git a/src/php/ext/grpc/byte_buffer.c b/src/php/ext/grpc/byte_buffer.c
index 9c9a6fc..2c090f2 100644
--- a/src/php/ext/grpc/byte_buffer.c
+++ b/src/php/ext/grpc/byte_buffer.c
@@ -31,6 +31,8 @@
   return buffer;
 }
 
+#if PHP_MAJOR_VERSION < 7
+
 void byte_buffer_to_string(grpc_byte_buffer *buffer, char **out_string,
                            size_t *out_length) {
   grpc_byte_buffer_reader reader;
@@ -50,3 +52,31 @@
   *out_string = string;
   *out_length = length;
 }
+
+#else
+
+zend_string* byte_buffer_to_zend_string(grpc_byte_buffer *buffer) {
+  grpc_byte_buffer_reader reader;
+  if (buffer == NULL || !grpc_byte_buffer_reader_init(&reader, buffer)) {
+    /* TODO(dgq): distinguish between the error cases. */
+    return NULL;
+  }
+
+  const size_t length = grpc_byte_buffer_length(reader.buffer_out);
+  zend_string* zstr = zend_string_alloc(length, 0);
+
+  char* buf = ZSTR_VAL(zstr);
+  grpc_slice next;
+  while (grpc_byte_buffer_reader_next(&reader, &next) != 0) {
+    const size_t next_len = GRPC_SLICE_LENGTH(next);
+    memcpy(buf, GRPC_SLICE_START_PTR(next), next_len);
+    buf += next_len;
+    grpc_slice_unref(next);
+  }
+
+  *buf = '\0';
+  
+  return zstr;
+}
+
+#endif // PHP_MAJOR_VERSION < 7
diff --git a/src/php/ext/grpc/byte_buffer.h b/src/php/ext/grpc/byte_buffer.h
index ca0435e..e58d131 100644
--- a/src/php/ext/grpc/byte_buffer.h
+++ b/src/php/ext/grpc/byte_buffer.h
@@ -23,7 +23,11 @@
 
 grpc_byte_buffer *string_to_byte_buffer(char *string, size_t length);
 
+#if PHP_MAJOR_VERSION < 7
 void byte_buffer_to_string(grpc_byte_buffer *buffer, char **out_string,
                            size_t *out_length);
+#else
+zend_string* byte_buffer_to_zend_string(grpc_byte_buffer *buffer);
+#endif // PHP_MAJOR_VERSION < 7
 
 #endif /* NET_GRPC_PHP_GRPC_BYTE_BUFFER_H_ */
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 46d1e22..66b2671 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -294,8 +294,13 @@
   grpc_byte_buffer *message;
   int cancelled;
   grpc_call_error error;
+
+  #if PHP_MAJOR_VERSION < 7
   char *message_str;
   size_t message_len;
+  #else
+  zend_string* zmessage = NULL;
+  #endif // PHP_MAJOR_VERSION < 7
 
   grpc_metadata_array_init(&metadata);
   grpc_metadata_array_init(&trailing_metadata);
@@ -483,12 +488,28 @@
       PHP_GRPC_DELREF(array);
       break;
     case GRPC_OP_RECV_MESSAGE:
+#if PHP_MAJOR_VERSION < 7
       byte_buffer_to_string(message, &message_str, &message_len);
+#else
+      zmessage = byte_buffer_to_zend_string(message);
+#endif // PHP_MAJOR_VERSION < 7
+
+#if PHP_MAJOR_VERSION < 7
       if (message_str == NULL) {
+#else
+      if (zmessage == NULL) {
+#endif // PHP_MAJOR_VERSION < 7
         add_property_null(result, "message");
       } else {
+#if PHP_MAJOR_VERSION < 7
         php_grpc_add_property_stringl(result, "message", message_str,
                                       message_len, false);
+#else
+        zval zmessage_val;
+        ZVAL_NEW_STR(&zmessage_val, zmessage);
+        add_property_zval(result, "message", &zmessage_val);
+        zval_ptr_dtor(&zmessage_val);
+#endif // PHP_MAJOR_VERSION < 7
       }
       break;
     case GRPC_OP_RECV_STATUS_ON_CLIENT:
@@ -537,7 +558,9 @@
     }
     if (ops[i].op == GRPC_OP_RECV_MESSAGE) {
       grpc_byte_buffer_destroy(message);
+      #if PHP_MAJOR_VERSION < 7
       PHP_GRPC_FREE_STD_ZVAL(message_str);
+      #endif // PHP_MAJOR_VERSION < 7
     }
   }
   RETURN_DESTROY_ZVAL(result);
diff --git a/tools/internal_ci/helper_scripts/install_python38.ps1 b/tools/internal_ci/helper_scripts/install_python38.ps1
new file mode 100644
index 0000000..a343bea
--- /dev/null
+++ b/tools/internal_ci/helper_scripts/install_python38.ps1
@@ -0,0 +1,94 @@
+#!/usr/bin/env powershell
+# Install Python 3.8 for x64 and x86 in order to build wheels on Windows.
+
+Set-StrictMode -Version 2
+
+# Avoid "Could not create SSL/TLS secure channel"
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+
+function Install-Python {
+    Param(
+        [string]$PythonVersion,
+        [string]$PythonInstaller,
+        [string]$PythonInstallPath,
+        [string]$PythonInstallerHash
+    )
+    $PythonInstallerUrl = "https://www.python.org/ftp/python/$PythonVersion/$PythonInstaller.exe"
+    $PythonInstallerPath = "C:\tools\$PythonInstaller.exe"
+
+    # Downloads installer
+    Write-Host "Downloading the Python installer: $PythonInstallerUrl => $PythonInstallerPath"
+    Invoke-WebRequest -Uri $PythonInstallerUrl -OutFile $PythonInstallerPath
+
+    # Validates checksum
+    $HashFromDownload = Get-FileHash -Path $PythonInstallerPath -Algorithm MD5
+    if ($HashFromDownload.Hash -ne $PythonInstallerHash) {
+        throw "Invalid Python installer: failed checksum!"
+    }
+    Write-Host "Python installer $PythonInstallerPath validated."
+
+    # Installs Python
+    & $PythonInstallerPath /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 TargetDir=$PythonInstallPath
+    if (-Not $?) {
+        throw "The Python installation exited with error!"
+    }
+
+    # Validates Python binary
+    # NOTE(lidiz) Even if the install command finishes in the script, that
+    # doesn't mean the Python installation is finished. If using "ps" to check
+    # for running processes, you might see ongoing installers at this point.
+    # So, we needs this "hack" to reliably validate that the Python binary is
+    # functioning properly.
+    $ValidationStartTime = Get-Date
+    $EarlyExitDDL = $ValidationStartTime.addminutes(5)
+    $PythonBinary = "$PythonInstallPath\python.exe"
+    While ($True) {
+        $CurrentTime = Get-Date
+        if ($CurrentTime -ge $EarlyExitDDL) {
+            throw "Invalid Python installation! Timeout!"
+        }
+        & $PythonBinary -c 'print(42)'
+        if ($?) {
+            Write-Host "Python binary works properly."
+            break
+        }
+        Start-Sleep -Seconds 1
+    }
+
+    # Waits until the installer process is gone
+    $ValidationStartTime = Get-Date
+    $EarlyExitDDL = $ValidationStartTime.addminutes(5)
+    While ($True) {
+        $CurrentTime = Get-Date
+        if ($CurrentTime -ge $EarlyExitDDL) {
+            throw "Python installation process hangs!"
+        }
+        $InstallProcess = Get-Process -Name $PythonInstaller
+        if ($InstallProcess -eq $null) {
+            Write-Host "Installation process exits normally."
+            break
+        }
+        Start-Sleep -Seconds 1
+    }
+
+    # Installs pip
+    & $PythonBinary -m ensurepip --user
+
+    Write-Host "Python $PythonVersion installed by $PythonInstaller at $PythonInstallPath."
+}
+
+$Python38x86Config = @{
+    PythonVersion = "3.8.0"
+    PythonInstaller = "python-3.8.0"
+    PythonInstallPath = "C:\Python38_32bit"
+    PythonInstallerHash = "412a649d36626d33b8ca5593cf18318c"
+}
+Install-Python @Python38x86Config
+
+$Python38x64Config = @{
+    PythonVersion = "3.8.0"
+    PythonInstaller = "python-3.8.0-amd64"
+    PythonInstallPath = "C:\Python38"
+    PythonInstallerHash = "29ea87f24c32f5e924b7d63f8a08ee8d"
+}
+Install-Python @Python38x64Config
diff --git a/tools/internal_ci/helper_scripts/prepare_build_windows.bat b/tools/internal_ci/helper_scripts/prepare_build_windows.bat
index d129332..c937884 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_windows.bat
+++ b/tools/internal_ci/helper_scripts/prepare_build_windows.bat
@@ -39,6 +39,11 @@
 @rem TODO(jtattermusch): try to eliminate the dependency on Go
 choco install golang -y --version 1.13.1 --limit-output
 
+@rem Install Python 3.8.0
+@rem NOTE(lidiz): Python installer process may live longer than expected, and
+@rem has other side effects. It needs to be installed last to reduce impact.
+powershell -File tools\internal_ci\helper_scripts\install_python38.ps1
+
 @rem Disable some unwanted dotnet options
 set NUGET_XMLDOC_MODE=skip
 set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
diff --git a/tools/internal_ci/windows/grpc_build_artifacts.bat b/tools/internal_ci/windows/grpc_build_artifacts.bat
index 190e848..be47fe6 100644
--- a/tools/internal_ci/windows/grpc_build_artifacts.bat
+++ b/tools/internal_ci/windows/grpc_build_artifacts.bat
@@ -12,13 +12,6 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-@rem Move python installation from _32bit to _32bits where they are expected by python artifact builder
-@rem TODO(jtattermusch): get rid of this hack
-rename C:\Python27_32bit Python27_32bits
-rename C:\Python35_32bit Python35_32bits
-rename C:\Python36_32bit Python36_32bits
-rename C:\Python37_32bit Python37_32bits
-
 @rem Boringssl build no longer supports yasm
 choco uninstall yasm -y --limit-output
 choco install nasm -y --limit-output
diff --git a/tools/internal_ci/windows/grpc_build_packages.bat b/tools/internal_ci/windows/grpc_build_packages.bat
index 3cf90af..19a805a 100644
--- a/tools/internal_ci/windows/grpc_build_packages.bat
+++ b/tools/internal_ci/windows/grpc_build_packages.bat
@@ -12,12 +12,6 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-@rem Move python installation from _32bit to _32bits where they are expected by python artifact builder
-@rem TODO(jtattermusch): get rid of this hack
-rename C:\Python27_32bit Python27_32bits
-rename C:\Python35_32bit Python35_32bits
-rename C:\Python36_32bit Python36_32bits
-
 @rem enter repo root
 cd /d %~dp0\..\..\..
 
diff --git a/tools/internal_ci/windows/grpc_distribtests.bat b/tools/internal_ci/windows/grpc_distribtests.bat
index effeee6..72d7076 100644
--- a/tools/internal_ci/windows/grpc_distribtests.bat
+++ b/tools/internal_ci/windows/grpc_distribtests.bat
@@ -12,12 +12,6 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-@rem Move python installation from _32bit to _32bits where they are expected by python artifact builder
-@rem TODO(jtattermusch): get rid of this hack
-rename C:\Python27_32bit Python27_32bits
-rename C:\Python35_32bit Python35_32bits
-rename C:\Python36_32bit Python36_32bits
-
 @rem enter repo root
 cd /d %~dp0\..\..\..
 
diff --git a/tools/internal_ci/windows/grpc_distribtests_standalone.bat b/tools/internal_ci/windows/grpc_distribtests_standalone.bat
index b33b99c..8033467 100644
--- a/tools/internal_ci/windows/grpc_distribtests_standalone.bat
+++ b/tools/internal_ci/windows/grpc_distribtests_standalone.bat
@@ -12,12 +12,6 @@
 @rem See the License for the specific language governing permissions and
 @rem limitations under the License.
 
-@rem Move python installation from _32bit to _32bits where they are expected by python artifact builder
-@rem TODO(jtattermusch): get rid of this hack
-rename C:\Python27_32bit Python27_32bits
-rename C:\Python35_32bit Python35_32bits
-rename C:\Python36_32bit Python36_32bits
-
 @rem enter repo root
 cd /d %~dp0\..\..\..
 
diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py
index 0709db9..c1288cd 100644
--- a/tools/run_tests/artifacts/artifact_targets.py
+++ b/tools/run_tests/artifacts/artifact_targets.py
@@ -407,18 +407,16 @@
         PythonArtifact('macos', 'x64', 'python3.6'),
         PythonArtifact('macos', 'x64', 'python3.7'),
         PythonArtifact('macos', 'x64', 'python3.8'),
-        PythonArtifact('windows', 'x86', 'Python27_32bits'),
-        PythonArtifact('windows', 'x86', 'Python35_32bits'),
-        PythonArtifact('windows', 'x86', 'Python36_32bits'),
-        PythonArtifact('windows', 'x86', 'Python37_32bits'),
-        # TODO(https://github.com/grpc/grpc/issues/20615) Enable this artifact
-        # PythonArtifact('windows', 'x86', 'Python38_32bits'),
+        PythonArtifact('windows', 'x86', 'Python27_32bit'),
+        PythonArtifact('windows', 'x86', 'Python35_32bit'),
+        PythonArtifact('windows', 'x86', 'Python36_32bit'),
+        PythonArtifact('windows', 'x86', 'Python37_32bit'),
+        PythonArtifact('windows', 'x86', 'Python38_32bit'),
         PythonArtifact('windows', 'x64', 'Python27'),
         PythonArtifact('windows', 'x64', 'Python35'),
         PythonArtifact('windows', 'x64', 'Python36'),
         PythonArtifact('windows', 'x64', 'Python37'),
-        # TODO(https://github.com/grpc/grpc/issues/20615) Enable this artifact
-        # PythonArtifact('windows', 'x64', 'Python38'),
+        PythonArtifact('windows', 'x64', 'Python38'),
         RubyArtifact('linux', 'x64'),
         RubyArtifact('macos', 'x64'),
         PHPArtifact('linux', 'x64')
diff --git a/tools/run_tests/artifacts/build_artifact_python.bat b/tools/run_tests/artifacts/build_artifact_python.bat
index 88a331e..b1e0ee7 100644
--- a/tools/run_tests/artifacts/build_artifact_python.bat
+++ b/tools/run_tests/artifacts/build_artifact_python.bat
@@ -15,10 +15,10 @@
 @rem set path to python & mingw compiler
 set PATH=C:\%1;C:\%1\scripts;C:\msys64\mingw%2\bin;C:\tools\msys64\mingw%2\bin;%PATH%
 
-pip install --upgrade six
+python -m pip install --upgrade six
 @rem some artifacts are broken for setuptools 38.5.0. See https://github.com/grpc/grpc/issues/14317
-pip install --upgrade setuptools==38.2.4
-pip install -rrequirements.txt
+python -m pip install --upgrade setuptools==38.2.4
+python -m pip install -rrequirements.txt
 
 set GRPC_PYTHON_BUILD_WITH_CYTHON=1