diff --git a/BUILD b/BUILD
index 1e1529162cf3e9404217108732efc87f2945c038..2bf302a7a0a39393c9835226f932f9373fc66c54 100644
--- a/BUILD
+++ b/BUILD
@@ -320,6 +320,7 @@ cc_library(
     "src/core/ext/census/mlog.h",
     "src/core/ext/census/resource.h",
     "src/core/ext/census/rpc_metric_id.h",
+    "src/core/ext/census/trace_context.h",
     "src/core/lib/surface/init.c",
     "src/core/lib/channel/channel_args.c",
     "src/core/lib/channel/channel_stack.c",
@@ -508,6 +509,7 @@ cc_library(
     "src/core/ext/census/operation.c",
     "src/core/ext/census/placeholders.c",
     "src/core/ext/census/resource.c",
+    "src/core/ext/census/trace_context.c",
     "src/core/ext/census/tracing.c",
     "src/core/plugin_registry/grpc_plugin_registry.c",
   ],
@@ -1047,6 +1049,7 @@ cc_library(
     "src/core/ext/census/mlog.h",
     "src/core/ext/census/resource.h",
     "src/core/ext/census/rpc_metric_id.h",
+    "src/core/ext/census/trace_context.h",
     "src/core/lib/surface/init.c",
     "src/core/lib/surface/init_unsecure.c",
     "src/core/lib/channel/channel_args.c",
@@ -1206,6 +1209,7 @@ cc_library(
     "src/core/ext/census/operation.c",
     "src/core/ext/census/placeholders.c",
     "src/core/ext/census/resource.c",
+    "src/core/ext/census/trace_context.c",
     "src/core/ext/census/tracing.c",
     "src/core/plugin_registry/grpc_unsecure_plugin_registry.c",
   ],
@@ -2359,6 +2363,7 @@ objc_library(
     "src/core/ext/census/operation.c",
     "src/core/ext/census/placeholders.c",
     "src/core/ext/census/resource.c",
+    "src/core/ext/census/trace_context.c",
     "src/core/ext/census/tracing.c",
     "src/core/plugin_registry/grpc_plugin_registry.c",
   ],
@@ -2547,6 +2552,7 @@ objc_library(
     "src/core/ext/census/mlog.h",
     "src/core/ext/census/resource.h",
     "src/core/ext/census/rpc_metric_id.h",
+    "src/core/ext/census/trace_context.h",
   ],
   includes = [
     "include",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2443e35243ca18fa48a21d000c68c01952007505..3d8e868398ff00862e1560656f21d69ac12fed8d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -480,6 +480,7 @@ add_library(grpc
   src/core/ext/census/operation.c
   src/core/ext/census/placeholders.c
   src/core/ext/census/resource.c
+  src/core/ext/census/trace_context.c
   src/core/ext/census/tracing.c
   src/core/plugin_registry/grpc_plugin_registry.c
 )
@@ -937,6 +938,7 @@ add_library(grpc_unsecure
   src/core/ext/census/operation.c
   src/core/ext/census/placeholders.c
   src/core/ext/census/resource.c
+  src/core/ext/census/trace_context.c
   src/core/ext/census/tracing.c
   src/core/plugin_registry/grpc_unsecure_plugin_registry.c
 )
diff --git a/Makefile b/Makefile
index fe09540ff4562c2d21bca5764ed83a05b3b6ae83..914f4a5031557f0ae7f506b3ad284d1c13b206f5 100644
--- a/Makefile
+++ b/Makefile
@@ -909,6 +909,7 @@ bin_decoder_test: $(BINDIR)/$(CONFIG)/bin_decoder_test
 bin_encoder_test: $(BINDIR)/$(CONFIG)/bin_encoder_test
 census_context_test: $(BINDIR)/$(CONFIG)/census_context_test
 census_resource_test: $(BINDIR)/$(CONFIG)/census_resource_test
+census_trace_context_test: $(BINDIR)/$(CONFIG)/census_trace_context_test
 channel_create_test: $(BINDIR)/$(CONFIG)/channel_create_test
 chttp2_hpack_encoder_test: $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test
 chttp2_status_conversion_test: $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test
@@ -1237,6 +1238,7 @@ buildtests_c: privatelibs_c \
   $(BINDIR)/$(CONFIG)/bin_encoder_test \
   $(BINDIR)/$(CONFIG)/census_context_test \
   $(BINDIR)/$(CONFIG)/census_resource_test \
+  $(BINDIR)/$(CONFIG)/census_trace_context_test \
   $(BINDIR)/$(CONFIG)/channel_create_test \
   $(BINDIR)/$(CONFIG)/chttp2_hpack_encoder_test \
   $(BINDIR)/$(CONFIG)/chttp2_status_conversion_test \
@@ -1551,6 +1553,8 @@ test_c: buildtests_c
 	$(Q) $(BINDIR)/$(CONFIG)/census_context_test || ( echo test census_context_test failed ; exit 1 )
 	$(E) "[RUN]     Testing census_resource_test"
 	$(Q) $(BINDIR)/$(CONFIG)/census_resource_test || ( echo test census_resource_test failed ; exit 1 )
+	$(E) "[RUN]     Testing census_trace_context_test"
+	$(Q) $(BINDIR)/$(CONFIG)/census_trace_context_test || ( echo test census_trace_context_test failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_create_test"
 	$(Q) $(BINDIR)/$(CONFIG)/channel_create_test || ( echo test channel_create_test failed ; exit 1 )
 	$(E) "[RUN]     Testing chttp2_hpack_encoder_test"
@@ -2709,6 +2713,7 @@ LIBGRPC_SRC = \
     src/core/ext/census/operation.c \
     src/core/ext/census/placeholders.c \
     src/core/ext/census/resource.c \
+    src/core/ext/census/trace_context.c \
     src/core/ext/census/tracing.c \
     src/core/plugin_registry/grpc_plugin_registry.c \
 
@@ -3410,6 +3415,7 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/census/operation.c \
     src/core/ext/census/placeholders.c \
     src/core/ext/census/resource.c \
+    src/core/ext/census/trace_context.c \
     src/core/ext/census/tracing.c \
     src/core/plugin_registry/grpc_unsecure_plugin_registry.c \
 
@@ -7217,6 +7223,38 @@ endif
 endif
 
 
+CENSUS_TRACE_CONTEXT_TEST_SRC = \
+    test/core/census/trace_context_test.c \
+
+CENSUS_TRACE_CONTEXT_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(CENSUS_TRACE_CONTEXT_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/census_trace_context_test: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/census_trace_context_test: $(CENSUS_TRACE_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(CENSUS_TRACE_CONTEXT_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/census_trace_context_test
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/census/trace_context_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_census_trace_context_test: $(CENSUS_TRACE_CONTEXT_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(CENSUS_TRACE_CONTEXT_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 CHANNEL_CREATE_TEST_SRC = \
     test/core/surface/channel_create_test.c \
 
diff --git a/binding.gyp b/binding.gyp
index f5af509941d154748465437e1f24d20af0587428..2dbf276c2ffd6eb6397d769767001e22ea28c1ff 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -755,6 +755,7 @@
         'src/core/ext/census/operation.c',
         'src/core/ext/census/placeholders.c',
         'src/core/ext/census/resource.c',
+        'src/core/ext/census/trace_context.c',
         'src/core/ext/census/tracing.c',
         'src/core/plugin_registry/grpc_plugin_registry.c',
       ],
diff --git a/build.yaml b/build.yaml
index 3bcf405056f52616544c44e39985479ca2bbee5d..3f64bd1e16a6da2c833e8a1c270c76c6188977b7 100644
--- a/build.yaml
+++ b/build.yaml
@@ -29,6 +29,7 @@ filegroups:
   - src/core/ext/census/mlog.h
   - src/core/ext/census/resource.h
   - src/core/ext/census/rpc_metric_id.h
+  - src/core/ext/census/trace_context.h
   src:
   - src/core/ext/census/base_resources.c
   - src/core/ext/census/context.c
@@ -42,6 +43,7 @@ filegroups:
   - src/core/ext/census/operation.c
   - src/core/ext/census/placeholders.c
   - src/core/ext/census/resource.c
+  - src/core/ext/census/trace_context.c
   - src/core/ext/census/tracing.c
   plugin: census_grpc_plugin
   uses:
@@ -1349,6 +1351,16 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: census_trace_context_test
+  build: test
+  language: c
+  src:
+  - test/core/census/trace_context_test.c
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: channel_create_test
   build: test
   language: c
diff --git a/config.m4 b/config.m4
index 391a9ec41fefc1aa3fe7f330f6179554d19a976d..28b518f32dc67034a792ebbbf184c4a1bbd3b20c 100644
--- a/config.m4
+++ b/config.m4
@@ -274,6 +274,7 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/census/operation.c \
     src/core/ext/census/placeholders.c \
     src/core/ext/census/resource.c \
+    src/core/ext/census/trace_context.c \
     src/core/ext/census/tracing.c \
     src/core/plugin_registry/grpc_plugin_registry.c \
     src/boringssl/err_data.c \
diff --git a/examples/php/route_guide/run_route_guide_client.sh b/examples/php/route_guide/run_route_guide_client.sh
index 90ecc6270bb03e304e49667c12a5c3fa5b98c59e..10e6f00238a471f582dd20a0ff5f8ad30a6fbd7e 100755
--- a/examples/php/route_guide/run_route_guide_client.sh
+++ b/examples/php/route_guide/run_route_guide_client.sh
@@ -30,5 +30,6 @@
 
 set -e
 cd $(dirname $0)
-php $extension_dir -d extension=grpc.so -d max_execution_time=300 \
-  route_guide_client.php ../../node/route_guide/route_guide_db.json
+php -d extension=grpc.so -d max_execution_time=300 \
+  route_guide_client.php \
+  ../../node/static_codegen/route_guide/route_guide_db.json
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 8104b4f0f6e82b3ef37bd79d490ef96821d943cc..228e022e8d46aea7a6196f4fb131fedcd64f944e 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -411,6 +411,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/census/mlog.h',
                       'src/core/ext/census/resource.h',
                       'src/core/ext/census/rpc_metric_id.h',
+                      'src/core/ext/census/trace_context.h',
                       'src/core/lib/surface/init.c',
                       'src/core/lib/channel/channel_args.c',
                       'src/core/lib/channel/channel_stack.c',
@@ -602,6 +603,7 @@ Pod::Spec.new do |s|
                       'src/core/ext/census/operation.c',
                       'src/core/ext/census/placeholders.c',
                       'src/core/ext/census/resource.c',
+                      'src/core/ext/census/trace_context.c',
                       'src/core/ext/census/tracing.c',
                       'src/core/plugin_registry/grpc_plugin_registry.c'
 
@@ -779,7 +781,8 @@ Pod::Spec.new do |s|
                               'src/core/ext/census/grpc_filter.h',
                               'src/core/ext/census/mlog.h',
                               'src/core/ext/census/resource.h',
-                              'src/core/ext/census/rpc_metric_id.h'
+                              'src/core/ext/census/rpc_metric_id.h',
+                              'src/core/ext/census/trace_context.h'
   end
 
   s.subspec 'Cronet-Interface' do |ss|
diff --git a/grpc.gemspec b/grpc.gemspec
index f8b309a8d6f7290751a3b1543a99ef0ac4bf451d..9308d4997633787647739f01f6dab789f180fa09 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -331,6 +331,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/census/mlog.h )
   s.files += %w( src/core/ext/census/resource.h )
   s.files += %w( src/core/ext/census/rpc_metric_id.h )
+  s.files += %w( src/core/ext/census/trace_context.h )
   s.files += %w( src/core/lib/surface/init.c )
   s.files += %w( src/core/lib/channel/channel_args.c )
   s.files += %w( src/core/lib/channel/channel_stack.c )
@@ -522,6 +523,7 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/census/operation.c )
   s.files += %w( src/core/ext/census/placeholders.c )
   s.files += %w( src/core/ext/census/resource.c )
+  s.files += %w( src/core/ext/census/trace_context.c )
   s.files += %w( src/core/ext/census/tracing.c )
   s.files += %w( src/core/plugin_registry/grpc_plugin_registry.c )
   s.files += %w( third_party/boringssl/crypto/aes/internal.h )
diff --git a/package.xml b/package.xml
index 936ddf6a20dc5c4cd175ec4c3d205a9b5dea7622..0e37406ca258d07ca55a7902ba40f4a69c1e420b 100644
--- a/package.xml
+++ b/package.xml
@@ -338,6 +338,7 @@
     <file baseinstalldir="/" name="src/core/ext/census/mlog.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/resource.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/rpc_metric_id.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/trace_context.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_args.c" role="src" />
     <file baseinstalldir="/" name="src/core/lib/channel/channel_stack.c" role="src" />
@@ -529,6 +530,7 @@
     <file baseinstalldir="/" name="src/core/ext/census/operation.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/placeholders.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/resource.c" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/census/trace_context.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/census/tracing.c" role="src" />
     <file baseinstalldir="/" name="src/core/plugin_registry/grpc_plugin_registry.c" role="src" />
     <file baseinstalldir="/" name="third_party/boringssl/crypto/aes/internal.h" role="src" />
diff --git a/src/core/ext/census/trace_context.c b/src/core/ext/census/trace_context.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbb20d3448f781cfe502268814ccb27e74f698ba
--- /dev/null
+++ b/src/core/ext/census/trace_context.c
@@ -0,0 +1,86 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/ext/census/trace_context.h"
+
+#include <grpc/census.h>
+#include <grpc/support/log.h>
+#include <stdbool.h>
+
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+// This function assumes the TraceContext is valid.
+size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
+                            const size_t buf_size) {
+  // Create a stream that will write to our buffer.
+  pb_ostream_t stream = pb_ostream_from_buffer(buffer, buf_size);
+
+  // encode message
+  bool status = pb_encode(&stream, google_trace_TraceContext_fields, ctxt);
+
+  if (!status) {
+    gpr_log(GPR_DEBUG, "TraceContext encoding failed: %s",
+            PB_GET_ERROR(&stream));
+    return 0;
+  }
+
+  return stream.bytes_written;
+}
+
+bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
+                          const size_t nbytes) {
+  // Create a stream that reads nbytes from the buffer.
+  pb_istream_t stream = pb_istream_from_buffer(buffer, nbytes);
+
+  // decode message
+  bool status = pb_decode(&stream, google_trace_TraceContext_fields, ctxt);
+
+  if (!status) {
+    gpr_log(GPR_DEBUG, "TraceContext decoding failed: %s",
+            PB_GET_ERROR(&stream));
+    return false;
+  }
+
+  // check fields
+  if (!ctxt->has_trace_id) {
+    gpr_log(GPR_DEBUG, "Invalid TraceContext: missing trace_id");
+    return false;
+  }
+  if (!ctxt->has_span_id) {
+    gpr_log(GPR_DEBUG, "Invalid TraceContext: missing span_id");
+    return false;
+  }
+
+  return true;
+}
diff --git a/src/core/ext/census/trace_context.h b/src/core/ext/census/trace_context.h
new file mode 100644
index 0000000000000000000000000000000000000000..ee71fef460e83442821cea9418c4187c12872852
--- /dev/null
+++ b/src/core/ext/census/trace_context.h
@@ -0,0 +1,68 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Functions for manipulating trace contexts as defined in
+   src/proto/census/trace.proto */
+#ifndef GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H
+#define GRPC_CORE_EXT_CENSUS_TRACE_CONTEXT_H
+
+#include "src/core/ext/census/gen/trace_context.pb.h"
+
+/* Maximum number of bytes required to encode a TraceContext (31)
+1 byte for trace_id field
+1 byte for trace_id length
+1 byte for trace_id.hi field
+8 bytes for trace_id.hi (uint64_t)
+1 byte for trace_id.lo field
+8 bytes for trace_id.lo (uint64_t)
+1 byte for span_id field
+8 bytes for span_id (uint64_t)
+1 byte for is_sampled field
+1 byte for is_sampled (bool) */
+#define TRACE_MAX_CONTEXT_SIZE 31
+
+/* Encode a trace context (ctxt) into proto format to the buffer provided.  The
+size of buffer must be at least TRACE_MAX_CONTEXT_SIZE.  On success, returns the
+number of bytes successfully encoded into buffer.  On failure, returns 0. */
+size_t encode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
+                            const size_t buf_size);
+
+/* Decode a proto-encoded TraceContext from the provided buffer into the
+TraceContext structure (ctxt).  The function expects to be supplied the number
+of bytes to be read from buffer (nbytes).  This function will also validate that
+the TraceContext has a span_id and a trace_id, and will return false if either
+of these do not exist. On success, returns true and false otherwise. */
+bool decode_trace_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
+                          const size_t nbytes);
+
+#endif
diff --git a/src/core/ext/census/tracing.c b/src/core/ext/census/tracing.c
index 3b5d6dab2b8d775f1624e5f922f9f692e66b98ea..8f0e12296ddc13b7b7a8608f7efe462f26744fe0 100644
--- a/src/core/ext/census/tracing.c
+++ b/src/core/ext/census/tracing.c
@@ -31,15 +31,19 @@
  *
  */
 
+//#include "src/core/ext/census/tracing.h"
+
 #include <grpc/census.h>
 
 /* TODO(aveitch): These are all placeholder implementations. */
 
-int census_trace_mask(const census_context *context) {
-  return CENSUS_TRACE_MASK_NONE;
-}
+// int census_trace_mask(const census_context *context) {
+//   return CENSUS_TRACE_MASK_NONE;
+// }
+
+// void census_set_trace_mask(int trace_mask) {}
 
-void census_set_trace_mask(int trace_mask) {}
+// void census_trace_print(census_context *context, uint32_t type,
+//                         const char *buffer, size_t n) {}
 
-void census_trace_print(census_context *context, uint32_t type,
-                        const char *buffer, size_t n) {}
+// void SetTracerParams(const Params& params);
diff --git a/src/core/ext/client_config/client_channel.c b/src/core/ext/client_config/client_channel.c
index 3ed66a33136dce0b108d66e025ff37ec50c632bc..2ec37a1a4dade662a235280f651a981a901120eb 100644
--- a/src/core/ext/client_config/client_channel.c
+++ b/src/core/ext/client_config/client_channel.c
@@ -42,6 +42,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/useful.h>
 
+#include "src/core/ext/client_config/lb_policy_registry.h"
 #include "src/core/ext/client_config/subchannel.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/connected_channel.h"
@@ -64,6 +65,8 @@ typedef struct client_channel_channel_data {
   grpc_resolver *resolver;
   /** have we started resolving this channel */
   bool started_resolving;
+  /** client channel factory */
+  grpc_client_channel_factory *client_channel_factory;
 
   /** mutex protecting client configuration, including all
       variables below in this data structure */
@@ -174,20 +177,26 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
   grpc_error *state_error = GRPC_ERROR_CREATE("No load balancing policy");
 
   if (chand->resolver_result != NULL) {
-    lb_policy = grpc_resolver_result_get_lb_policy(chand->resolver_result);
+    grpc_lb_policy_args lb_policy_args;
+    lb_policy_args.addresses =
+        grpc_resolver_result_get_addresses(chand->resolver_result);
+    lb_policy_args.additional_args =
+        grpc_resolver_result_get_lb_policy_args(chand->resolver_result);
+    lb_policy_args.client_channel_factory = chand->client_channel_factory;
+    lb_policy = grpc_lb_policy_create(
+        exec_ctx,
+        grpc_resolver_result_get_lb_policy_name(chand->resolver_result),
+        &lb_policy_args);
     if (lb_policy != NULL) {
-      GRPC_LB_POLICY_REF(lb_policy, "channel");
       GRPC_LB_POLICY_REF(lb_policy, "config_change");
       GRPC_ERROR_UNREF(state_error);
       state =
           grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
     }
-
     grpc_resolver_result_unref(exec_ctx, chand->resolver_result);
+    chand->resolver_result = NULL;
   }
 
-  chand->resolver_result = NULL;
-
   if (lb_policy != NULL) {
     grpc_pollset_set_add_pollset_set(exec_ctx, lb_policy->interested_parties,
                                      chand->interested_parties);
@@ -347,6 +356,9 @@ static void cc_destroy_channel_elem(grpc_exec_ctx *exec_ctx,
     grpc_resolver_shutdown(exec_ctx, chand->resolver);
     GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
   }
+  if (chand->client_channel_factory != NULL) {
+    grpc_client_channel_factory_unref(exec_ctx, chand->client_channel_factory);
+  }
   if (chand->lb_policy != NULL) {
     grpc_pollset_set_del_pollset_set(exec_ctx,
                                      chand->lb_policy->interested_parties,
@@ -796,10 +808,12 @@ const grpc_channel_filter grpc_client_channel_filter = {
     "client-channel",
 };
 
-void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
-                                      grpc_channel_stack *channel_stack,
-                                      grpc_resolver *resolver) {
+void grpc_client_channel_finish_initialization(
+    grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
+    grpc_resolver *resolver,
+    grpc_client_channel_factory *client_channel_factory) {
   /* post construction initialization: set the transport setup pointer */
+  GPR_ASSERT(client_channel_factory != NULL);
   grpc_channel_element *elem = grpc_channel_stack_last_element(channel_stack);
   channel_data *chand = elem->channel_data;
   gpr_mu_lock(&chand->mu);
@@ -813,6 +827,8 @@ void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
     grpc_resolver_next(exec_ctx, resolver, &chand->resolver_result,
                        &chand->on_resolver_result_changed);
   }
+  chand->client_channel_factory = client_channel_factory;
+  grpc_client_channel_factory_ref(client_channel_factory);
   gpr_mu_unlock(&chand->mu);
 }
 
diff --git a/src/core/ext/client_config/client_channel.h b/src/core/ext/client_config/client_channel.h
index 1e47ad34ad8bbea6cc713e5e056983c63850fcd7..abb5ac4d878a2a21d397d9a74972a634d2c37251 100644
--- a/src/core/ext/client_config/client_channel.h
+++ b/src/core/ext/client_config/client_channel.h
@@ -34,6 +34,7 @@
 #ifndef GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_H
 #define GRPC_CORE_EXT_CLIENT_CONFIG_CLIENT_CHANNEL_H
 
+#include "src/core/ext/client_config/client_channel_factory.h"
 #include "src/core/ext/client_config/resolver.h"
 #include "src/core/lib/channel/channel_stack.h"
 
@@ -46,12 +47,12 @@
 
 extern const grpc_channel_filter grpc_client_channel_filter;
 
-/* post-construction initializer to let the client channel know which
-   transport setup it should cancel upon destruction, or initiate when it needs
-   a connection */
-void grpc_client_channel_set_resolver(grpc_exec_ctx *exec_ctx,
-                                      grpc_channel_stack *channel_stack,
-                                      grpc_resolver *resolver);
+/* Post-construction initializer to give the client channel its resolver
+   and factory. */
+void grpc_client_channel_finish_initialization(
+    grpc_exec_ctx *exec_ctx, grpc_channel_stack *channel_stack,
+    grpc_resolver *resolver,
+    grpc_client_channel_factory *client_channel_factory);
 
 grpc_connectivity_state grpc_client_channel_check_connectivity_state(
     grpc_exec_ctx *exec_ctx, grpc_channel_element *elem, int try_to_connect);
diff --git a/src/core/ext/client_config/lb_policy_factory.c b/src/core/ext/client_config/lb_policy_factory.c
index f86117aa384e6ed971728676b26197c51727274c..c17af91a09e4b762771a9bd24aca708341206242 100644
--- a/src/core/ext/client_config/lb_policy_factory.c
+++ b/src/core/ext/client_config/lb_policy_factory.c
@@ -34,6 +34,7 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
 
 #include "src/core/ext/client_config/lb_policy_factory.h"
 
@@ -46,6 +47,25 @@ grpc_lb_addresses* grpc_lb_addresses_create(size_t num_addresses) {
   return addresses;
 }
 
+grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses,
+                                          void* (*user_data_copy)(void*)) {
+  grpc_lb_addresses* new_addresses =
+      grpc_lb_addresses_create(addresses->num_addresses);
+  memcpy(new_addresses->addresses, addresses->addresses,
+         sizeof(grpc_lb_address) * addresses->num_addresses);
+  for (size_t i = 0; i < addresses->num_addresses; ++i) {
+    if (new_addresses->addresses[i].balancer_name != NULL) {
+      new_addresses->addresses[i].balancer_name =
+          gpr_strdup(new_addresses->addresses[i].balancer_name);
+    }
+    if (user_data_copy != NULL) {
+      new_addresses->addresses[i].user_data =
+          user_data_copy(new_addresses->addresses[i].user_data);
+    }
+  }
+  return new_addresses;
+}
+
 void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
                                    void* address, size_t address_len,
                                    bool is_balancer, char* balancer_name,
diff --git a/src/core/ext/client_config/lb_policy_factory.h b/src/core/ext/client_config/lb_policy_factory.h
index b31179cf80b0daee52d643db0b2b8be6ce91293f..54408c63080bd2b6da38bcf878d9e4a403212f13 100644
--- a/src/core/ext/client_config/lb_policy_factory.h
+++ b/src/core/ext/client_config/lb_policy_factory.h
@@ -36,9 +36,9 @@
 
 #include "src/core/ext/client_config/client_channel_factory.h"
 #include "src/core/ext/client_config/lb_policy.h"
-#include "src/core/ext/client_config/resolver_result.h"
 
 #include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/resolve_address.h"
 
 typedef struct grpc_lb_policy_factory grpc_lb_policy_factory;
 typedef struct grpc_lb_policy_factory_vtable grpc_lb_policy_factory_vtable;
@@ -68,6 +68,11 @@ typedef struct grpc_lb_addresses {
  * \a num_addresses addresses. */
 grpc_lb_addresses *grpc_lb_addresses_create(size_t num_addresses);
 
+/** Creates a copy of \a addresses.  If \a user_data_copy is not NULL,
+ * it will be invoked to copy the \a user_data field of each address. */
+grpc_lb_addresses *grpc_lb_addresses_copy(grpc_lb_addresses *addresses,
+                                          void *(*user_data_copy)(void *));
+
 /** Sets the value of the address at index \a index of \a addresses.
  * \a address is a socket address of length \a address_len.
  * Takes ownership of \a balancer_name. */
@@ -82,9 +87,13 @@ void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses,
                                void (*user_data_destroy)(void *));
 
 /** Arguments passed to LB policies. */
+/* TODO(roth, ctiller): Consider replacing this struct with
+   grpc_channel_args.  See comment in resolver_result.h for details. */
 typedef struct grpc_lb_policy_args {
   grpc_lb_addresses *addresses;
   grpc_client_channel_factory *client_channel_factory;
+  /* Can be used to pass implementation-specific parameters to the LB policy. */
+  grpc_channel_args *additional_args;
 } grpc_lb_policy_args;
 
 struct grpc_lb_policy_factory_vtable {
diff --git a/src/core/ext/client_config/resolver_factory.h b/src/core/ext/client_config/resolver_factory.h
index f69bf795649d6be2129821e8ccba324e7bf9b23e..9ec5b9a70e70de38849cbb827a642ba350759202 100644
--- a/src/core/ext/client_config/resolver_factory.h
+++ b/src/core/ext/client_config/resolver_factory.h
@@ -47,10 +47,7 @@ struct grpc_resolver_factory {
   const grpc_resolver_factory_vtable *vtable;
 };
 
-typedef struct grpc_resolver_args {
-  grpc_uri *uri;
-  grpc_client_channel_factory *client_channel_factory;
-} grpc_resolver_args;
+typedef struct grpc_resolver_args { grpc_uri *uri; } grpc_resolver_args;
 
 struct grpc_resolver_factory_vtable {
   void (*ref)(grpc_resolver_factory *factory);
diff --git a/src/core/ext/client_config/resolver_registry.c b/src/core/ext/client_config/resolver_registry.c
index e7a4abd568c0112b60da65835dd4aafeb40375d2..b5308a140c910506440c8eb5b8e0ad4ff3c295bf 100644
--- a/src/core/ext/client_config/resolver_registry.c
+++ b/src/core/ext/client_config/resolver_registry.c
@@ -128,15 +128,13 @@ static grpc_resolver_factory *resolve_factory(const char *target,
   return factory;
 }
 
-grpc_resolver *grpc_resolver_create(
-    const char *target, grpc_client_channel_factory *client_channel_factory) {
+grpc_resolver *grpc_resolver_create(const char *target) {
   grpc_uri *uri = NULL;
   grpc_resolver_factory *factory = resolve_factory(target, &uri);
   grpc_resolver *resolver;
   grpc_resolver_args args;
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.client_channel_factory = client_channel_factory;
   resolver = grpc_resolver_factory_create_resolver(factory, &args);
   grpc_uri_destroy(uri);
   return resolver;
diff --git a/src/core/ext/client_config/resolver_registry.h b/src/core/ext/client_config/resolver_registry.h
index 5ef1383cd35d607b00d3f62ca6f450cfeaf020a3..92e248d5488882cfceebb1c4e82a2e1034bacf45 100644
--- a/src/core/ext/client_config/resolver_registry.h
+++ b/src/core/ext/client_config/resolver_registry.h
@@ -55,8 +55,7 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
     If a resolver factory was found, use it to instantiate a resolver and
     return it.
     If a resolver factory was not found, return NULL. */
-grpc_resolver *grpc_resolver_create(
-    const char *target, grpc_client_channel_factory *client_channel_factory);
+grpc_resolver *grpc_resolver_create(const char *target);
 
 /** Find a resolver factory given a name and return an (owned-by-the-caller)
  *  reference to it */
diff --git a/src/core/ext/client_config/resolver_result.c b/src/core/ext/client_config/resolver_result.c
index 242989a0da94b6da88d41bcf6c4b1859422809cf..59c9e7dc25516f7a1801d9c8251d0cf616d131e0 100644
--- a/src/core/ext/client_config/resolver_result.c
+++ b/src/core/ext/client_config/resolver_result.c
@@ -34,40 +34,54 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/lib/channel/channel_args.h"
 
 struct grpc_resolver_result {
   gpr_refcount refs;
-  grpc_lb_policy* lb_policy;
+  grpc_lb_addresses* addresses;
+  char* lb_policy_name;
+  grpc_channel_args* lb_policy_args;
 };
 
-grpc_resolver_result* grpc_resolver_result_create() {
-  grpc_resolver_result* c = gpr_malloc(sizeof(*c));
-  memset(c, 0, sizeof(*c));
-  gpr_ref_init(&c->refs, 1);
-  return c;
+grpc_resolver_result* grpc_resolver_result_create(
+    grpc_lb_addresses* addresses, const char* lb_policy_name,
+    grpc_channel_args* lb_policy_args) {
+  grpc_resolver_result* result = gpr_malloc(sizeof(*result));
+  memset(result, 0, sizeof(*result));
+  gpr_ref_init(&result->refs, 1);
+  result->addresses = addresses;
+  result->lb_policy_name = gpr_strdup(lb_policy_name);
+  result->lb_policy_args = lb_policy_args;
+  return result;
 }
 
-void grpc_resolver_result_ref(grpc_resolver_result* c) { gpr_ref(&c->refs); }
+void grpc_resolver_result_ref(grpc_resolver_result* result) {
+  gpr_ref(&result->refs);
+}
 
 void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
-                                grpc_resolver_result* c) {
-  if (gpr_unref(&c->refs)) {
-    if (c->lb_policy != NULL) {
-      GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "resolver_result");
-    }
-    gpr_free(c);
+                                grpc_resolver_result* result) {
+  if (gpr_unref(&result->refs)) {
+    grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */);
+    gpr_free(result->lb_policy_name);
+    grpc_channel_args_destroy(result->lb_policy_args);
+    gpr_free(result);
   }
 }
 
-void grpc_resolver_result_set_lb_policy(grpc_resolver_result* c,
-                                        grpc_lb_policy* lb_policy) {
-  GPR_ASSERT(c->lb_policy == NULL);
-  if (lb_policy) {
-    GRPC_LB_POLICY_REF(lb_policy, "resolver_result");
-  }
-  c->lb_policy = lb_policy;
+grpc_lb_addresses* grpc_resolver_result_get_addresses(
+    grpc_resolver_result* result) {
+  return result->addresses;
+}
+
+const char* grpc_resolver_result_get_lb_policy_name(
+    grpc_resolver_result* result) {
+  return result->lb_policy_name;
 }
 
-grpc_lb_policy* grpc_resolver_result_get_lb_policy(grpc_resolver_result* c) {
-  return c->lb_policy;
+grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
+    grpc_resolver_result* result) {
+  return result->lb_policy_args;
 }
diff --git a/src/core/ext/client_config/resolver_result.h b/src/core/ext/client_config/resolver_result.h
index 5a69d81990795c1a35a02104dc71f922855b3776..d4118b90e8a06c610fbafd71002928424ea5660c 100644
--- a/src/core/ext/client_config/resolver_result.h
+++ b/src/core/ext/client_config/resolver_result.h
@@ -32,22 +32,40 @@
 #ifndef GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_RESULT_H
 #define GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_RESULT_H
 
-#include <stdbool.h>
-
-#include "src/core/ext/client_config/lb_policy.h"
+#include "src/core/ext/client_config/lb_policy_factory.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 
+// TODO(roth, ctiller): In the long term, we are considering replacing
+// the resolver_result data structure with grpc_channel_args.  The idea is
+// that the resolver will return a set of channel args that contains the
+// information that is currently in the resolver_result struct.  For
+// example, there will be specific args indicating the set of addresses
+// and the name of the LB policy to instantiate.  Note that if we did
+// this, we would probably want to change the data structure of
+// grpc_channel_args such to a hash table or AVL or some other data
+// structure that does not require linear search to find keys.
+
 /// Results reported from a grpc_resolver.
 typedef struct grpc_resolver_result grpc_resolver_result;
 
-grpc_resolver_result* grpc_resolver_result_create();
+/// Takes ownership of \a addresses and \a lb_policy_args.
+grpc_resolver_result* grpc_resolver_result_create(
+    grpc_lb_addresses* addresses, const char* lb_policy_name,
+    grpc_channel_args* lb_policy_args);
 void grpc_resolver_result_ref(grpc_resolver_result* result);
 void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
                                 grpc_resolver_result* result);
 
-void grpc_resolver_result_set_lb_policy(grpc_resolver_result* result,
-                                        grpc_lb_policy* lb_policy);
-grpc_lb_policy* grpc_resolver_result_get_lb_policy(
+/// Caller does NOT take ownership of result.
+grpc_lb_addresses* grpc_resolver_result_get_addresses(
+    grpc_resolver_result* result);
+
+/// Caller does NOT take ownership of result.
+const char* grpc_resolver_result_get_lb_policy_name(
+    grpc_resolver_result* result);
+
+/// Caller does NOT take ownership of result.
+grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
     grpc_resolver_result* result);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CONFIG_RESOLVER_RESULT_H */
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index 63682db7de57a549759b5a8fc9342776e659770a..1b85d2d6344bb4d2cf992c339f093cc26ad2f729 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -37,7 +37,6 @@
 #include <grpc/support/host_port.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/ext/client_config/lb_policy_registry.h"
 #include "src/core/ext/client_config/resolver_registry.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
@@ -58,8 +57,6 @@ typedef struct {
   char *name;
   /** default port to use */
   char *default_port;
-  /** subchannel factory */
-  grpc_client_channel_factory *client_channel_factory;
   /** load balancing policy name */
   char *lb_policy_name;
 
@@ -166,31 +163,20 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
                             grpc_error *error) {
   dns_resolver *r = arg;
   grpc_resolver_result *result = NULL;
-  grpc_lb_policy *lb_policy;
   gpr_mu_lock(&r->mu);
   GPR_ASSERT(r->resolving);
   r->resolving = 0;
   if (r->addresses != NULL) {
-    grpc_lb_policy_args lb_policy_args;
-    memset(&lb_policy_args, 0, sizeof(lb_policy_args));
-    lb_policy_args.addresses = grpc_lb_addresses_create(r->addresses->naddrs);
+    grpc_lb_addresses *addresses =
+        grpc_lb_addresses_create(r->addresses->naddrs);
     for (size_t i = 0; i < r->addresses->naddrs; ++i) {
       grpc_lb_addresses_set_address(
-          lb_policy_args.addresses, i, &r->addresses->addrs[i].addr,
+          addresses, i, &r->addresses->addrs[i].addr,
           r->addresses->addrs[i].len, false /* is_balancer */,
           NULL /* balancer_name */, NULL /* user_data */);
     }
     grpc_resolved_addresses_destroy(r->addresses);
-    lb_policy_args.client_channel_factory = r->client_channel_factory;
-    lb_policy =
-        grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
-    grpc_lb_addresses_destroy(lb_policy_args.addresses,
-                              NULL /* user_data_destroy */);
-    result = grpc_resolver_result_create();
-    if (lb_policy != NULL) {
-      grpc_resolver_result_set_lb_policy(result, lb_policy);
-      GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
-    }
+    result = grpc_resolver_result_create(addresses, r->lb_policy_name, NULL);
   } else {
     gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
@@ -251,7 +237,6 @@ static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
   if (r->resolved_result) {
     grpc_resolver_result_unref(exec_ctx, r->resolved_result);
   }
-  grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
   gpr_free(r->name);
   gpr_free(r->default_port);
   gpr_free(r->lb_policy_name);
@@ -278,10 +263,8 @@ static grpc_resolver *dns_create(grpc_resolver_args *args,
   grpc_resolver_init(&r->base, &dns_resolver_vtable);
   r->name = gpr_strdup(path);
   r->default_port = gpr_strdup(default_port);
-  r->client_channel_factory = args->client_channel_factory;
   gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
                    BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
-  grpc_client_channel_factory_ref(r->client_channel_factory);
   r->lb_policy_name = gpr_strdup(lb_policy_name);
   return &r->base;
 }
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index fbfe5d774b09ce984af4f6e516fd8d732dd471e1..ced4fb024c3f0f9d9eff2471015fe164d42c8dd0 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -40,7 +40,6 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/string_util.h>
 
-#include "src/core/ext/client_config/lb_policy_registry.h"
 #include "src/core/ext/client_config/parse_address.h"
 #include "src/core/ext/client_config/resolver_registry.h"
 #include "src/core/lib/iomgr/resolve_address.h"
@@ -52,8 +51,6 @@ typedef struct {
   grpc_resolver base;
   /** refcount */
   gpr_refcount refs;
-  /** subchannel factory */
-  grpc_client_channel_factory *client_channel_factory;
   /** load balancing policy name */
   char *lb_policy_name;
 
@@ -122,17 +119,10 @@ static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
 static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
                                               sockaddr_resolver *r) {
   if (r->next_completion != NULL && !r->published) {
-    grpc_resolver_result *result = grpc_resolver_result_create();
-    grpc_lb_policy_args lb_policy_args;
-    memset(&lb_policy_args, 0, sizeof(lb_policy_args));
-    lb_policy_args.addresses = r->addresses;
-    lb_policy_args.client_channel_factory = r->client_channel_factory;
-    grpc_lb_policy *lb_policy =
-        grpc_lb_policy_create(exec_ctx, r->lb_policy_name, &lb_policy_args);
-    grpc_resolver_result_set_lb_policy(result, lb_policy);
-    GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "sockaddr");
     r->published = true;
-    *r->target_result = result;
+    *r->target_result = grpc_resolver_result_create(
+        grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */),
+        r->lb_policy_name, NULL);
     grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
   }
@@ -141,7 +131,6 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
 static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
   sockaddr_resolver *r = (sockaddr_resolver *)gr;
   gpr_mu_destroy(&r->mu);
-  grpc_client_channel_factory_unref(exec_ctx, r->client_channel_factory);
   grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
   gpr_free(r->lb_policy_name);
   gpr_free(r);
@@ -243,8 +232,6 @@ static grpc_resolver *sockaddr_create(
   gpr_ref_init(&r->refs, 1);
   gpr_mu_init(&r->mu);
   grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
-  r->client_channel_factory = args->client_channel_factory;
-  grpc_client_channel_factory_ref(r->client_channel_factory);
 
   return &r->base;
 }
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index cbaa75a90affcaea8655ea0afe488e647cf2fd0f..ddc00bd79f8c50f14a6a5f7be914868bf8413168 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -160,7 +160,6 @@ typedef struct {
   grpc_client_channel_factory base;
   gpr_refcount refs;
   grpc_channel_args *merge_args;
-  grpc_channel *master;
 } client_channel_factory;
 
 static void client_channel_factory_ref(
@@ -173,10 +172,6 @@ static void client_channel_factory_unref(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
   client_channel_factory *f = (client_channel_factory *)cc_factory;
   if (gpr_unref(&f->refs)) {
-    if (f->master != NULL) {
-      GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
-                                  "client_channel_factory");
-    }
     grpc_channel_args_destroy(f->merge_args);
     gpr_free(f);
   }
@@ -210,15 +205,15 @@ static grpc_channel *client_channel_factory_create_channel(
   grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
                                               GRPC_CLIENT_CHANNEL, NULL);
   grpc_channel_args_destroy(final_args);
-  grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
+  grpc_resolver *resolver = grpc_resolver_create(target);
   if (!resolver) {
     GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
                                 "client_channel_factory_create_channel");
     return NULL;
   }
 
-  grpc_client_channel_set_resolver(
-      exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
+  grpc_client_channel_finish_initialization(
+      exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
   GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");
 
   return channel;
@@ -250,12 +245,8 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
 
   grpc_channel *channel = client_channel_factory_create_channel(
       &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
-  if (channel != NULL) {
-    f->master = channel;
-    GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_insecure_channel_create");
-  }
-  grpc_client_channel_factory_unref(&exec_ctx, &f->base);
 
+  grpc_client_channel_factory_unref(&exec_ctx, &f->base);
   grpc_exec_ctx_finish(&exec_ctx);
 
   return channel != NULL ? channel : grpc_lame_client_channel_create(
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index 9e2bdd758f91ee21e360f2a2d802aa069f67e1f4..f36fbbfc579b515b46657a8b8266683ac888cfd1 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -220,7 +220,6 @@ typedef struct {
   gpr_refcount refs;
   grpc_channel_args *merge_args;
   grpc_channel_security_connector *security_connector;
-  grpc_channel *master;
 } client_channel_factory;
 
 static void client_channel_factory_ref(
@@ -235,10 +234,6 @@ static void client_channel_factory_unref(
   if (gpr_unref(&f->refs)) {
     GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                   "client_channel_factory");
-    if (f->master != NULL) {
-      GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master,
-                                  "client_channel_factory");
-    }
     grpc_channel_args_destroy(f->merge_args);
     gpr_free(f);
   }
@@ -276,10 +271,10 @@ static grpc_channel *client_channel_factory_create_channel(
                                               GRPC_CLIENT_CHANNEL, NULL);
   grpc_channel_args_destroy(final_args);
 
-  grpc_resolver *resolver = grpc_resolver_create(target, &f->base);
+  grpc_resolver *resolver = grpc_resolver_create(target);
   if (resolver != NULL) {
-    grpc_client_channel_set_resolver(
-        exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
+    grpc_client_channel_finish_initialization(
+        exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
     GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create");
   } else {
     GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
@@ -356,10 +351,6 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
 
   grpc_channel *channel = client_channel_factory_create_channel(
       &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
-  if (channel != NULL) {
-    f->master = channel;
-    GRPC_CHANNEL_INTERNAL_REF(f->master, "grpc_secure_channel_create");
-  }
 
   grpc_client_channel_factory_unref(&exec_ctx, &f->base);
   grpc_exec_ctx_finish(&exec_ctx);
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index d850eebc78890ed1a3a194779a8492e93388bddf..8a7f6572a626fd58fee645626cb9a936e4077f98 100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -182,6 +182,7 @@ class BaseStub
         } else {
             $hostname = $this->hostname;
         }
+
         return 'https://'.$hostname.$service_name;
     }
 
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index 94ceeda02c7476caae2badce917db378f75e4b80..4bc4589956c0f2c03bf574d26fd6568947ac11b4 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -70,7 +70,8 @@ function hardAssertIfStatusOk($status)
  */
 function emptyUnary($stub)
 {
-    list($result, $status) = $stub->EmptyCall(new grpc\testing\EmptyMessage())->wait();
+    list($result, $status) =
+        $stub->EmptyCall(new grpc\testing\EmptyMessage())->wait();
     hardAssertIfStatusOk($status);
     hardAssert($result !== null, 'Call completed with a null response');
 }
@@ -92,8 +93,8 @@ function largeUnary($stub)
  * @param $fillUsername boolean whether to fill result with username
  * @param $fillOauthScope boolean whether to fill result with oauth scope
  */
-function performLargeUnary($stub, $fillUsername = false, $fillOauthScope = false,
-                           $callback = false)
+function performLargeUnary($stub, $fillUsername = false,
+                           $fillOauthScope = false, $callback = false)
 {
     $request_len = 271828;
     $response_len = 314159;
@@ -118,11 +119,11 @@ function performLargeUnary($stub, $fillUsername = false, $fillOauthScope = false
     hardAssert($result !== null, 'Call returned a null response');
     $payload = $result->getPayload();
     hardAssert($payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
-         'Payload had the wrong type');
+               'Payload had the wrong type');
     hardAssert(strlen($payload->getBody()) === $response_len,
-         'Payload had the wrong length');
+               'Payload had the wrong length');
     hardAssert($payload->getBody() === str_repeat("\0", $response_len),
-         'Payload had the wrong content');
+               'Payload had the wrong content');
 
     return $result;
 }
@@ -141,11 +142,12 @@ function serviceAccountCreds($stub, $args)
     $jsonKey = json_decode(
         file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
         true);
-    $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true);
-    hardAssert($result->getUsername() == $jsonKey['client_email'],
-             'invalid email returned');
+    $result = performLargeUnary($stub, $fillUsername = true,
+                                $fillOauthScope = true);
+    hardAssert($result->getUsername() === $jsonKey['client_email'],
+               'invalid email returned');
     hardAssert(strpos($args['oauth_scope'], $result->getOauthScope()) !== false,
-             'invalid oauth scope returned');
+               'invalid oauth scope returned');
 }
 
 /**
@@ -163,9 +165,10 @@ function computeEngineCreds($stub, $args)
     if (!array_key_exists('default_service_account', $args)) {
         throw new Exception('Missing default_service_account');
     }
-    $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true);
-    hardAssert($args['default_service_account'] == $result->getUsername(),
-             'invalid email returned');
+    $result = performLargeUnary($stub, $fillUsername = true,
+                                $fillOauthScope = true);
+    hardAssert($args['default_service_account'] === $result->getUsername(),
+               'invalid email returned');
 }
 
 /**
@@ -179,9 +182,10 @@ function jwtTokenCreds($stub, $args)
     $jsonKey = json_decode(
         file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
         true);
-    $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true);
-    hardAssert($result->getUsername() == $jsonKey['client_email'],
-             'invalid email returned');
+    $result = performLargeUnary($stub, $fillUsername = true,
+                                $fillOauthScope = true);
+    hardAssert($result->getUsername() === $jsonKey['client_email'],
+               'invalid email returned');
 }
 
 /**
@@ -195,9 +199,10 @@ function oauth2AuthToken($stub, $args)
     $jsonKey = json_decode(
         file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
         true);
-    $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true);
-    hardAssert($result->getUsername() == $jsonKey['client_email'],
-             'invalid email returned');
+    $result = performLargeUnary($stub, $fillUsername = true,
+                                $fillOauthScope = true);
+    hardAssert($result->getUsername() === $jsonKey['client_email'],
+               'invalid email returned');
 }
 
 function updateAuthMetadataCallback($context)
@@ -209,8 +214,9 @@ function updateAuthMetadataCallback($context)
     $metadata = [];
     $result = $auth_credentials->updateMetadata([], $authUri);
     foreach ($result as $key => $value) {
-      $metadata[strtolower($key)] = $value;
+        $metadata[strtolower($key)] = $value;
     }
+
     return $metadata;
 }
 
@@ -226,10 +232,11 @@ function perRpcCreds($stub, $args)
         file_get_contents(getenv(CredentialsLoader::ENV_VAR)),
         true);
 
-    $result = performLargeUnary($stub, $fillUsername = true, $fillOauthScope = true,
+    $result = performLargeUnary($stub, $fillUsername = true,
+                                $fillOauthScope = true,
                                 'updateAuthMetadataCallback');
-    hardAssert($result->getUsername() == $jsonKey['client_email'],
-             'invalid email returned');
+    hardAssert($result->getUsername() === $jsonKey['client_email'],
+               'invalid email returned');
 }
 
 /**
@@ -258,7 +265,7 @@ function clientStreaming($stub)
     list($result, $status) = $call->wait();
     hardAssertIfStatusOk($status);
     hardAssert($result->getAggregatedPayloadSize() === 74922,
-              'aggregated_payload_size was incorrect');
+               'aggregated_payload_size was incorrect');
 }
 
 /**
@@ -283,10 +290,11 @@ function serverStreaming($stub)
     foreach ($call->responses() as $value) {
         hardAssert($i < 4, 'Too many responses');
         $payload = $value->getPayload();
-        hardAssert($payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
-                'Payload '.$i.' had the wrong type');
+        hardAssert(
+            $payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
+            'Payload '.$i.' had the wrong type');
         hardAssert(strlen($payload->getBody()) === $sizes[$i],
-                'Response '.$i.' had the wrong length');
+                   'Response '.$i.' had the wrong length');
         $i += 1;
     }
     hardAssertIfStatusOk($call->getStatus());
@@ -318,10 +326,11 @@ function pingPong($stub)
 
         hardAssert($response !== null, 'Server returned too few responses');
         $payload = $response->getPayload();
-        hardAssert($payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
-                'Payload '.$i.' had the wrong type');
+        hardAssert(
+            $payload->getType() === grpc\testing\PayloadType::COMPRESSABLE,
+            'Payload '.$i.' had the wrong type');
         hardAssert(strlen($payload->getBody()) === $response_lengths[$i],
-                'Payload '.$i.' had the wrong length');
+                   'Payload '.$i.' had the wrong length');
     }
     $call->writesDone();
     hardAssert($call->read() === null, 'Server returned too many responses');
@@ -352,7 +361,7 @@ function cancelAfterBegin($stub)
     $call->cancel();
     list($result, $status) = $call->wait();
     hardAssert($status->code === Grpc\STATUS_CANCELLED,
-             'Call status was not CANCELLED');
+               'Call status was not CANCELLED');
 }
 
 /**
@@ -377,7 +386,7 @@ function cancelAfterFirstResponse($stub)
 
     $call->cancel();
     hardAssert($call->getStatus()->code === Grpc\STATUS_CANCELLED,
-             'Call status was not CANCELLED');
+               'Call status was not CANCELLED');
 }
 
 function timeoutOnSleepingServer($stub)
@@ -396,7 +405,7 @@ function timeoutOnSleepingServer($stub)
     $response = $call->read();
 
     hardAssert($call->getStatus()->code === Grpc\STATUS_DEADLINE_EXCEEDED,
-             'Call status was not DEADLINE_EXCEEDED');
+               'Call status was not DEADLINE_EXCEEDED');
 }
 
 function customMetadata($stub)
@@ -425,9 +434,9 @@ function customMetadata($stub)
     $initial_metadata = $call->getMetadata();
     hardAssert(array_key_exists($ECHO_INITIAL_KEY, $initial_metadata),
                'Initial metadata does not contain expected key');
-    hardAssert($initial_metadata[$ECHO_INITIAL_KEY][0] ==
-               $ECHO_INITIAL_VALUE,
-               'Incorrect initial metadata value');
+    hardAssert(
+        $initial_metadata[$ECHO_INITIAL_KEY][0] === $ECHO_INITIAL_VALUE,
+        'Incorrect initial metadata value');
 
     list($result, $status) = $call->wait();
     hardAssertIfStatusOk($status);
@@ -435,8 +444,9 @@ function customMetadata($stub)
     $trailing_metadata = $call->getTrailingMetadata();
     hardAssert(array_key_exists($ECHO_TRAILING_KEY, $trailing_metadata),
                'Trailing metadata does not contain expected key');
-    hardAssert($trailing_metadata[$ECHO_TRAILING_KEY][0] ==
-               $ECHO_TRAILING_VALUE, 'Incorrect trailing metadata value');
+    hardAssert(
+        $trailing_metadata[$ECHO_TRAILING_KEY][0] === $ECHO_TRAILING_VALUE,
+        'Incorrect trailing metadata value');
 
     $streaming_call = $stub->FullDuplexCall($metadata);
 
@@ -451,7 +461,7 @@ function customMetadata($stub)
     hardAssert(array_key_exists($ECHO_TRAILING_KEY,
                                 $streaming_trailing_metadata),
                'Trailing metadata does not contain expected key');
-    hardAssert($streaming_trailing_metadata[$ECHO_TRAILING_KEY][0] ==
+    hardAssert($streaming_trailing_metadata[$ECHO_TRAILING_KEY][0] ===
                $ECHO_TRAILING_VALUE, 'Incorrect trailing metadata value');
 }
 
@@ -506,7 +516,7 @@ function _makeStub($args)
         throw new Exception('Missing argument: --test_case is required');
     }
 
-    if ($args['server_port'] == 443) {
+    if ($args['server_port'] === 443) {
         $server_address = $args['server_host'];
     } else {
         $server_address = $args['server_host'].':'.$args['server_port'];
@@ -548,7 +558,7 @@ function _makeStub($args)
 
     if (in_array($test_case, ['service_account_creds',
                               'compute_engine_creds', 'jwt_token_creds', ])) {
-        if ($test_case == 'jwt_token_creds') {
+        if ($test_case === 'jwt_token_creds') {
             $auth_credentials = ApplicationDefaultCredentials::getCredentials();
         } else {
             $auth_credentials = ApplicationDefaultCredentials::getCredentials(
@@ -558,7 +568,7 @@ function _makeStub($args)
         $opts['update_metadata'] = $auth_credentials->getUpdateMetadataFunc();
     }
 
-    if ($test_case == 'oauth2_auth_token') {
+    if ($test_case === 'oauth2_auth_token') {
         $auth_credentials = ApplicationDefaultCredentials::getCredentials(
             $args['oauth_scope']
         );
@@ -578,8 +588,9 @@ function _makeStub($args)
         $opts['update_metadata'] = $update_metadata;
     }
 
-    if ($test_case == 'unimplemented_method') {
-        $stub = new grpc\testing\UnimplementedServiceClient($server_address, $opts);
+    if ($test_case === 'unimplemented_method') {
+        $stub = new grpc\testing\UnimplementedServiceClient($server_address,
+                                                            $opts);
     } else {
         $stub = new grpc\testing\TestServiceClient($server_address, $opts);
     }
@@ -656,7 +667,8 @@ function interop_main($args, $stub = false)
     return $stub;
 }
 
-if (isset($_SERVER['PHP_SELF']) && preg_match('/interop_client/', $_SERVER['PHP_SELF'])) {
+if (isset($_SERVER['PHP_SELF']) &&
+    preg_match('/interop_client/', $_SERVER['PHP_SELF'])) {
     $args = getopt('', ['server_host:', 'server_port:', 'test_case:',
                         'use_tls::', 'use_test_ca::',
                         'server_host_override:', 'oauth_scope:',
diff --git a/src/php/tests/unit_tests/CallCredentials2Test.php b/src/php/tests/unit_tests/CallCredentials2Test.php
index b3b98a22cae8854e22933e54fcc3ea8ec4db5a73..fa31439c54373db9116ff75d55d05eb782515172 100644
--- a/src/php/tests/unit_tests/CallCredentials2Test.php
+++ b/src/php/tests/unit_tests/CallCredentials2Test.php
@@ -170,7 +170,7 @@ class CallCredentials2Test extends PHPUnit_Framework_TestCase
         $this->assertTrue(is_string($context->service_url));
         $this->assertTrue(is_string($context->method_name));
 
-        return "a string";
+        return 'a string';
     }
 
     public function testCallbackWithInvalidReturnValue()
@@ -196,5 +196,4 @@ class CallCredentials2Test extends PHPUnit_Framework_TestCase
         $this->assertTrue($event->send_close);
         $this->assertTrue($event->status->code == Grpc\STATUS_UNAUTHENTICATED);
     }
-
 }
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index faf3ab5f0d5d6810448e15f1fe3c9acc5c450e19..b9b662c032989346a17e291377409fd13689f9e4 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -1189,7 +1189,7 @@ def insecure_channel(target, options=None):
     A Channel to the target through which RPCs may be conducted.
   """
   from grpc import _channel
-  return _channel.Channel(target, options, None)
+  return _channel.Channel(target, () if options is None else options, None)
 
 
 def secure_channel(target, credentials, options=None):
@@ -1205,10 +1205,11 @@ def secure_channel(target, credentials, options=None):
     A Channel to the target through which RPCs may be conducted.
   """
   from grpc import _channel
-  return _channel.Channel(target, options, credentials._credentials)
+  return _channel.Channel(target, () if options is None else options,
+                          credentials._credentials)
 
 
-def server(thread_pool, handlers=None):
+def server(thread_pool, handlers=None, options=None):
   """Creates a Server with which RPCs can be serviced.
 
   Args:
@@ -1219,12 +1220,15 @@ def server(thread_pool, handlers=None):
       only handlers the server will use to service RPCs; other handlers may
       later be added by calling add_generic_rpc_handlers any time before the
       returned Server is started.
+    options: A sequence of string-value pairs according to which to configure
+      the created server.
 
   Returns:
     A Server with which RPCs can be serviced.
   """
   from grpc import _server
-  return _server.Server(thread_pool, () if handlers is None else handlers)
+  return _server.Server(thread_pool, () if handlers is None else handlers,
+                        () if options is None else options)
 
 
 ###################################  __all__  #################################
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 3117dd1cb3140ab731c84b8355b319741688a290..53a26727abed3f7c43612cc5fc097e08fea9ff2b 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -842,18 +842,8 @@ def _unsubscribe(state, callback):
 
 
 def _options(options):
-  if options is None:
-    pairs = ((cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT),)
-  else:
-    pairs = list(options) + [
-        (cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)]
-  encoded_pairs = [
-      (_common.encode(arg_name), arg_value) if isinstance(arg_value, int)
-      else (_common.encode(arg_name), _common.encode(arg_value))
-      for arg_name, arg_value in pairs]
-  return cygrpc.ChannelArgs([
-      cygrpc.ChannelArg(arg_name, arg_value)
-      for arg_name, arg_value in encoded_pairs])
+  return list(options) + [
+      (cygrpc.ChannelArgKey.primary_user_agent_string, _USER_AGENT)]
 
 
 class Channel(grpc.Channel):
@@ -867,7 +857,8 @@ class Channel(grpc.Channel):
       credentials: A cygrpc.ChannelCredentials or None.
     """
     self._channel = cygrpc.Channel(
-        _common.encode(target), _options(options), credentials)
+        _common.encode(target), _common.channel_args(_options(options)),
+        credentials)
     self._call_state = _ChannelCallState(self._channel)
     self._connectivity_state = _ChannelConnectivityState(self._channel)
 
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index 4d7d5214195eab43ec66f8c68f61851dbe8f04d0..cc0984c8c63b69176837ec5c9d6103d80c6019a5 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -94,6 +94,16 @@ def decode(b):
       return b.decode('latin1')
 
 
+def channel_args(options):
+  channel_args = []
+  for key, value in options:
+    if isinstance(value, six.string_types):
+      channel_args.append(cygrpc.ChannelArg(encode(key), encode(value)))
+    else:
+      channel_args.append(cygrpc.ChannelArg(encode(key), value))
+  return cygrpc.ChannelArgs(channel_args)
+
+
 def cygrpc_metadata(application_metadata):
   return _EMPTY_METADATA if application_metadata is None else cygrpc.Metadata(
       cygrpc.Metadatum(encode(key), encode(value))
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index 3df937eb14f192e7c70e5a110d503d4d42349269..73d1ff7b97d3bc382a8bb7fbf2fb604629bafd1a 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -32,15 +32,16 @@ cimport cpython
 
 cdef class Channel:
 
-  def __cinit__(self, bytes target, ChannelArgs arguments=None,
+  def __cinit__(self, bytes target, ChannelArgs arguments,
                 ChannelCredentials channel_credentials=None):
     grpc_init()
     cdef grpc_channel_args *c_arguments = NULL
     cdef char *c_target = NULL
     self.c_channel = NULL
     self.references = []
-    if arguments is not None:
+    if len(arguments) > 0:
       c_arguments = &arguments.c_args
+      self.references.append(arguments)
     c_target = target
     if channel_credentials is None:
       with nogil:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
index ca2b83111479442425979316b37934b406b0724e..18db38b68610c096e4c08326082770bc7b8f35d3 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi
@@ -34,12 +34,12 @@ import time
 
 cdef class Server:
 
-  def __cinit__(self, ChannelArgs arguments=None):
+  def __cinit__(self, ChannelArgs arguments):
     grpc_init()
     cdef grpc_channel_args *c_arguments = NULL
     self.references = []
     self.registered_completion_queues = []
-    if arguments is not None:
+    if len(arguments) > 0:
       c_arguments = &arguments.c_args
       self.references.append(arguments)
     with nogil:
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index 94a13bfb2fbf225c403e59ea9c1adc31de3bd391..5f846ce7732d6f7163179f11e893c9520f2f046a 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -728,12 +728,11 @@ def _start(state):
         cleanup_server, target=_serve, args=(state,))
     thread.start()
 
-
 class Server(grpc.Server):
 
-  def __init__(self, thread_pool, generic_handlers):
+  def __init__(self, thread_pool, generic_handlers, options):
     completion_queue = cygrpc.CompletionQueue()
-    server = cygrpc.Server()
+    server = cygrpc.Server(_common.channel_args(options))
     server.register_completion_queue(completion_queue)
     self._state = _ServerState(
         completion_queue, server, generic_handlers, thread_pool)
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 137177774b59b08e442e96cf6364111f9a31d800..ef9e85ccfb4e7dbcca463b1edc5bb06142e6f986 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -268,6 +268,7 @@ CORE_SOURCE_FILES = [
   'src/core/ext/census/operation.c',
   'src/core/ext/census/placeholders.c',
   'src/core/ext/census/resource.c',
+  'src/core/ext/census/trace_context.c',
   'src/core/ext/census/tracing.c',
   'src/core/plugin_registry/grpc_plugin_registry.c',
   'src/boringssl/err_data.c',
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index dcaef0db1fabb4c36bf996854b9817f30d2b987f..2071a33e13a6cbca7c3bcc15e0baac5465ec5fe0 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -7,6 +7,7 @@
   "_beta_features_test.BetaFeaturesTest", 
   "_beta_features_test.ContextManagementAndLifecycleTest", 
   "_cancel_many_calls_test.CancelManyCallsTest",
+  "_channel_args_test.ChannelArgsTest",
   "_channel_connectivity_test.ChannelConnectivityTest",
   "_channel_ready_future_test.ChannelReadyFutureTest",
   "_channel_test.ChannelTest", 
diff --git a/src/python/grpcio_tests/tests/unit/_channel_args_test.py b/src/python/grpcio_tests/tests/unit/_channel_args_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a636d79935b8e772946e2d17109680a1b37f426
--- /dev/null
+++ b/src/python/grpcio_tests/tests/unit/_channel_args_test.py
@@ -0,0 +1,53 @@
+# 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.
+
+"""Tests of Channel Args on client/server side."""
+
+import unittest
+
+import grpc
+
+TEST_CHANNEL_ARGS = (
+    ('arg1', b'bytes_val'),
+    ('arg2', 'str_val'),
+    ('arg3', 1),
+    (b'arg4', 'str_val'),
+)
+
+
+class ChannelArgsTest(unittest.TestCase):
+
+  def test_client(self):
+    grpc.insecure_channel('localhost:8080', options=TEST_CHANNEL_ARGS)
+
+  def test_server(self):
+    grpc.server(None, options=TEST_CHANNEL_ARGS)
+
+if __name__ == '__main__':
+  unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
index 9cae96a00d851ba530470675843be53cb8f5c16a..1324ad37b6d97d167b4b5ac69f6aa17cf2a7ade7 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_connectivity_test.py
@@ -78,7 +78,7 @@ class ChannelConnectivityTest(unittest.TestCase):
   def test_lonely_channel_connectivity(self):
     callback = _Callback()
 
-    channel = _channel.Channel('localhost:12345', None, None)
+    channel = _channel.Channel('localhost:12345', (), None)
     channel.subscribe(callback.update, try_to_connect=False)
     first_connectivities = callback.block_until_connectivities_satisfy(bool)
     channel.subscribe(callback.update, try_to_connect=True)
@@ -105,13 +105,13 @@ class ChannelConnectivityTest(unittest.TestCase):
 
   def test_immediately_connectable_channel_connectivity(self):
     thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
-    server = _server.Server(thread_pool, ())
+    server = _server.Server(thread_pool, (), ())
     port = server.add_insecure_port('[::]:0')
     server.start()
     first_callback = _Callback()
     second_callback = _Callback()
 
-    channel = _channel.Channel('localhost:{}'.format(port), None, None)
+    channel = _channel.Channel('localhost:{}'.format(port), (), None)
     channel.subscribe(first_callback.update, try_to_connect=False)
     first_connectivities = first_callback.block_until_connectivities_satisfy(
         bool)
@@ -146,12 +146,12 @@ class ChannelConnectivityTest(unittest.TestCase):
 
   def test_reachable_then_unreachable_channel_connectivity(self):
     thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
-    server = _server.Server(thread_pool, ())
+    server = _server.Server(thread_pool, (), ())
     port = server.add_insecure_port('[::]:0')
     server.start()
     callback = _Callback()
 
-    channel = _channel.Channel('localhost:{}'.format(port), None, None)
+    channel = _channel.Channel('localhost:{}'.format(port), (), None)
     channel.subscribe(callback.update, try_to_connect=True)
     callback.block_until_connectivities_satisfy(_ready_in_connectivities)
     # Now take down the server and confirm that channel readiness is repudiated.
diff --git a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
index 24f5b45b18e6512cb44daca5eefd537e5b609ade..60d478bcd9645afea766f3bcdfe3e326ebd5682b 100644
--- a/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
+++ b/src/python/grpcio_tests/tests/unit/_channel_ready_future_test.py
@@ -79,7 +79,7 @@ class ChannelReadyFutureTest(unittest.TestCase):
 
   def test_immediately_connectable_channel_connectivity(self):
     thread_pool = _thread_pool.RecordingThreadPool(max_workers=None)
-    server = _server.Server(thread_pool, ())
+    server = _server.Server(thread_pool, (), ())
     port = server.add_insecure_port('[::]:0')
     server.start()
     channel = grpc.insecure_channel('localhost:{}'.format(port))
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
index cf212c56539a9f69ae58b37c9d55ea1830e21d3e..20115fb22cb7bf774a6e14f8fcf0f7096fcf6a34 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
@@ -157,11 +157,12 @@ class CancelManyCallsTest(unittest.TestCase):
     server_thread_pool = logging_pool.pool(test_constants.THREAD_CONCURRENCY)
 
     server_completion_queue = cygrpc.CompletionQueue()
-    server = cygrpc.Server()
+    server = cygrpc.Server(cygrpc.ChannelArgs([]))
     server.register_completion_queue(server_completion_queue)
     port = server.add_http2_port(b'[::]:0')
     server.start()
-    channel = cygrpc.Channel('localhost:{}'.format(port).encode())
+    channel = cygrpc.Channel('localhost:{}'.format(port).encode(),
+                             cygrpc.ChannelArgs([]))
 
     state = _State()
 
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
index 152d8edde3b49aa438d04178ae7dac0d61307d91..2ae5285232c2061f2b21acba0478f28e2c014165 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
@@ -124,11 +124,12 @@ class ReadSomeButNotAllResponsesTest(unittest.TestCase):
 
   def testReadSomeButNotAllResponses(self):
     server_completion_queue = cygrpc.CompletionQueue()
-    server = cygrpc.Server()
+    server = cygrpc.Server(cygrpc.ChannelArgs([]))
     server.register_completion_queue(server_completion_queue)
     port = server.add_http2_port(b'[::]:0')
     server.start()
-    channel = cygrpc.Channel('localhost:{}'.format(port).encode())
+    channel = cygrpc.Channel('localhost:{}'.format(port).encode(),
+                             cygrpc.ChannelArgs([]))
 
     server_shutdown_tag = 'server_shutdown_tag'
     server_driver = _ServerDriver(server_completion_queue, server_shutdown_tag)
diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
index 142387d810ad73a4f5e8d3c739d8c6d6ec89aac1..8dedebfabeee7e9607852c7308ce2eb15426db60 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
@@ -121,7 +121,7 @@ class TypeSmokeTest(unittest.TestCase):
     del call_credentials
 
   def testServerStartNoExplicitShutdown(self):
-    server = cygrpc.Server()
+    server = cygrpc.Server(cygrpc.ChannelArgs([]))
     completion_queue = cygrpc.CompletionQueue()
     server.register_completion_queue(completion_queue)
     port = server.add_http2_port(b'[::]:0')
@@ -131,7 +131,7 @@ class TypeSmokeTest(unittest.TestCase):
 
   def testServerStartShutdown(self):
     completion_queue = cygrpc.CompletionQueue()
-    server = cygrpc.Server()
+    server = cygrpc.Server(cygrpc.ChannelArgs([]))
     server.add_http2_port(b'[::]:0')
     server.register_completion_queue(completion_queue)
     server.start()
@@ -148,7 +148,7 @@ class ServerClientMixin(object):
 
   def setUpMixin(self, server_credentials, client_credentials, host_override):
     self.server_completion_queue = cygrpc.CompletionQueue()
-    self.server = cygrpc.Server()
+    self.server = cygrpc.Server(cygrpc.ChannelArgs([]))
     self.server.register_completion_queue(self.server_completion_queue)
     if server_credentials:
       self.port = self.server.add_http2_port(b'[::]:0', server_credentials)
@@ -164,7 +164,8 @@ class ServerClientMixin(object):
           'localhost:{}'.format(self.port).encode(), client_channel_arguments,
           client_credentials)
     else:
-      self.client_channel = cygrpc.Channel('localhost:{}'.format(self.port).encode())
+      self.client_channel = cygrpc.Channel(
+          'localhost:{}'.format(self.port).encode(), cygrpc.ChannelArgs([]))
     if host_override:
       self.host_argument = None  # default host
       self.expected_host = host_override
diff --git a/test/core/census/data/context_empty.pb b/test/core/census/data/context_empty.pb
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/core/census/data/context_empty.txt b/test/core/census/data/context_empty.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/test/core/census/data/context_full.pb b/test/core/census/data/context_full.pb
new file mode 100644
index 0000000000000000000000000000000000000000..80ebcf280bc5a358d595eb88ff84420bcfe9d11e
Binary files /dev/null and b/test/core/census/data/context_full.pb differ
diff --git a/test/core/census/data/context_full.txt b/test/core/census/data/context_full.txt
new file mode 100644
index 0000000000000000000000000000000000000000..7901a10c33652293054c507dca9719bc0a537230
--- /dev/null
+++ b/test/core/census/data/context_full.txt
@@ -0,0 +1,3 @@
+trace_id { hi : 5; lo : 1 }
+span_id : 7
+is_sampled : true
diff --git a/test/core/census/data/context_no_sample.pb b/test/core/census/data/context_no_sample.pb
new file mode 100644
index 0000000000000000000000000000000000000000..ab7ad7d1091955636cfaa7e342d94497b717e55b
Binary files /dev/null and b/test/core/census/data/context_no_sample.pb differ
diff --git a/test/core/census/data/context_no_sample.txt b/test/core/census/data/context_no_sample.txt
new file mode 100644
index 0000000000000000000000000000000000000000..150298002fc2d0bbb4feaffde67606c2a865bbde
--- /dev/null
+++ b/test/core/census/data/context_no_sample.txt
@@ -0,0 +1,2 @@
+trace_id { hi : 5; lo : 1 }
+span_id : 7
diff --git a/test/core/census/data/context_span_only.pb b/test/core/census/data/context_span_only.pb
new file mode 100644
index 0000000000000000000000000000000000000000..2a9527a75a6ddb2ea7a17d096ad5c70615512819
Binary files /dev/null and b/test/core/census/data/context_span_only.pb differ
diff --git a/test/core/census/data/context_span_only.txt b/test/core/census/data/context_span_only.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d90de2e614b406844e15c0bc045e1b4e03ee7fde
--- /dev/null
+++ b/test/core/census/data/context_span_only.txt
@@ -0,0 +1,2 @@
+span_id : 7
+is_sampled : true
diff --git a/test/core/census/data/context_trace_only.pb b/test/core/census/data/context_trace_only.pb
new file mode 100644
index 0000000000000000000000000000000000000000..7fdf6f61a3f2e4b72edc05f23a0632043d4f6bcc
Binary files /dev/null and b/test/core/census/data/context_trace_only.pb differ
diff --git a/test/core/census/data/context_trace_only.txt b/test/core/census/data/context_trace_only.txt
new file mode 100644
index 0000000000000000000000000000000000000000..9b68a6aa9285a2072bbbc3326656fbb9ae93a9a6
--- /dev/null
+++ b/test/core/census/data/context_trace_only.txt
@@ -0,0 +1,2 @@
+trace_id { hi : 5; lo : 1 }
+is_sampled : true
diff --git a/test/core/census/trace_context_test.c b/test/core/census/trace_context_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee409e8d1a5a72ef8fb80765727835c2cd444aca
--- /dev/null
+++ b/test/core/census/trace_context_test.c
@@ -0,0 +1,231 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/census.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/useful.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "src/core/ext/census/base_resources.h"
+#include "src/core/ext/census/resource.h"
+#include "test/core/util/test_config.h"
+
+#include "src/core/ext/census/gen/trace_context.pb.h"
+#include "src/core/ext/census/trace_context.h"
+#include "third_party/nanopb/pb_decode.h"
+#include "third_party/nanopb/pb_encode.h"
+
+#define BUF_SIZE 256
+
+/* Encodes a TraceContext structure (ctxt1) to a buffer, and then decodes it
+to a second TraceContext (ctxt2).  Validates that the resulting TraceContext
+has a span_id, trace_id, and that the values are equal to those in initial
+TraceContext. On success, returns true.  If encode_trace_context returns 0,
+decode_trace_context fails, or the resulting TraceContext is missing a trace_id
+or span_id, it will return false. */
+bool validate_encode_decode_context(google_trace_TraceContext *ctxt1,
+                                    uint8_t *buffer, size_t buf_size) {
+  google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero;
+  size_t msg_length;
+  GPR_ASSERT(ctxt1->has_trace_id && ctxt1->has_span_id);
+
+  msg_length = encode_trace_context(ctxt1, buffer, buf_size);
+  if (msg_length == 0) {
+    return false;
+  }
+
+  if (!decode_trace_context(&ctxt2, buffer, msg_length)) {
+    return false;
+  }
+
+  if (!ctxt2.has_trace_id || !ctxt2.has_span_id) {
+    return false;
+  }
+
+  GPR_ASSERT(
+      ctxt1->trace_id.hi == ctxt2.trace_id.hi &&
+      ctxt1->trace_id.lo == ctxt2.trace_id.lo &&
+      ctxt1->span_id == ctxt2.span_id &&
+      ctxt1->has_is_sampled == ctxt2.has_is_sampled &&
+      (ctxt1->has_is_sampled ? ctxt1->is_sampled == ctxt2.is_sampled : true));
+
+  return true;
+}
+
+/* Decodes a proto-encoded TraceContext from a buffer.  If decode_trace_context
+fails or the resulting TraceContext is missing a trace_id or span_id it will
+return false, otherwise returns true. */
+bool validate_decode_context(google_trace_TraceContext *ctxt, uint8_t *buffer,
+                             size_t msg_length) {
+  // Validate the decoding of a context written to buffer.
+  if (!decode_trace_context(ctxt, buffer, msg_length)) {
+    return false;
+  }
+
+  if (!ctxt->has_trace_id || !ctxt->has_span_id) {
+    return false;
+  }
+
+  return true;
+}
+
+/* Read an encoded trace context from a file.  Validates that the decoding
+gives the expected result (succeed). */
+static void read_and_validate_context_from_file(google_trace_TraceContext *ctxt,
+                                                const char *file,
+                                                const bool succeed) {
+  uint8_t buffer[BUF_SIZE];
+  FILE *input = fopen(file, "rb");
+  GPR_ASSERT(input != NULL);
+  size_t nbytes = fread(buffer, 1, BUF_SIZE, input);
+  GPR_ASSERT(nbytes <= BUF_SIZE && feof(input) && !ferror(input));
+  bool res = validate_decode_context(ctxt, buffer, nbytes);
+  GPR_ASSERT(res == succeed);
+  GPR_ASSERT(fclose(input) == 0);
+}
+
+// Test full proto-buffer.
+static void test_full() {
+  google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
+  read_and_validate_context_from_file(
+      &ctxt, "test/core/census/data/context_full.pb", true);
+}
+
+// Test empty proto-buffer.
+static void test_empty() {
+  google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
+  read_and_validate_context_from_file(
+      &ctxt, "test/core/census/data/context_empty.pb", false);
+}
+
+// Test proto-buffer with only trace_id.
+static void test_trace_only() {
+  google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
+  read_and_validate_context_from_file(
+      &ctxt, "test/core/census/data/context_trace_only.pb", false);
+}
+
+// Test proto-buffer with only span_id.
+static void test_span_only() {
+  google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
+  read_and_validate_context_from_file(
+      &ctxt, "test/core/census/data/context_span_only.pb", false);
+}
+
+// Test proto-buffer without is_sampled value.
+static void test_no_sample() {
+  google_trace_TraceContext ctxt = google_trace_TraceContext_init_zero;
+  read_and_validate_context_from_file(
+      &ctxt, "test/core/census/data/context_no_sample.pb", true);
+  GPR_ASSERT(ctxt.has_is_sampled == false && ctxt.is_sampled == false);
+}
+
+static void test_encode_decode() {
+  uint8_t buffer[BUF_SIZE] = {0};
+
+  google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
+  ctxt1.has_trace_id = true;
+  ctxt1.trace_id.has_hi = true;
+  ctxt1.trace_id.has_lo = true;
+  ctxt1.trace_id.lo = 1;
+  ctxt1.trace_id.hi = 2;
+  ctxt1.has_span_id = true;
+  ctxt1.span_id = 3;
+  validate_encode_decode_context(&ctxt1, buffer, sizeof(buffer));
+
+  google_trace_TraceContext ctxt2 = google_trace_TraceContext_init_zero;
+  ctxt2.has_trace_id = true;
+  ctxt2.trace_id.has_hi = false;
+  ctxt2.trace_id.has_lo = false;
+  ctxt2.has_span_id = true;
+  validate_encode_decode_context(&ctxt2, buffer, sizeof(buffer));
+}
+
+// Test a corrupted proto-buffer.
+static void test_corrupt() {
+  uint8_t buffer[BUF_SIZE] = {0};
+  google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
+  size_t msg_length;
+
+  ctxt1.has_trace_id = true;
+  ctxt1.trace_id.has_hi = true;
+  ctxt1.trace_id.has_lo = true;
+  ctxt1.trace_id.lo = 1;
+  ctxt1.trace_id.hi = 2;
+  ctxt1.has_span_id = true;
+  ctxt1.span_id = 3;
+  ctxt1.is_sampled = true;
+  msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer));
+
+  /* Corrupt some bytes.  255 (0xFF) should be illegal for the first byte of the
+  proto encoded object. */
+  buffer[0] = 255;
+
+  bool res = validate_decode_context(&ctxt1, buffer, msg_length);
+  GPR_ASSERT(res == false);
+}
+
+static void test_buffer_size() {
+  // This buffer is too small, so the encode should fail.
+  uint8_t buffer[16] = {0};
+  google_trace_TraceContext ctxt1 = google_trace_TraceContext_init_zero;
+  size_t msg_length;
+
+  ctxt1.has_trace_id = true;
+  ctxt1.trace_id.has_hi = true;
+  ctxt1.trace_id.has_lo = true;
+  ctxt1.trace_id.lo = 1;
+  ctxt1.trace_id.hi = 2;
+  ctxt1.has_span_id = true;
+  ctxt1.span_id = 3;
+  ctxt1.is_sampled = true;
+  msg_length = encode_trace_context(&ctxt1, buffer, sizeof(buffer));
+
+  GPR_ASSERT(msg_length == 0);
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  test_full();
+  test_empty();
+  test_trace_only();
+  test_span_only();
+  test_encode_decode();
+  test_corrupt();
+  test_no_sample();
+  test_buffer_size();
+
+  return 0;
+}
diff --git a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
index 6a33525f629be4aa804a3f382980af67d59d684a..d3b961959d2700eff4b7f4c3aaf5f3c1d62d0b02 100644
--- a/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_config/resolvers/dns_resolver_connectivity_test.c
@@ -41,29 +41,6 @@
 #include "src/core/lib/iomgr/timer.h"
 #include "test/core/util/test_config.h"
 
-static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
-static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                         grpc_client_channel_factory *scv) {}
-static grpc_subchannel *client_channel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
-    grpc_subchannel_args *args) {
-  return NULL;
-}
-
-static grpc_channel *client_channel_factory_create_channel(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
-    const char *target, grpc_client_channel_type type,
-    grpc_channel_args *args) {
-  GPR_UNREACHABLE_CODE(return NULL);
-}
-
-static const grpc_client_channel_factory_vtable sc_vtable = {
-    client_channel_factory_ref, client_channel_factory_unref,
-    client_channel_factory_create_subchannel,
-    client_channel_factory_create_channel};
-
-static grpc_client_channel_factory cc_factory = {&sc_vtable};
-
 static gpr_mu g_mu;
 static bool g_fail_resolution = true;
 
@@ -92,7 +69,6 @@ static grpc_resolver *create_resolver(const char *name) {
   grpc_resolver_args args;
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.client_channel_factory = &cc_factory;
   grpc_resolver *resolver =
       grpc_resolver_factory_create_resolver(factory, &args);
   grpc_resolver_factory_unref(factory);
diff --git a/test/core/client_config/resolvers/dns_resolver_test.c b/test/core/client_config/resolvers/dns_resolver_test.c
index 21dc99cadd8f7274f8f693fbaf5e158ce189ce46..c3f4cb1244417ed6bd3dc3b58220d71e57d93333 100644
--- a/test/core/client_config/resolvers/dns_resolver_test.c
+++ b/test/core/client_config/resolvers/dns_resolver_test.c
@@ -38,29 +38,6 @@
 #include "src/core/ext/client_config/resolver_registry.h"
 #include "test/core/util/test_config.h"
 
-static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
-static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                         grpc_client_channel_factory *scv) {}
-static grpc_subchannel *client_channel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
-    grpc_subchannel_args *args) {
-  GPR_UNREACHABLE_CODE(return NULL);
-}
-
-static grpc_channel *client_channel_factory_create_channel(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
-    const char *target, grpc_client_channel_type type,
-    grpc_channel_args *args) {
-  GPR_UNREACHABLE_CODE(return NULL);
-}
-
-static const grpc_client_channel_factory_vtable sc_vtable = {
-    client_channel_factory_ref, client_channel_factory_unref,
-    client_channel_factory_create_subchannel,
-    client_channel_factory_create_channel};
-
-static grpc_client_channel_factory cc_factory = {&sc_vtable};
-
 static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_uri *uri = grpc_uri_parse(string, 0);
@@ -71,7 +48,6 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.client_channel_factory = &cc_factory;
   resolver = grpc_resolver_factory_create_resolver(factory, &args);
   GPR_ASSERT(resolver != NULL);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
diff --git a/test/core/client_config/resolvers/sockaddr_resolver_test.c b/test/core/client_config/resolvers/sockaddr_resolver_test.c
index b11546b6b1cb18d6eaf8d3cb262e48ac88ee48c5..d8430d39c4c745653cbbbce8d471dbcd3ed50224 100644
--- a/test/core/client_config/resolvers/sockaddr_resolver_test.c
+++ b/test/core/client_config/resolvers/sockaddr_resolver_test.c
@@ -38,29 +38,6 @@
 #include "src/core/ext/client_config/resolver_registry.h"
 #include "test/core/util/test_config.h"
 
-static void client_channel_factory_ref(grpc_client_channel_factory *scv) {}
-static void client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
-                                         grpc_client_channel_factory *scv) {}
-static grpc_subchannel *client_channel_factory_create_subchannel(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
-    grpc_subchannel_args *args) {
-  GPR_UNREACHABLE_CODE(return NULL);
-}
-
-static grpc_channel *client_channel_factory_create_channel(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
-    const char *target, grpc_client_channel_type type,
-    grpc_channel_args *args) {
-  GPR_UNREACHABLE_CODE(return NULL);
-}
-
-static const grpc_client_channel_factory_vtable sc_vtable = {
-    client_channel_factory_ref, client_channel_factory_unref,
-    client_channel_factory_create_subchannel,
-    client_channel_factory_create_channel};
-
-static grpc_client_channel_factory cc_factory = {&sc_vtable};
-
 static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   grpc_uri *uri = grpc_uri_parse(string, 0);
@@ -71,7 +48,6 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
   GPR_ASSERT(uri);
   memset(&args, 0, sizeof(args));
   args.uri = uri;
-  args.client_channel_factory = &cc_factory;
   resolver = grpc_resolver_factory_create_resolver(factory, &args);
   GPR_ASSERT(resolver != NULL);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test_succeeds");
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index c74af115d463b405cc016b947d5dc688eb117acc..c047d615aa5b149c9ec50ea53cf63d0796a748e1 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -948,6 +948,7 @@ src/core/ext/census/grpc_filter.h \
 src/core/ext/census/mlog.h \
 src/core/ext/census/resource.h \
 src/core/ext/census/rpc_metric_id.h \
+src/core/ext/census/trace_context.h \
 src/core/lib/surface/init.c \
 src/core/lib/channel/channel_args.c \
 src/core/lib/channel/channel_stack.c \
@@ -1139,6 +1140,7 @@ src/core/ext/census/mlog.c \
 src/core/ext/census/operation.c \
 src/core/ext/census/placeholders.c \
 src/core/ext/census/resource.c \
+src/core/ext/census/trace_context.c \
 src/core/ext/census/tracing.c \
 src/core/plugin_registry/grpc_plugin_registry.c \
 include/grpc/support/alloc.h \
diff --git a/tools/run_tests/run_build_statistics.py b/tools/run_tests/run_build_statistics.py
index 89aad2a39919fb46c0843227b44dd79d34d13cc6..9c17cd1db9188914a7b655c45348ff846d7eeda3 100755
--- a/tools/run_tests/run_build_statistics.py
+++ b/tools/run_tests/run_build_statistics.py
@@ -63,6 +63,8 @@ _URL_BASE = 'https://grpc-testing.appspot.com/job'
 _KNOWN_ERRORS = [
     'Failed to build workspace Tests with scheme AllTests',
     'Build timed out',
+    'TIMEOUT: tools/run_tests/pre_build_node.sh',
+    'TIMEOUT: tools/run_tests/pre_build_ruby.sh',
     'FATAL: Unable to produce a script file',
     'FAILED: build_docker_c\+\+',
     'cannot find package \"cloud.google.com/go/compute/metadata\"',
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index c579f14f91d16829a8c9b2b04d6460e51a0667c8..19931246ccff754f85f5347691b9716673571b7a 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -1198,18 +1198,6 @@ def _shut_down_legacy_server(legacy_server_port):
         'http://localhost:%d/quitquitquit' % legacy_server_port).read()
 
 
-def _shut_down_legacy_server(legacy_server_port):
-  try:
-    version = int(urllib2.urlopen(
-        'http://localhost:%d/version_number' % legacy_server_port,
-        timeout=10).read())
-  except:
-    pass
-  else:
-    urllib2.urlopen(
-        'http://localhost:%d/quitquitquit' % legacy_server_port).read()
-
-
 def _start_port_server(port_server_port):
   # check if a compatible port server is running
   # if incompatible (version mismatch) ==> start a new one
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 469f0d04cc2b86804b9d4c76c2b9c4b7aa7f14f2..d603813fbc69246030aef48420d412b6829e4f89 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -156,6 +156,22 @@
     "third_party": false, 
     "type": "target"
   }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "census_trace_context_test", 
+    "src": [
+      "test/core/census/trace_context_test.c"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
   {
     "deps": [
       "gpr", 
@@ -5695,7 +5711,8 @@
       "src/core/ext/census/grpc_filter.h", 
       "src/core/ext/census/mlog.h", 
       "src/core/ext/census/resource.h", 
-      "src/core/ext/census/rpc_metric_id.h"
+      "src/core/ext/census/rpc_metric_id.h", 
+      "src/core/ext/census/trace_context.h"
     ], 
     "language": "c", 
     "name": "census", 
@@ -5723,6 +5740,8 @@
       "src/core/ext/census/resource.c", 
       "src/core/ext/census/resource.h", 
       "src/core/ext/census/rpc_metric_id.h", 
+      "src/core/ext/census/trace_context.c", 
+      "src/core/ext/census/trace_context.h", 
       "src/core/ext/census/tracing.c"
     ], 
     "third_party": false, 
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index f9300c1ff9403de6243d88cd93d407a73cdd5f4a..3e3bfd503ee4c2ed2e8704d8fb951745e65389ec 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -190,6 +190,27 @@
       "windows"
     ]
   }, 
+  {
+    "args": [], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c", 
+    "name": "census_trace_context_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "args": [], 
     "ci_platforms": [
diff --git a/vsprojects/buildtests_c.sln b/vsprojects/buildtests_c.sln
index 04f487689ca5cb6477dc5d5df8d54c8bf2e60823..c46e86d78bf0d416120a3f545737fb2cdcbc02e4 100644
--- a/vsprojects/buildtests_c.sln
+++ b/vsprojects/buildtests_c.sln
@@ -120,6 +120,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_resource_test", "vcx
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "census_trace_context_test", "vcxproj\test\census_trace_context_test\census_trace_context_test.vcxproj", "{14511310-FAE4-C287-31DC-D6F456D10AF3}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "channel_create_test", "vcxproj\test\channel_create_test\channel_create_test.vcxproj", "{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -1660,6 +1671,22 @@ Global
 		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|Win32.Build.0 = Release|Win32
 		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|x64.ActiveCfg = Release|x64
 		{18CF99B5-3C61-EC3D-9509-3C95334C3B88}.Release-DLL|x64.Build.0 = Release|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|Win32.ActiveCfg = Debug|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|x64.ActiveCfg = Debug|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|Win32.ActiveCfg = Release|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|x64.ActiveCfg = Release|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|Win32.Build.0 = Debug|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug|x64.Build.0 = Debug|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|Win32.Build.0 = Release|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release|x64.Build.0 = Release|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Debug-DLL|x64.Build.0 = Debug|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|Win32.Build.0 = Release|Win32
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|x64.ActiveCfg = Release|x64
+		{14511310-FAE4-C287-31DC-D6F456D10AF3}.Release-DLL|x64.Build.0 = Release|x64
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|Win32.ActiveCfg = Debug|Win32
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Debug|x64.ActiveCfg = Debug|x64
 		{AFC88484-3A2E-32BC-25B2-23DF741D4F3D}.Release|Win32.ActiveCfg = Release|Win32
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index a83b4f52668f39c0965452b7deb57a9f6b649de4..8c835ec50c14a93fd7af593e35bad50bd3de16fe 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -457,6 +457,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
@@ -841,6 +842,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\trace_context.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_plugin_registry.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index c15366b5dd1fd8f73d7714730dcc5bcab49d40d4..20ad9356f5814c1e521fd937ce72d477a8467b06 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -574,6 +574,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\trace_context.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
@@ -1148,6 +1151,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index c34d4bc5ea7db4826a48bfd37b0a956cf2aae2ac..aca6e5279d6e3b376f59b259a45d54dfe144aba3 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -423,6 +423,7 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\mlog.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\resource.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h" />
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="$(SolutionDir)\..\src\core\lib\surface\init.c">
@@ -749,6 +750,8 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\trace_context.c">
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\plugin_registry\grpc_unsecure_plugin_registry.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 6f8d1f69613b43c5afb48725bd2b6c30b9c00048..9d1a33c47c5f9be9229549683b8b3d782f080d8c 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -487,6 +487,9 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\resource.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
+    <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\trace_context.c">
+      <Filter>src\core\ext\census</Filter>
+    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\census\tracing.c">
       <Filter>src\core\ext\census</Filter>
     </ClCompile>
@@ -986,6 +989,9 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\rpc_metric_id.h">
       <Filter>src\core\ext\census</Filter>
     </ClInclude>
+    <ClInclude Include="$(SolutionDir)\..\src\core\ext\census\trace_context.h">
+      <Filter>src\core\ext\census</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj
new file mode 100644
index 0000000000000000000000000000000000000000..f0c76e7f04c4d9877c5f68c2992b18594c21f543
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\1.0.204.1.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{14511310-FAE4-C287-31DC-D6F456D10AF3}</ProjectGuid>
+    <IgnoreWarnIntDirInTempDetected>true</IgnoreWarnIntDirInTempDetected>
+    <IntDir>$(SolutionDir)IntDir\$(MSBuildProjectName)\</IntDir>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '14.0'" Label="Configuration">
+    <PlatformToolset>v140</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="$(SolutionDir)\..\vsprojects\global.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\openssl.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\winsock.props" />
+    <Import Project="$(SolutionDir)\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>census_trace_context_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>census_trace_context_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Release</Configuration-grpc_dependencies_zlib>
+    <Linkage-grpc_dependencies_openssl>static</Linkage-grpc_dependencies_openssl>
+    <Configuration-grpc_dependencies_openssl>Release</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+    <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+      <MinimalRebuild Condition="$(Jenkins)">false</MinimalRebuild>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\census\trace_context_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="$(SolutionDir)\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets" Condition="Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.10\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.10\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.204.1\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\..\vsprojects\packages\grpc.dependencies.openssl.1.0.204.1\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+
diff --git a/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters
new file mode 100644
index 0000000000000000000000000000000000000000..1aafe06ff0448fadc834218f8e8853601d63b754
--- /dev/null
+++ b/vsprojects/vcxproj/test/census_trace_context_test/census_trace_context_test.vcxproj.filters
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="$(SolutionDir)\..\test\core\census\trace_context_test.c">
+      <Filter>test\core\census</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{ceb3b75d-b5bc-0966-6724-06fb51237d08}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{8d294ce5-d65c-2fef-28ab-43b4d23722c3}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\census">
+      <UniqueIdentifier>{3981af30-20c0-647e-755f-fa184674d50a}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+