Refactoring channel API.

Client:
* New ManagedChannel abstract class.
* Adding ping to Channel.
* Moving builders and implementations to internal.

Server:
* Added lifecycle management API to Server (mirroring ManagedChannel).
* Moved ServerImpl, AbstractServerBuilder and handler registries to internal.
* New ServerBuilder abstract class (mirroring ManagedChannelBuilder).

Fixes #545
diff --git a/benchmarks/src/jmh/java/io/grpc/benchmarks/TransportBenchmark.java b/benchmarks/src/jmh/java/io/grpc/benchmarks/TransportBenchmark.java
index a822128..39bf08e 100644
--- a/benchmarks/src/jmh/java/io/grpc/benchmarks/TransportBenchmark.java
+++ b/benchmarks/src/jmh/java/io/grpc/benchmarks/TransportBenchmark.java
@@ -36,13 +36,13 @@
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.protobuf.ByteString;
 
-import io.grpc.AbstractChannelBuilder;
-import io.grpc.AbstractServerBuilder;
-import io.grpc.ChannelImpl;
-import io.grpc.ServerImpl;
+import io.grpc.ManagedChannel;
+import io.grpc.Server;
 import io.grpc.benchmarks.qps.AsyncServer;
 import io.grpc.inprocess.InProcessChannelBuilder;
 import io.grpc.inprocess.InProcessServerBuilder;
+import io.grpc.internal.AbstractManagedChannelImplBuilder;
+import io.grpc.internal.AbstractServerImplBuilder;
 import io.grpc.netty.NegotiationType;
 import io.grpc.netty.NettyChannelBuilder;
 import io.grpc.netty.NettyServerBuilder;
@@ -80,14 +80,14 @@
   @Param({"true", "false"})
   public boolean direct;
 
-  private ChannelImpl channel;
-  private ServerImpl server;
+  private ManagedChannel channel;
+  private Server server;
   private TestServiceGrpc.TestServiceBlockingStub stub;
 
   @Setup
   public void setUp() throws Exception {
-    AbstractServerBuilder serverBuilder;
-    AbstractChannelBuilder channelBuilder;
+    AbstractServerImplBuilder serverBuilder;
+    AbstractManagedChannelImplBuilder channelBuilder;
     switch (transport) {
       case INPROCESS:
       {
diff --git a/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/AbstractBenchmark.java b/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/AbstractBenchmark.java
index 6b95f4b..db7a973 100644
--- a/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/AbstractBenchmark.java
+++ b/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/AbstractBenchmark.java
@@ -3,16 +3,16 @@
 import com.google.common.util.concurrent.MoreExecutors;
 
 import io.grpc.CallOptions;
-import io.grpc.ChannelImpl;
 import io.grpc.ClientCall;
 import io.grpc.Drainable;
 import io.grpc.KnownLength;
+import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
 import io.grpc.MethodDescriptor.MethodType;
+import io.grpc.Server;
 import io.grpc.ServerCall;
 import io.grpc.ServerCallHandler;
-import io.grpc.ServerImpl;
 import io.grpc.ServerServiceDefinition;
 import io.grpc.Status;
 import io.grpc.netty.NegotiationType;
@@ -155,13 +155,13 @@
   }
 
 
-  protected ServerImpl server;
+  protected Server server;
   protected ByteBuf request;
   protected ByteBuf response;
   protected MethodDescriptor<ByteBuf, ByteBuf> unaryMethod;
   private MethodDescriptor<ByteBuf, ByteBuf> pingPongMethod;
   private MethodDescriptor<ByteBuf, ByteBuf> flowControlledStreaming;
-  protected ChannelImpl[] channels;
+  protected ManagedChannel[] channels;
 
   public AbstractBenchmark() {
   }
@@ -350,7 +350,7 @@
     // Build and start the clients and servers
     server = serverBuilder.build();
     server.start();
-    channels = new ChannelImpl[channelCount];
+    channels = new ManagedChannel[channelCount];
     for (int i = 0; i < channelCount; i++) {
       // Use a dedicated event-loop for each channel
       channels[i] = channelBuilder
@@ -368,7 +368,7 @@
                                  final AtomicLong counter,
                                  final AtomicBoolean done,
                                  final long counterDelta) {
-    for (final ChannelImpl channel : channels) {
+    for (final ManagedChannel channel : channels) {
       for (int i = 0; i < callsPerChannel; i++) {
         StreamObserver<ByteBuf> observer = new StreamObserver<ByteBuf>() {
           @Override
@@ -404,7 +404,7 @@
                                      final AtomicLong counter,
                                      final AtomicBoolean done,
                                      final long counterDelta) {
-    for (final ChannelImpl channel : channels) {
+    for (final ManagedChannel channel : channels) {
       for (int i = 0; i < callsPerChannel; i++) {
         final ClientCall<ByteBuf, ByteBuf> streamingCall =
             channel.newCall(pingPongMethod, CALL_OPTIONS);
@@ -447,7 +447,7 @@
                                                    final AtomicLong counter,
                                                    final AtomicBoolean done,
                                                    final long counterDelta) {
-    for (final ChannelImpl channel : channels) {
+    for (final ManagedChannel channel : channels) {
       for (int i = 0; i < callsPerChannel; i++) {
         final ClientCall<ByteBuf, ByteBuf> streamingCall =
             channel.newCall(flowControlledStreaming, CALL_OPTIONS);
@@ -483,7 +483,7 @@
    * Shutdown all the client channels and then shutdown the server.
    */
   protected void teardown() throws Exception {
-    for (ChannelImpl channel : channels) {
+    for (ManagedChannel channel : channels) {
       channel.shutdown();
     }
     server.shutdown().awaitTermination(5, TimeUnit.SECONDS);
diff --git a/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/HandlerRegistryBenchmark.java b/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/HandlerRegistryBenchmark.java
index 9ac534b..68351c0 100644
--- a/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/HandlerRegistryBenchmark.java
+++ b/benchmarks/src/jmh/java/io/grpc/benchmarks/netty/HandlerRegistryBenchmark.java
@@ -50,7 +50,7 @@
 import java.util.Random;
 
 /**
- * Benchmark for {@link io.grpc.MutableHandlerRegistryImpl}.
+ * Benchmark for {@link MutableHandlerRegistryImpl}.
  */
 @State(Scope.Benchmark)
 @Fork(1)
@@ -94,7 +94,7 @@
   }
 
   /**
-   * Benchmark the {@link io.grpc.HandlerRegistry#lookupMethod(String)} throughput.
+   * Benchmark the {@link MutableHandlerRegistryImpl#lookupMethod(String)} throughput.
    */
   @Benchmark
   public void lookupMethod(Blackhole bh) {
diff --git a/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncClient.java b/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncClient.java
index 4588e7e..4e2e821 100644
--- a/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncClient.java
+++ b/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncClient.java
@@ -55,7 +55,7 @@
 import com.google.protobuf.ByteString;
 
 import io.grpc.Channel;
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.Status;
 import io.grpc.stub.StreamObserver;
 import io.grpc.testing.Payload;
@@ -96,7 +96,7 @@
 
     SimpleRequest req = newRequest();
 
-    List<Channel> channels = new ArrayList<Channel>(config.channels);
+    List<ManagedChannel> channels = new ArrayList<ManagedChannel>(config.channels);
     for (int i = 0; i < config.channels; i++) {
       channels.add(newClientChannel(config));
     }
@@ -130,7 +130,7 @@
             .build();
   }
 
-  private void warmup(SimpleRequest req, List<Channel> channels) throws Exception {
+  private void warmup(SimpleRequest req, List<? extends Channel> channels) throws Exception {
     long endTime = System.nanoTime() + TimeUnit.SECONDS.toNanos(config.warmupDuration);
     doBenchmark(req, channels, endTime);
     // I don't know if this helps, but it doesn't hurt trying. We sometimes run warmups
@@ -140,7 +140,8 @@
   }
 
   private List<Histogram> doBenchmark(SimpleRequest req,
-                                      List<Channel> channels, long endTime) throws Exception {
+                                      List<? extends Channel> channels,
+                                      long endTime) throws Exception {
     // Initiate the concurrent calls
     List<Future<Histogram>> futures =
         new ArrayList<Future<Histogram>>(config.outstandingRpcsPerChannel);
@@ -314,9 +315,9 @@
     System.out.println(values);
   }
 
-  private static void shutdown(List<Channel> channels) {
-    for (Channel channel : channels) {
-      ((ChannelImpl) channel).shutdown();
+  private static void shutdown(List<ManagedChannel> channels) {
+    for (ManagedChannel channel : channels) {
+      channel.shutdown();
     }
   }
 
diff --git a/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncServer.java b/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncServer.java
index 857de41..0bc3bdb 100644
--- a/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncServer.java
+++ b/benchmarks/src/main/java/io/grpc/benchmarks/qps/AsyncServer.java
@@ -34,7 +34,7 @@
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.protobuf.ByteString;
 
-import io.grpc.ServerImpl;
+import io.grpc.Server;
 import io.grpc.Status;
 import io.grpc.netty.GrpcSslContexts;
 import io.grpc.netty.NettyServerBuilder;
@@ -81,7 +81,7 @@
       return;
     }
 
-    final ServerImpl server = newServer(config);
+    final Server server = newServer(config);
     server.start();
 
     System.out.println("QPS Server started on " + config.address);
@@ -100,7 +100,7 @@
     });
   }
 
-  static ServerImpl newServer(ServerConfiguration config) throws IOException {
+  static Server newServer(ServerConfiguration config) throws IOException {
     SslContext sslContext = null;
     if (config.tls) {
       System.out.println("Using fake CA for TLS certificate.\n"
diff --git a/benchmarks/src/main/java/io/grpc/benchmarks/qps/OpenLoopClient.java b/benchmarks/src/main/java/io/grpc/benchmarks/qps/OpenLoopClient.java
index 2f65fac..ad29a4b 100644
--- a/benchmarks/src/main/java/io/grpc/benchmarks/qps/OpenLoopClient.java
+++ b/benchmarks/src/main/java/io/grpc/benchmarks/qps/OpenLoopClient.java
@@ -50,7 +50,7 @@
 import static io.grpc.benchmarks.qps.Utils.saveHistogram;
 
 import io.grpc.Channel;
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.Status;
 import io.grpc.stub.StreamObserver;
 import io.grpc.testing.SimpleRequest;
@@ -108,7 +108,7 @@
     }
     config.channels = 1;
     config.directExecutor = true;
-    Channel ch = newClientChannel(config);
+    ManagedChannel ch = newClientChannel(config);
     SimpleRequest req = newRequest(config);
     LoadGenerationWorker worker =
         new LoadGenerationWorker(ch, req, config.targetQps, config.duration);
@@ -119,7 +119,7 @@
     if (config.histogramFile != null) {
       saveHistogram(histogram, config.histogramFile);
     }
-    ((ChannelImpl) ch).shutdown();
+    ch.shutdown();
   }
 
   private void printStats(Histogram histogram, long elapsedTime) {
diff --git a/benchmarks/src/main/java/io/grpc/benchmarks/qps/Utils.java b/benchmarks/src/main/java/io/grpc/benchmarks/qps/Utils.java
index 8daeae5..100a68e 100644
--- a/benchmarks/src/main/java/io/grpc/benchmarks/qps/Utils.java
+++ b/benchmarks/src/main/java/io/grpc/benchmarks/qps/Utils.java
@@ -34,7 +34,7 @@
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.protobuf.ByteString;
 
-import io.grpc.Channel;
+import io.grpc.ManagedChannel;
 import io.grpc.netty.GrpcSslContexts;
 import io.grpc.netty.NegotiationType;
 import io.grpc.netty.NettyChannelBuilder;
@@ -128,7 +128,7 @@
         .build();
   }
 
-  static Channel newClientChannel(ClientConfiguration config) throws IOException {
+  static ManagedChannel newClientChannel(ClientConfiguration config) throws IOException {
     if (config.transport == ClientConfiguration.Transport.OK_HTTP) {
       InetSocketAddress addr = (InetSocketAddress) config.address;
       OkHttpChannelBuilder builder = OkHttpChannelBuilder
diff --git a/core/src/main/java/io/grpc/HandlerRegistry.java b/core/src/main/java/io/grpc/HandlerRegistry.java
index e50966b..f7a79db 100644
--- a/core/src/main/java/io/grpc/HandlerRegistry.java
+++ b/core/src/main/java/io/grpc/HandlerRegistry.java
@@ -38,6 +38,7 @@
  * Registry of services and their methods used by servers to dispatching incoming calls.
  */
 @ThreadSafe
+@ExperimentalApi("https://github.com/grpc/grpc-java/issues/933")
 public abstract class HandlerRegistry {
 
   /**
diff --git a/core/src/main/java/io/grpc/ManagedChannel.java b/core/src/main/java/io/grpc/ManagedChannel.java
new file mode 100644
index 0000000..af234ee
--- /dev/null
+++ b/core/src/main/java/io/grpc/ManagedChannel.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package io.grpc;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A {@link Channel} that provides lifecycle management.
+ */
+public abstract class ManagedChannel extends Channel {
+  /**
+   * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
+   * cancelled.
+   */
+  public abstract ManagedChannel shutdown();
+
+  /**
+   * Returns whether the channel is shutdown. Shutdown channels immediately cancel any new calls,
+   * but may still have some calls being processed.
+   *
+   * @see #shutdown()
+   * @see #isTerminated()
+   */
+  public abstract boolean isShutdown();
+
+  /**
+   * Returns whether the channel is terminated. Terminated channels have no running calls and
+   * relevant resources released (like TCP connections).
+   *
+   * @see #isShutdown()
+   */
+  public abstract boolean isTerminated();
+
+  /**
+   * Initiates a forceful shutdown in which preexisting and new calls are cancelled. Although
+   * forceful, the shutdown process is still not instantaneous; {@link #isTerminated()} will likely
+   * return {@code false} immediately after this method returns.
+   */
+  public abstract ManagedChannel shutdownNow();
+
+  /**
+   * Waits for the channel to become terminated, giving up if the timeout is reached.
+   *
+   * @return whether the channel is terminated, as would be done by {@link #isTerminated()}.
+   */
+  public abstract boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
+}
diff --git a/core/src/main/java/io/grpc/ManagedChannelBuilder.java b/core/src/main/java/io/grpc/ManagedChannelBuilder.java
new file mode 100644
index 0000000..18f3809
--- /dev/null
+++ b/core/src/main/java/io/grpc/ManagedChannelBuilder.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package io.grpc;
+
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * A builder for {@link ManagedChannel} instances.
+ *
+ * @param <T> The concrete type of this builder.
+ */
+public abstract class ManagedChannelBuilder<T extends ManagedChannelBuilder<T>> {
+
+  /**
+   * Provides a custom executor.
+   *
+   * <p>It's an optional parameter. If the user has not provided an executor when the channel is
+   * built, the builder will use a static cached thread pool.
+   *
+   * <p>The channel won't take ownership of the given executor. It's caller's responsibility to
+   * shut down the executor when it's desired.
+   */
+  public abstract T executor(ExecutorService executor);
+
+  /**
+   * Adds interceptors that will be called before the channel performs its real work. This is
+   * functionally equivalent to using {@link ClientInterceptors#intercept(Channel, List)}, but while
+   * still having access to the original {@code ChannelImpl}.
+   */
+  public abstract T intercept(List<ClientInterceptor> interceptors);
+
+  /**
+   * Builds a channel using the given parameters.
+   */
+  public abstract ManagedChannel build();
+}
diff --git a/core/src/main/java/io/grpc/MutableHandlerRegistry.java b/core/src/main/java/io/grpc/MutableHandlerRegistry.java
index ccfa53f..5b6dcc7 100644
--- a/core/src/main/java/io/grpc/MutableHandlerRegistry.java
+++ b/core/src/main/java/io/grpc/MutableHandlerRegistry.java
@@ -41,6 +41,7 @@
  * @see MutableHandlerRegistryImpl
  */
 @ThreadSafe
+@ExperimentalApi("https://github.com/grpc/grpc-java/issues/933")
 public abstract class MutableHandlerRegistry extends HandlerRegistry {
   /**
    * Returns {@code null}, or previous service if {@code service} replaced an existing service.
@@ -51,6 +52,5 @@
   /**
    * Returns {@code false} if {@code service} was not registered.
    */
-  @Nullable
   public abstract boolean removeService(ServerServiceDefinition service);
 }
diff --git a/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java b/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java
index 62868c3..78bc8f0 100644
--- a/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java
+++ b/core/src/main/java/io/grpc/MutableHandlerRegistryImpl.java
@@ -44,6 +44,7 @@
  * blocking method lookup.
  */
 @ThreadSafe
+@ExperimentalApi("https://github.com/grpc/grpc-java/issues/933")
 public final class MutableHandlerRegistryImpl extends MutableHandlerRegistry {
   private final ConcurrentMap<String, ServerServiceDefinition> services
       = new ConcurrentHashMap<String, ServerServiceDefinition>();
diff --git a/core/src/main/java/io/grpc/Server.java b/core/src/main/java/io/grpc/Server.java
index 92e35be..417feb9 100644
--- a/core/src/main/java/io/grpc/Server.java
+++ b/core/src/main/java/io/grpc/Server.java
@@ -31,6 +31,9 @@
 
 package io.grpc;
 
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
 import javax.annotation.concurrent.ThreadSafe;
 
 /**
@@ -38,4 +41,54 @@
  * application code or interceptors.
  */
 @ThreadSafe
-public abstract class Server {}
+public abstract class Server {
+  /**
+   * Bind and start the server.
+   *
+   * @return {@code this} object
+   * @throws IllegalStateException if already started
+   * @throws IOException if unable to bind
+   */
+  public abstract Server start() throws IOException;
+
+  /**
+   * Initiates an orderly shutdown in which preexisting calls continue but new calls are rejected.
+   */
+  public abstract Server shutdown();
+
+  /**
+   * Initiates a forceful shutdown in which preexisting and new calls are rejected. Although
+   * forceful, the shutdown process is still not instantaneous; {@link #isTerminated()} will likely
+   * return {@code false} immediately after this method returns.
+   */
+  public abstract Server shutdownNow();
+
+  /**
+   * Returns whether the server is shutdown. Shutdown servers reject any new calls, but may still
+   * have some calls being processed.
+   *
+   * @see #shutdown()
+   * @see #isTerminated()
+   */
+  public abstract boolean isShutdown();
+
+  /**
+   * Returns whether the server is terminated. Terminated servers have no running calls and
+   * relevant resources released (like TCP connections).
+   *
+   * @see #isShutdown()
+   */
+  public abstract boolean isTerminated();
+
+  /**
+   * Waits for the server to become terminated, giving up if the timeout is reached.
+   *
+   * @return whether the server is terminated, as would be done by {@link #isTerminated()}.
+   */
+  public abstract boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
+
+  /**
+   * Waits for the server to become terminated.
+   */
+  public abstract void awaitTermination() throws InterruptedException;
+}
diff --git a/core/src/main/java/io/grpc/ServerBuilder.java b/core/src/main/java/io/grpc/ServerBuilder.java
new file mode 100644
index 0000000..a8e2902
--- /dev/null
+++ b/core/src/main/java/io/grpc/ServerBuilder.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package io.grpc;
+
+import java.util.concurrent.ExecutorService;
+
+import javax.annotation.Nullable;
+
+/**
+ * A builder for {@link Server} instances.
+ *
+ * @param <T> The concrete type of this builder.
+ */
+public abstract class ServerBuilder<T extends ServerBuilder<T>> {
+  /**
+   * Provides a custom executor.
+   *
+   * <p>It's an optional parameter. If the user has not provided an executor when the server is
+   * built, the builder will use a static cached thread pool.
+   *
+   * <p>The server won't take ownership of the given executor. It's caller's responsibility to
+   * shut down the executor when it's desired.
+   */
+  public abstract T executor(@Nullable ExecutorService executor);
+
+  /**
+   * Adds a service implementation to the handler registry.
+   *
+   * @throws UnsupportedOperationException if this builder does not support dynamically adding
+   *                                       services.
+   */
+  public abstract T addService(ServerServiceDefinition service);
+
+  /**
+   * Builds a server using the given parameters.
+   *
+   * <p>The returned service will not been started or be bound a port. You will need to start it
+   * with {@link Server#start()}.
+   */
+  public abstract Server build();
+}
diff --git a/core/src/main/java/io/grpc/ServerMethodDefinition.java b/core/src/main/java/io/grpc/ServerMethodDefinition.java
index 66fe12a..c419a53 100644
--- a/core/src/main/java/io/grpc/ServerMethodDefinition.java
+++ b/core/src/main/java/io/grpc/ServerMethodDefinition.java
@@ -32,8 +32,7 @@
 package io.grpc;
 
 /**
- * Definition of a method bound by a {@link io.grpc.HandlerRegistry} and exposed
- * by a {@link Server}.
+ * Definition of a method exposed by a {@link Server}.
  */
 public final class ServerMethodDefinition<RequestT, ResponseT> {
   private final MethodDescriptor<RequestT, ResponseT> method;
diff --git a/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java b/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java
index 33ef76c..729294f 100644
--- a/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java
+++ b/core/src/main/java/io/grpc/inprocess/InProcessChannelBuilder.java
@@ -33,7 +33,8 @@
 
 import com.google.common.base.Preconditions;
 
-import io.grpc.AbstractChannelBuilder;
+import io.grpc.ExperimentalApi;
+import io.grpc.internal.AbstractManagedChannelImplBuilder;
 import io.grpc.internal.AbstractReferenceCounted;
 import io.grpc.internal.ClientTransport;
 import io.grpc.internal.ClientTransportFactory;
@@ -44,7 +45,9 @@
  *
  * <p>The channel is intended to be fully-featured, high performance, and useful in testing.
  */
-public class InProcessChannelBuilder extends AbstractChannelBuilder<InProcessChannelBuilder> {
+@ExperimentalApi("There is no plan to make this API stable.")
+public class InProcessChannelBuilder extends
+        AbstractManagedChannelImplBuilder<InProcessChannelBuilder> {
   /**
    * Create a channel builder that will connect to the server with the given name.
    *
diff --git a/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java b/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java
index 6536753..ddf9754 100644
--- a/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java
+++ b/core/src/main/java/io/grpc/inprocess/InProcessServerBuilder.java
@@ -33,8 +33,9 @@
 
 import com.google.common.base.Preconditions;
 
-import io.grpc.AbstractServerBuilder;
+import io.grpc.ExperimentalApi;
 import io.grpc.HandlerRegistry;
+import io.grpc.internal.AbstractServerImplBuilder;
 
 /**
  * Builder for a server that services in-process requests. Clients identify the in-process server by
@@ -42,7 +43,9 @@
  *
  * <p>The server is intended to be fully-featured, high performance, and useful in testing.
  */
-public final class InProcessServerBuilder extends AbstractServerBuilder<InProcessServerBuilder> {
+@ExperimentalApi("There is no plan to make this API stable.")
+public final class InProcessServerBuilder
+        extends AbstractServerImplBuilder<InProcessServerBuilder> {
   /**
    * Create a server builder that will bind with the given name.
    *
diff --git a/core/src/main/java/io/grpc/AbstractChannelBuilder.java b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
similarity index 77%
rename from core/src/main/java/io/grpc/AbstractChannelBuilder.java
rename to core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
index 2d286a3..e9992b2 100644
--- a/core/src/main/java/io/grpc/AbstractChannelBuilder.java
+++ b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
@@ -29,9 +29,11 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
-import io.grpc.internal.ClientTransportFactory;
+import io.grpc.ClientInterceptor;
+import io.grpc.Internal;
+import io.grpc.ManagedChannelBuilder;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -43,9 +45,10 @@
 /**
  * The base class for channel builders.
  *
- * @param <BuilderT> The concrete type of this builder.
+ * @param <T> The concrete type of this builder.
  */
-public abstract class AbstractChannelBuilder<BuilderT extends AbstractChannelBuilder<BuilderT>> {
+public abstract class AbstractManagedChannelImplBuilder
+        <T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {
 
   @Nullable
   private ExecutorService executor;
@@ -63,33 +66,33 @@
    * <p>The channel won't take ownership of the given executor. It's caller's responsibility to
    * shut down the executor when it's desired.
    */
-  public final BuilderT executor(ExecutorService executor) {
+  public final T executor(ExecutorService executor) {
     this.executor = executor;
     return thisT();
   }
 
   /**
    * Adds interceptors that will be called before the channel performs its real work. This is
-   * functionally equivalent to using {@link ClientInterceptors#intercept(Channel, List)}, but while
-   * still having access to the original {@code ChannelImpl}.
+   * functionally equivalent to using {@link io.grpc.ClientInterceptors#intercept(io.grpc.Channel,
+   * List)}, but while still having access to the original {@code ChannelImpl}.
    */
-  public final BuilderT intercept(List<ClientInterceptor> interceptors) {
+  public final T intercept(List<ClientInterceptor> interceptors) {
     this.interceptors.addAll(interceptors);
     return thisT();
   }
 
   /**
    * Adds interceptors that will be called before the channel performs its real work. This is
-   * functionally equivalent to using {@link ClientInterceptors#intercept(Channel,
+   * functionally equivalent to using {@link io.grpc.ClientInterceptors#intercept(io.grpc.Channel,
    * ClientInterceptor...)}, but while still having access to the original {@code ChannelImpl}.
    */
-  public final BuilderT intercept(ClientInterceptor... interceptors) {
+  public final T intercept(ClientInterceptor... interceptors) {
     return intercept(Arrays.asList(interceptors));
   }
 
-  private BuilderT thisT() {
+  private T thisT() {
     @SuppressWarnings("unchecked")
-    BuilderT thisT = (BuilderT) this;
+    T thisT = (T) this;
     return thisT;
   }
 
@@ -99,18 +102,17 @@
    * <p>It's an optional parameter. If provided, the given agent will be prepended by the
    * grpc {@code User-Agent}.
    */
-  @SuppressWarnings("unchecked")
-  public final BuilderT userAgent(String userAgent) {
+  public final T userAgent(String userAgent) {
     this.userAgent = userAgent;
-    return (BuilderT) this;
+    return thisT();
   }
 
   /**
    * Builds a channel using the given parameters.
    */
-  public ChannelImpl build() {
+  public ManagedChannelImpl build() {
     ClientTransportFactory transportFactory = buildTransportFactory();
-    return new ChannelImpl(transportFactory, executor, userAgent, interceptors);
+    return new ManagedChannelImpl(transportFactory, executor, userAgent, interceptors);
   }
 
   /**
diff --git a/core/src/main/java/io/grpc/AbstractServerBuilder.java b/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java
similarity index 73%
rename from core/src/main/java/io/grpc/AbstractServerBuilder.java
rename to core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java
index 80248a1..d224912 100644
--- a/core/src/main/java/io/grpc/AbstractServerBuilder.java
+++ b/core/src/main/java/io/grpc/internal/AbstractServerImplBuilder.java
@@ -29,10 +29,17 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import com.google.common.base.Preconditions;
 
+import io.grpc.HandlerRegistry;
+import io.grpc.Internal;
+import io.grpc.MutableHandlerRegistry;
+import io.grpc.MutableHandlerRegistryImpl;
+import io.grpc.ServerBuilder;
+import io.grpc.ServerServiceDefinition;
+
 import java.util.concurrent.ExecutorService;
 
 import javax.annotation.Nullable;
@@ -40,9 +47,10 @@
 /**
  * The base class for server builders.
  *
- * @param <BuilderT> The concrete type for this builder.
+ * @param <T> The concrete type for this builder.
  */
-public abstract class AbstractServerBuilder<BuilderT extends AbstractServerBuilder<BuilderT>> {
+public abstract class AbstractServerImplBuilder<T extends AbstractServerImplBuilder<T>>
+        extends ServerBuilder<T> {
 
   private final HandlerRegistry registry;
   @Nullable
@@ -51,30 +59,21 @@
   /**
    * Constructs using a given handler registry.
    */
-  protected AbstractServerBuilder(HandlerRegistry registry) {
+  protected AbstractServerImplBuilder(HandlerRegistry registry) {
     this.registry = Preconditions.checkNotNull(registry);
   }
 
   /**
    * Constructs with a MutableHandlerRegistry created internally.
    */
-  protected AbstractServerBuilder() {
+  protected AbstractServerImplBuilder() {
     this.registry = new MutableHandlerRegistryImpl();
   }
 
-  /**
-   * Provides a custom executor.
-   *
-   * <p>It's an optional parameter. If the user has not provided an executor when the server is
-   * built, the builder will use a static cached thread pool.
-   *
-   * <p>The server won't take ownership of the given executor. It's caller's responsibility to
-   * shut down the executor when it's desired.
-   */
-  @SuppressWarnings("unchecked")
-  public final BuilderT executor(ExecutorService executor) {
+  @Override
+  public final T executor(@Nullable ExecutorService executor) {
     this.executor = executor;
-    return (BuilderT) this;
+    return thisT();
   }
 
   /**
@@ -83,21 +82,16 @@
    * <p>This is supported only if the user didn't provide a handler registry, or the provided one is
    * a {@link MutableHandlerRegistry}. Otherwise it throws an UnsupportedOperationException.
    */
-  @SuppressWarnings("unchecked")
-  public final BuilderT addService(ServerServiceDefinition service) {
+  @Override
+  public final T addService(ServerServiceDefinition service) {
     if (registry instanceof MutableHandlerRegistry) {
       ((MutableHandlerRegistry) registry).addService(service);
-      return (BuilderT) this;
+      return thisT();
     }
     throw new UnsupportedOperationException("Underlying HandlerRegistry is not mutable");
   }
 
-  /**
-   * Builds a server using the given parameters.
-   *
-   * <p>The returned service will not been started or be bound a port. You will need to start it
-   * with {@link ServerImpl#start()}.
-   */
+  @Override
   public ServerImpl build() {
     io.grpc.internal.Server transportServer = buildTransportServer();
     return new ServerImpl(executor, registry, transportServer);
@@ -110,4 +104,10 @@
    */
   @Internal
   protected abstract io.grpc.internal.Server buildTransportServer();
+
+  private T thisT() {
+    @SuppressWarnings("unchecked")
+    T thisT = (T) this;
+    return thisT;
+  }
 }
diff --git a/core/src/main/java/io/grpc/BackoffPolicy.java b/core/src/main/java/io/grpc/internal/BackoffPolicy.java
similarity index 98%
rename from core/src/main/java/io/grpc/BackoffPolicy.java
rename to core/src/main/java/io/grpc/internal/BackoffPolicy.java
index 2f24f87..1a2bc37 100644
--- a/core/src/main/java/io/grpc/BackoffPolicy.java
+++ b/core/src/main/java/io/grpc/internal/BackoffPolicy.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 /**
  * Determines how long to wait before doing some action (typically a retry, or a reconnect).
diff --git a/core/src/main/java/io/grpc/ClientCallImpl.java b/core/src/main/java/io/grpc/internal/ClientCallImpl.java
similarity index 98%
rename from core/src/main/java/io/grpc/ClientCallImpl.java
rename to core/src/main/java/io/grpc/internal/ClientCallImpl.java
index 345751e..d346c84 100644
--- a/core/src/main/java/io/grpc/ClientCallImpl.java
+++ b/core/src/main/java/io/grpc/internal/ClientCallImpl.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static io.grpc.internal.GrpcUtil.AUTHORITY_KEY;
 import static io.grpc.internal.GrpcUtil.MESSAGE_ENCODING_KEY;
@@ -39,12 +39,14 @@
 import com.google.common.base.Preconditions;
 import com.google.common.base.Throwables;
 
+import io.grpc.CallOptions;
+import io.grpc.ClientCall;
+import io.grpc.MessageEncoding;
 import io.grpc.MessageEncoding.Compressor;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
 import io.grpc.MethodDescriptor.MethodType;
-import io.grpc.internal.ClientStream;
-import io.grpc.internal.ClientStreamListener;
-import io.grpc.internal.ClientTransport;
-import io.grpc.internal.SerializingExecutor;
+import io.grpc.Status;
 
 import java.io.InputStream;
 import java.util.concurrent.ScheduledExecutorService;
diff --git a/core/src/main/java/io/grpc/ExponentialBackoffPolicy.java b/core/src/main/java/io/grpc/internal/ExponentialBackoffPolicy.java
similarity index 99%
rename from core/src/main/java/io/grpc/ExponentialBackoffPolicy.java
rename to core/src/main/java/io/grpc/internal/ExponentialBackoffPolicy.java
index e22082d..8d3191f 100644
--- a/core/src/main/java/io/grpc/ExponentialBackoffPolicy.java
+++ b/core/src/main/java/io/grpc/internal/ExponentialBackoffPolicy.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java
index 46677c0..734f368 100644
--- a/core/src/main/java/io/grpc/internal/GrpcUtil.java
+++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java
@@ -36,13 +36,16 @@
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
 
 import io.grpc.Metadata;
 import io.grpc.Status;
+import io.grpc.internal.SharedResourceHolder.Resource;
 
 import java.net.HttpURLConnection;
 import java.util.EnumSet;
 import java.util.Set;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
@@ -294,10 +297,33 @@
   }
 
   /**
+   * Shared executor for channels.
+   */
+  static final Resource<ExecutorService> SHARED_CHANNEL_EXECUTOR =
+      new Resource<ExecutorService>() {
+        private static final String name = "grpc-default-executor";
+        @Override
+        public ExecutorService create() {
+          return Executors.newCachedThreadPool(new ThreadFactoryBuilder()
+              .setNameFormat(name + "-%d").build());
+        }
+
+        @Override
+        public void close(ExecutorService instance) {
+          instance.shutdown();
+        }
+
+        @Override
+        public String toString() {
+          return name;
+        }
+      };
+
+  /**
    * Shared executor for managing channel timers.
    */
-  public static final SharedResourceHolder.Resource<ScheduledExecutorService> TIMER_SERVICE =
-      new SharedResourceHolder.Resource<ScheduledExecutorService>() {
+  public static final Resource<ScheduledExecutorService> TIMER_SERVICE =
+      new Resource<ScheduledExecutorService>() {
         @Override
         public ScheduledExecutorService create() {
           return Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
diff --git a/core/src/main/java/io/grpc/ChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
similarity index 85%
rename from core/src/main/java/io/grpc/ChannelImpl.java
rename to core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
index f2cf2d0..d2f5669 100644
--- a/core/src/main/java/io/grpc/ChannelImpl.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -29,29 +29,30 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static io.grpc.internal.GrpcUtil.TIMER_SERVICE;
 
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
-
-import io.grpc.ClientCallImpl.ClientTransportProvider;
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.ClientInterceptors;
+import io.grpc.ExperimentalApi;
+import io.grpc.ManagedChannel;
+import io.grpc.MessageEncoding;
 import io.grpc.MessageEncoding.Compressor;
-import io.grpc.internal.ClientStream;
-import io.grpc.internal.ClientStreamListener;
-import io.grpc.internal.ClientTransport;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import io.grpc.Status;
+import io.grpc.internal.ClientCallImpl.ClientTransportProvider;
 import io.grpc.internal.ClientTransport.PingCallback;
-import io.grpc.internal.ClientTransportFactory;
-import io.grpc.internal.SerializingExecutor;
-import io.grpc.internal.SharedResourceHolder;
-import io.grpc.internal.SharedResourceHolder.Resource;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Logger;
@@ -62,28 +63,8 @@
 
 /** A communication channel for making outgoing RPCs. */
 @ThreadSafe
-public final class ChannelImpl extends Channel {
-  private static final Logger log = Logger.getLogger(ChannelImpl.class.getName());
-
-  static final Resource<ExecutorService> SHARED_EXECUTOR =
-      new Resource<ExecutorService>() {
-        private static final String name = "grpc-default-executor";
-        @Override
-        public ExecutorService create() {
-          return Executors.newCachedThreadPool(new ThreadFactoryBuilder()
-              .setNameFormat(name + "-%d").build());
-        }
-
-        @Override
-        public void close(ExecutorService instance) {
-          instance.shutdown();
-        }
-
-        @Override
-        public String toString() {
-          return name;
-        }
-      };
+public final class ManagedChannelImpl extends ManagedChannel {
+  private static final Logger log = Logger.getLogger(ManagedChannelImpl.class.getName());
 
   private final ClientTransportFactory transportFactory;
   private final ExecutorService executor;
@@ -133,7 +114,7 @@
     }
   };
 
-  ChannelImpl(ClientTransportFactory transportFactory, @Nullable ExecutorService executor,
+  ManagedChannelImpl(ClientTransportFactory transportFactory, @Nullable ExecutorService executor,
       @Nullable String userAgent, List<ClientInterceptor> interceptors) {
     this.transportFactory = transportFactory;
     this.userAgent = userAgent;
@@ -142,7 +123,7 @@
 
     if (executor == null) {
       usingSharedExecutor = true;
-      this.executor = SharedResourceHolder.get(SHARED_EXECUTOR);
+      this.executor = SharedResourceHolder.get(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
     } else {
       usingSharedExecutor = false;
       this.executor = executor;
@@ -167,7 +148,8 @@
    * Initiates an orderly shutdown in which preexisting calls continue but new calls are immediately
    * cancelled.
    */
-  public ChannelImpl shutdown() {
+  @Override
+  public ManagedChannelImpl shutdown() {
     ClientTransport savedActiveTransport;
     synchronized (lock) {
       if (shutdown) {
@@ -199,29 +181,20 @@
    * <p>NOT YET IMPLEMENTED. This method currently behaves identically to shutdown().
    */
   // TODO(ejona86): cancel preexisting calls.
-  public ChannelImpl shutdownNow() {
+  @Override
+  public ManagedChannelImpl shutdownNow() {
     shutdown();
     return this;
   }
 
-  /**
-   * Returns whether the channel is shutdown. Shutdown channels immediately cancel any new calls,
-   * but may still have some calls being processed.
-   *
-   * @see #shutdown()
-   * @see #isTerminated()
-   */
+  @Override
   public boolean isShutdown() {
     synchronized (lock) {
       return shutdown;
     }
   }
 
-  /**
-   * Waits for the channel to become terminated, giving up if the timeout is reached.
-   *
-   * @return whether the channel is terminated, as would be done by {@link #isTerminated()}.
-   */
+  @Override
   public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
     synchronized (lock) {
       long timeoutNanos = unit.toNanos(timeout);
@@ -233,12 +206,7 @@
     }
   }
 
-  /**
-   * Returns whether the channel is terminated. Terminated channels have no running calls and
-   * relevant resources released (like TCP connections).
-   *
-   * @see #isShutdown()
-   */
+  @Override
   public boolean isTerminated() {
     synchronized (lock) {
       return terminated;
@@ -250,13 +218,12 @@
    * is received, the given callback will be invoked using the given executor.
    *
    * <p>If the underlying transport has no mechanism by when to send a ping, this method may throw
-   * an {@link UnsupportedOperationException}. The operation may
-   * {@linkplain PingCallback#pingFailed(Throwable) fail} due to transient transport errors. In
-   * that case, trying again may succeed.
+   * an {@link UnsupportedOperationException}. The operation may {@linkplain
+   * io.grpc.internal.ClientTransport.PingCallback#pingFailed(Throwable) fail} due to transient
+   * transport errors. In that case, trying again may succeed.
    *
-   * @see ClientTransport#ping(PingCallback, Executor)
+   * @see ClientTransport#ping(ClientTransport.PingCallback, Executor)
    */
-  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/737")
   public void ping(final PingCallback callback, final Executor executor) {
     try {
       obtainActiveTransport().ping(callback, executor);
@@ -420,7 +387,7 @@
    */
   private void onChannelTerminated() {
     if (usingSharedExecutor) {
-      SharedResourceHolder.release(SHARED_EXECUTOR, executor);
+      SharedResourceHolder.release(GrpcUtil.SHARED_CHANNEL_EXECUTOR, executor);
     }
     // Release the transport factory so that it can deallocate any resources.
     transportFactory.release();
diff --git a/core/src/main/java/io/grpc/ServerImpl.java b/core/src/main/java/io/grpc/internal/ServerImpl.java
similarity index 91%
rename from core/src/main/java/io/grpc/ServerImpl.java
rename to core/src/main/java/io/grpc/internal/ServerImpl.java
index be7ef7d..2cda167 100644
--- a/core/src/main/java/io/grpc/ServerImpl.java
+++ b/core/src/main/java/io/grpc/internal/ServerImpl.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static io.grpc.internal.GrpcUtil.TIMEOUT_KEY;
 import static io.grpc.internal.GrpcUtil.TIMER_SERVICE;
@@ -38,13 +38,12 @@
 import com.google.common.base.Throwables;
 import com.google.common.util.concurrent.Futures;
 
-import io.grpc.internal.SerializingExecutor;
-import io.grpc.internal.ServerListener;
-import io.grpc.internal.ServerStream;
-import io.grpc.internal.ServerStreamListener;
-import io.grpc.internal.ServerTransport;
-import io.grpc.internal.ServerTransportListener;
-import io.grpc.internal.SharedResourceHolder;
+import io.grpc.HandlerRegistry;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import io.grpc.ServerCall;
+import io.grpc.ServerMethodDefinition;
+import io.grpc.Status;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -58,7 +57,7 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Default implementation of {@link Server}, for creation by transports.
+ * Default implementation of {@link io.grpc.Server}, for creation by transports.
  *
  * <p>Expected usage (by a theoretical TCP transport):
  * <pre><code>public class TcpTransportServerFactory {
@@ -71,7 +70,7 @@
  * <p>Starting the server starts the underlying transport for servicing requests. Stopping the
  * server stops servicing new requests and waits for all connections to terminate.
  */
-public final class ServerImpl extends Server {
+public final class ServerImpl extends io.grpc.Server {
   private static final ServerStreamListener NOOP_LISTENER = new NoopListener();
 
   private static final Future<?> DEFAULT_TIMEOUT_FUTURE = Futures.immediateCancelledFuture();
@@ -112,6 +111,7 @@
    * @throws IllegalStateException if already started
    * @throws IOException if unable to bind
    */
+  @Override
   public ServerImpl start() throws IOException {
     synchronized (lock) {
       if (started) {
@@ -119,7 +119,7 @@
       }
       usingSharedExecutor = executor == null;
       if (usingSharedExecutor) {
-        executor = SharedResourceHolder.get(ChannelImpl.SHARED_EXECUTOR);
+        executor = SharedResourceHolder.get(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
       }
       // Start and wait for any port to actually be bound.
       transportServer.start(new ServerListenerImpl());
@@ -131,6 +131,7 @@
   /**
    * Initiates an orderly shutdown in which preexisting calls continue but new calls are rejected.
    */
+  @Override
   public ServerImpl shutdown() {
     boolean shutdownTransportServer;
     synchronized (lock) {
@@ -149,42 +150,29 @@
     }
     SharedResourceHolder.release(TIMER_SERVICE, timeoutService);
     if (usingSharedExecutor) {
-      SharedResourceHolder.release(ChannelImpl.SHARED_EXECUTOR, (ExecutorService) executor);
+      SharedResourceHolder.release(GrpcUtil.SHARED_CHANNEL_EXECUTOR, (ExecutorService) executor);
     }
     return this;
   }
 
   /**
-   * Initiates a forceful shutdown in which preexisting and new calls are rejected. Although
-   * forceful, the shutdown process is still not instantaneous; {@link #isTerminated()} will likely
-   * return {@code false} immediately after this method returns.
-   *
-   * <p>NOT YET IMPLEMENTED. This method currently behaves identically to shutdown().
+   * NOT YET IMPLEMENTED. This method currently behaves identically to shutdown().
    */
   // TODO(ejona86): cancel preexisting calls.
+  @Override
   public ServerImpl shutdownNow() {
     shutdown();
     return this;
   }
 
-  /**
-   * Returns whether the server is shutdown. Shutdown servers reject any new calls, but may still
-   * have some calls being processed.
-   *
-   * @see #shutdown()
-   * @see #isTerminated()
-   */
+  @Override
   public boolean isShutdown() {
     synchronized (lock) {
       return shutdown;
     }
   }
 
-  /**
-   * Waits for the server to become terminated, giving up if the timeout is reached.
-   *
-   * @return whether the server is terminated, as would be done by {@link #isTerminated()}.
-   */
+  @Override
   public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
     synchronized (lock) {
       long timeoutNanos = unit.toNanos(timeout);
@@ -196,9 +184,7 @@
     }
   }
 
-  /**
-   * Waits for the server to become terminated.
-   */
+  @Override
   public void awaitTermination() throws InterruptedException {
     synchronized (lock) {
       while (!terminated) {
@@ -207,12 +193,7 @@
     }
   }
 
-  /**
-   * Returns whether the server is terminated. Terminated servers have no running calls and
-   * relevant resources released (like TCP connections).
-   *
-   * @see #isShutdown()
-   */
+  @Override
   public boolean isTerminated() {
     synchronized (lock) {
       return terminated;
diff --git a/core/src/test/java/io/grpc/IntegerMarshaller.java b/core/src/test/java/io/grpc/IntegerMarshaller.java
index 2930adc..b1e428c 100644
--- a/core/src/test/java/io/grpc/IntegerMarshaller.java
+++ b/core/src/test/java/io/grpc/IntegerMarshaller.java
@@ -34,7 +34,7 @@
 import java.io.InputStream;
 
 /** Marshalls decimal-encoded integers. */
-class IntegerMarshaller implements MethodDescriptor.Marshaller<Integer> {
+public class IntegerMarshaller implements MethodDescriptor.Marshaller<Integer> {
   public static IntegerMarshaller INSTANCE = new IntegerMarshaller();
 
   @Override
diff --git a/core/src/test/java/io/grpc/StringMarshaller.java b/core/src/test/java/io/grpc/StringMarshaller.java
index 2c0116b..c485a4d 100644
--- a/core/src/test/java/io/grpc/StringMarshaller.java
+++ b/core/src/test/java/io/grpc/StringMarshaller.java
@@ -40,7 +40,7 @@
 import java.io.InputStream;
 
 /** Marshalls UTF-8 encoded strings. */
-class StringMarshaller implements MethodDescriptor.Marshaller<String> {
+public class StringMarshaller implements MethodDescriptor.Marshaller<String> {
   public static StringMarshaller INSTANCE = new StringMarshaller();
 
   @Override
diff --git a/core/src/test/java/io/grpc/ExponentialBackoffPolicyTest.java b/core/src/test/java/io/grpc/internal/ExponentialBackoffPolicyTest.java
similarity index 98%
rename from core/src/test/java/io/grpc/ExponentialBackoffPolicyTest.java
rename to core/src/test/java/io/grpc/internal/ExponentialBackoffPolicyTest.java
index f26f023..af58032 100644
--- a/core/src/test/java/io/grpc/ExponentialBackoffPolicyTest.java
+++ b/core/src/test/java/io/grpc/internal/ExponentialBackoffPolicyTest.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
diff --git a/core/src/test/java/io/grpc/ChannelImplTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
similarity index 95%
rename from core/src/test/java/io/grpc/ChannelImplTest.java
rename to core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
index b613eb3..ada39c9 100644
--- a/core/src/test/java/io/grpc/ChannelImplTest.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -47,10 +47,16 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
-import io.grpc.internal.ClientStream;
-import io.grpc.internal.ClientStreamListener;
-import io.grpc.internal.ClientTransport;
-import io.grpc.internal.ClientTransportFactory;
+import io.grpc.CallOptions;
+import io.grpc.Channel;
+import io.grpc.ClientCall;
+import io.grpc.ClientInterceptor;
+import io.grpc.IntegerMarshaller;
+import io.grpc.ManagedChannel;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import io.grpc.Status;
+import io.grpc.StringMarshaller;
 
 import org.junit.After;
 import org.junit.Before;
@@ -70,9 +76,9 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicLong;
 
-/** Unit tests for {@link ChannelImpl}. */
+/** Unit tests for {@link ManagedChannelImpl}. */
 @RunWith(JUnit4.class)
-public class ChannelImplTest {
+public class ManagedChannelImplTest {
   private MethodDescriptor<String, Integer> method = MethodDescriptor.create(
       MethodDescriptor.MethodType.UNKNOWN, "/service/method",
       new StringMarshaller(), new IntegerMarshaller());
@@ -82,7 +88,7 @@
   private ClientTransport mockTransport;
   @Mock
   private ClientTransportFactory mockTransportFactory;
-  private ChannelImpl channel;
+  private ManagedChannel channel;
 
   @Mock
   private ClientCall.Listener<Integer> mockCallListener;
@@ -99,7 +105,7 @@
   @Before
   public void setUp() {
     MockitoAnnotations.initMocks(this);
-    channel = new ChannelImpl(mockTransportFactory, executor, null,
+    channel = new ManagedChannelImpl(mockTransportFactory, executor, null,
         Collections.<ClientInterceptor>emptyList());
     when(mockTransportFactory.newClientTransport()).thenReturn(mockTransport);
   }
@@ -280,7 +286,8 @@
         return next.newCall(method, callOptions);
       }
     };
-    channel = new ChannelImpl(mockTransportFactory, executor, null, Arrays.asList(interceptor));
+    channel = new ManagedChannelImpl(mockTransportFactory, executor, null,
+            Arrays.asList(interceptor));
     assertNotNull(channel.newCall(method, CallOptions.DEFAULT));
     assertEquals(1, atomic.get());
   }
diff --git a/core/src/test/java/io/grpc/ServerImplTest.java b/core/src/test/java/io/grpc/internal/ServerImplTest.java
similarity index 97%
rename from core/src/test/java/io/grpc/ServerImplTest.java
rename to core/src/test/java/io/grpc/internal/ServerImplTest.java
index 4861715..20d76e4 100644
--- a/core/src/test/java/io/grpc/ServerImplTest.java
+++ b/core/src/test/java/io/grpc/internal/ServerImplTest.java
@@ -29,7 +29,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package io.grpc;
+package io.grpc.internal;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -44,12 +44,17 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import io.grpc.IntegerMarshaller;
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
 import io.grpc.MethodDescriptor.MethodType;
-import io.grpc.internal.ServerListener;
-import io.grpc.internal.ServerStream;
-import io.grpc.internal.ServerStreamListener;
-import io.grpc.internal.ServerTransport;
-import io.grpc.internal.ServerTransportListener;
+import io.grpc.MutableHandlerRegistry;
+import io.grpc.MutableHandlerRegistryImpl;
+import io.grpc.ServerCall;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerServiceDefinition;
+import io.grpc.Status;
+import io.grpc.StringMarshaller;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java b/examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
index b6d734f..104f873 100644
--- a/examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
+++ b/examples/android/app/src/main/java/io/grpc/helloworldexample/HelloworldActivity.java
@@ -11,13 +11,13 @@
 import android.widget.EditText;
 import android.widget.TextView;
 
-import java.util.concurrent.TimeUnit;
-
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.helloworldexample.Helloworld.HelloReply;
 import io.grpc.helloworldexample.Helloworld.HelloRequest;
 import io.grpc.transport.okhttp.OkHttpChannelBuilder;
 
+import java.util.concurrent.TimeUnit;
+
 public class HelloworldActivity extends ActionBarActivity {
     private Button mSendButton;
     private EditText mHostEdit;
@@ -47,7 +47,7 @@
         private String mHost;
         private String mMessage;
         private int mPort;
-        private ChannelImpl mChannel;
+        private ManagedChannel mChannel;
 
         @Override
         protected void onPreExecute() {
@@ -58,7 +58,7 @@
             mResultText.setText("");
         }
 
-        private String sayHello(ChannelImpl channel) {
+        private String sayHello(ManagedChannel channel) {
             GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
             HelloRequest message = new HelloRequest();
             message.name = mMessage;
diff --git a/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java b/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java
index 0f9e296..368b427 100644
--- a/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java
+++ b/examples/src/main/java/io/grpc/examples/header/CustomHeaderClient.java
@@ -32,9 +32,9 @@
 package io.grpc.examples.header;
 
 import io.grpc.Channel;
-import io.grpc.ChannelImpl;
 import io.grpc.ClientInterceptor;
 import io.grpc.ClientInterceptors;
+import io.grpc.ManagedChannel;
 import io.grpc.examples.helloworld.GreeterGrpc;
 import io.grpc.examples.helloworld.HelloRequest;
 import io.grpc.examples.helloworld.HelloResponse;
@@ -52,7 +52,7 @@
 public class CustomHeaderClient {
   private static final Logger logger = Logger.getLogger(CustomHeaderClient.class.getName());
 
-  private final ChannelImpl originChannel;
+  private final ManagedChannel originChannel;
   private final GreeterGrpc.GreeterBlockingStub blockingStub;
 
   /**
diff --git a/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java b/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java
index 7454f68..26a5341 100644
--- a/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java
+++ b/examples/src/main/java/io/grpc/examples/header/CustomHeaderServer.java
@@ -31,7 +31,7 @@
 
 package io.grpc.examples.header;
 
-import io.grpc.ServerImpl;
+import io.grpc.Server;
 import io.grpc.ServerInterceptors;
 import io.grpc.examples.helloworld.GreeterGrpc;
 import io.grpc.examples.helloworld.HelloRequest;
@@ -50,7 +50,7 @@
 
   /* The port on which the server should run */
   private static final int port = 50051;
-  private ServerImpl server;
+  private Server server;
 
   private void start() throws Exception {
     server = NettyServerBuilder.forPort(port).addService(ServerInterceptors
diff --git a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
index a4a9d89..47de301 100644
--- a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
+++ b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java
@@ -31,7 +31,7 @@
 
 package io.grpc.examples.helloworld;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.netty.NegotiationType;
 import io.grpc.netty.NettyChannelBuilder;
 
@@ -45,7 +45,7 @@
 public class HelloWorldClient {
   private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());
 
-  private final ChannelImpl channel;
+  private final ManagedChannel channel;
   private final GreeterGrpc.GreeterBlockingStub blockingStub;
 
   /** Construct client connecting to HelloWorld server at {@code host:port}. */
diff --git a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
index 65a35b7..78eb8e6 100644
--- a/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
+++ b/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java
@@ -31,7 +31,7 @@
 
 package io.grpc.examples.helloworld;
 
-import io.grpc.ServerImpl;
+import io.grpc.Server;
 import io.grpc.netty.NettyServerBuilder;
 import io.grpc.stub.StreamObserver;
 
@@ -45,7 +45,7 @@
 
   /* The port on which the server should run */
   private int port = 50051;
-  private ServerImpl server;
+  private Server server;
 
   private void start() throws Exception {
     server = NettyServerBuilder.forPort(port)
diff --git a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
index 8013f0f..2c64fd1 100644
--- a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
+++ b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java
@@ -33,7 +33,7 @@
 
 import com.google.common.util.concurrent.SettableFuture;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.examples.routeguide.RouteGuideGrpc.RouteGuideBlockingStub;
 import io.grpc.examples.routeguide.RouteGuideGrpc.RouteGuideStub;
 import io.grpc.netty.NegotiationType;
@@ -53,7 +53,7 @@
 public class RouteGuideClient {
   private static final Logger logger = Logger.getLogger(RouteGuideClient.class.getName());
 
-  private final ChannelImpl channel;
+  private final ManagedChannel channel;
   private final RouteGuideBlockingStub blockingStub;
   private final RouteGuideStub asyncStub;
 
diff --git a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
index 78f26d2..02ee4d2 100644
--- a/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
+++ b/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java
@@ -40,7 +40,7 @@
 import static java.lang.Math.toRadians;
 import static java.util.concurrent.TimeUnit.NANOSECONDS;
 
-import io.grpc.ServerImpl;
+import io.grpc.Server;
 import io.grpc.netty.NettyServerBuilder;
 import io.grpc.stub.StreamObserver;
 
@@ -63,7 +63,7 @@
 
   private final int port;
   private final Collection<Feature> features;
-  private ServerImpl grpcServer;
+  private Server grpcServer;
 
   public RouteGuideServer(int port) {
     this(port, RouteGuideUtil.getDefaultFeaturesFile());
diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java
index 324da40..ab13535 100644
--- a/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java
+++ b/interop-testing/src/main/java/io/grpc/testing/integration/AbstractTransportTest.java
@@ -32,7 +32,6 @@
 package io.grpc.testing.integration;
 
 import static io.grpc.testing.integration.Messages.PayloadType.COMPRESSABLE;
-import static io.grpc.testing.integration.Util.assertEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
@@ -52,16 +51,16 @@
 import com.google.protobuf.ByteString;
 import com.google.protobuf.EmptyProtos.Empty;
 
-import io.grpc.AbstractServerBuilder;
 import io.grpc.CallOptions;
-import io.grpc.ChannelImpl;
 import io.grpc.ClientCall;
+import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
-import io.grpc.ServerImpl;
+import io.grpc.Server;
 import io.grpc.ServerInterceptors;
 import io.grpc.Status;
 import io.grpc.StatusRuntimeException;
 import io.grpc.auth.ClientAuthInterceptor;
+import io.grpc.internal.AbstractServerImplBuilder;
 import io.grpc.internal.GrpcUtil;
 import io.grpc.protobuf.ProtoUtils;
 import io.grpc.stub.MetadataUtils;
@@ -104,10 +103,10 @@
   private static final AtomicReference<Metadata> requestHeadersCapture =
       new AtomicReference<Metadata>();
   private static ScheduledExecutorService testServiceExecutor;
-  private static ServerImpl server;
+  private static Server server;
   private static int OPERATION_TIMEOUT = 5000;
 
-  protected static void startStaticServer(AbstractServerBuilder<?> builder) {
+  protected static void startStaticServer(AbstractServerImplBuilder<?> builder) {
     testServiceExecutor = Executors.newScheduledThreadPool(2);
 
     builder.addService(ServerInterceptors.intercept(
@@ -126,7 +125,7 @@
     testServiceExecutor.shutdown();
   }
 
-  protected ChannelImpl channel;
+  protected ManagedChannel channel;
   protected TestServiceGrpc.TestServiceBlockingStub blockingStub;
   protected TestServiceGrpc.TestService asyncStub;
 
@@ -149,7 +148,7 @@
     }
   }
 
-  protected abstract ChannelImpl createChannel();
+  protected abstract ManagedChannel createChannel();
 
   @Test(timeout = 10000)
   public void emptyUnary() throws Exception {
diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/ReconnectTestClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/ReconnectTestClient.java
index 92486d1..39cfe35 100644
--- a/interop-testing/src/main/java/io/grpc/testing/integration/ReconnectTestClient.java
+++ b/interop-testing/src/main/java/io/grpc/testing/integration/ReconnectTestClient.java
@@ -35,7 +35,7 @@
 
 import com.google.protobuf.EmptyProtos.Empty;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.StatusRuntimeException;
 import io.grpc.netty.NegotiationType;
 import io.grpc.netty.NettyChannelBuilder;
@@ -53,8 +53,8 @@
   private int serverControlPort = 8080;
   private int serverRetryPort = 8081;
   private boolean useOkhttp = false;
-  private ChannelImpl controlChannel;
-  private ChannelImpl retryChannel;
+  private ManagedChannel controlChannel;
+  private ManagedChannel retryChannel;
   private ReconnectServiceGrpc.ReconnectServiceBlockingStub controlStub;
   private ReconnectServiceGrpc.ReconnectServiceBlockingStub retryStub;
 
diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java
index 6c9af45..0f3b2b1 100644
--- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java
+++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceClient.java
@@ -33,7 +33,7 @@
 
 import com.google.common.io.Files;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.netty.GrpcSslContexts;
 import io.grpc.netty.NegotiationType;
 import io.grpc.netty.NettyChannelBuilder;
@@ -253,7 +253,7 @@
 
   private class Tester extends AbstractTransportTest {
     @Override
-    protected ChannelImpl createChannel() {
+    protected ManagedChannel createChannel() {
       if (!useOkHttp) {
         InetAddress address;
         try {
diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceServer.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceServer.java
index 4b5beae..07ebefe 100644
--- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceServer.java
+++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceServer.java
@@ -33,7 +33,7 @@
 
 import com.google.common.util.concurrent.MoreExecutors;
 
-import io.grpc.ServerImpl;
+import io.grpc.Server;
 import io.grpc.ServerInterceptors;
 import io.grpc.netty.GrpcSslContexts;
 import io.grpc.netty.NettyServerBuilder;
@@ -80,7 +80,7 @@
   private boolean useTls = true;
 
   private ScheduledExecutorService executor;
-  private ServerImpl server;
+  private Server server;
 
   private void parseArgs(String[] args) {
     boolean usage = false;
diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java
index 43c57c5..952fc34 100644
--- a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java
+++ b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyLocalChannelTest.java
@@ -31,7 +31,7 @@
 
 package io.grpc.testing.integration;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.netty.NegotiationType;
 import io.grpc.netty.NettyChannelBuilder;
 import io.grpc.netty.NettyServerBuilder;
@@ -67,7 +67,7 @@
   }
 
   @Override
-  protected ChannelImpl createChannel() {
+  protected ManagedChannel createChannel() {
     return NettyChannelBuilder
         .forAddress(new LocalAddress("in-process-1"))
         .negotiationType(NegotiationType.PLAINTEXT)
diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java
index 77fd9d1..02196a0 100644
--- a/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java
+++ b/interop-testing/src/test/java/io/grpc/testing/integration/Http2NettyTest.java
@@ -31,7 +31,7 @@
 
 package io.grpc.testing.integration;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.netty.GrpcSslContexts;
 import io.grpc.netty.NettyChannelBuilder;
 import io.grpc.netty.NettyServerBuilder;
@@ -73,7 +73,7 @@
   }
 
   @Override
-  protected ChannelImpl createChannel() {
+  protected ManagedChannel createChannel() {
     try {
       return NettyChannelBuilder
           .forAddress(TestUtils.testServerAddress(serverPort))
diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java
index 647cd92..d15f2da 100644
--- a/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java
+++ b/interop-testing/src/test/java/io/grpc/testing/integration/Http2OkHttpTest.java
@@ -34,7 +34,7 @@
 import com.squareup.okhttp.ConnectionSpec;
 import com.squareup.okhttp.TlsVersion;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.netty.GrpcSslContexts;
 import io.grpc.netty.NettyServerBuilder;
 import io.grpc.okhttp.OkHttpChannelBuilder;
@@ -75,7 +75,7 @@
   }
 
   @Override
-  protected ChannelImpl createChannel() {
+  protected ManagedChannel createChannel() {
     OkHttpChannelBuilder builder = OkHttpChannelBuilder.forAddress("127.0.0.1", serverPort)
         .connectionSpec(new ConnectionSpec.Builder(OkHttpChannelBuilder.DEFAULT_CONNECTION_SPEC)
             .cipherSuites(TestUtils.preferredTestCiphers().toArray(new String[0]))
diff --git a/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java b/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java
index d7f65a5..5085450 100644
--- a/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java
+++ b/interop-testing/src/test/java/io/grpc/testing/integration/InProcessTest.java
@@ -31,7 +31,7 @@
 
 package io.grpc.testing.integration;
 
-import io.grpc.ChannelImpl;
+import io.grpc.ManagedChannel;
 import io.grpc.inprocess.InProcessChannelBuilder;
 import io.grpc.inprocess.InProcessServerBuilder;
 
@@ -57,7 +57,7 @@
   }
 
   @Override
-  protected ChannelImpl createChannel() {
+  protected ManagedChannel createChannel() {
     return InProcessChannelBuilder.forName(serverName).build();
   }
 }
diff --git a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java
index e5d7a31..2e97c2a 100644
--- a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java
+++ b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java
@@ -36,12 +36,12 @@
 
 import com.google.common.base.Preconditions;
 
-import io.grpc.AbstractChannelBuilder;
+import io.grpc.ExperimentalApi;
+import io.grpc.internal.AbstractManagedChannelImplBuilder;
 import io.grpc.internal.AbstractReferenceCounted;
 import io.grpc.internal.ClientTransport;
 import io.grpc.internal.ClientTransportFactory;
 import io.grpc.internal.SharedResourceHolder;
-
 import io.netty.channel.Channel;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.socket.nio.NioSocketChannel;
@@ -56,7 +56,9 @@
 /**
  * A builder to help simplify construction of channels using the Netty transport.
  */
-public final class NettyChannelBuilder extends AbstractChannelBuilder<NettyChannelBuilder> {
+@ExperimentalApi("There is no plan to make this API stable, given transport API instability")
+public final class NettyChannelBuilder
+        extends AbstractManagedChannelImplBuilder<NettyChannelBuilder> {
   public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1048576; // 1MiB
 
   private final SocketAddress serverAddress;
diff --git a/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java b/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java
index 1bbed87..9f6f251 100644
--- a/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java
+++ b/netty/src/main/java/io/grpc/netty/NettyServerBuilder.java
@@ -36,9 +36,9 @@
 
 import com.google.common.base.Preconditions;
 
-import io.grpc.AbstractServerBuilder;
+import io.grpc.ExperimentalApi;
 import io.grpc.HandlerRegistry;
-
+import io.grpc.internal.AbstractServerImplBuilder;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.ServerChannel;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
@@ -52,7 +52,8 @@
 /**
  * A builder to help simplify the construction of a Netty-based GRPC server.
  */
-public final class NettyServerBuilder extends AbstractServerBuilder<NettyServerBuilder> {
+@ExperimentalApi("There is no plan to make this API stable, given transport API instability")
+public final class NettyServerBuilder extends AbstractServerImplBuilder<NettyServerBuilder> {
   public static final int DEFAULT_FLOW_CONTROL_WINDOW = 1048576; // 1MiB
 
   private final SocketAddress address;
@@ -128,13 +129,13 @@
    * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility
    * to shut it down when it's desired.
    *
-   * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.ServerImpl} will
+   * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will
    * continue to run even after the main thread has terminated. However, users have to be cautious
    * when providing their own {@link EventLoopGroup}s.
    * For example, Netty's {@link EventLoopGroup}s use daemon threads by default
    * and thus an application with only daemon threads running besides the main thread will exit as
    * soon as the main thread completes.
-   * A simple solution to this problem is to call {@link io.grpc.ServerImpl#awaitTermination()} to
+   * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to
    * keep the main thread alive until the server has terminated.
    */
   public NettyServerBuilder bossEventLoopGroup(EventLoopGroup group) {
@@ -151,13 +152,13 @@
    * <p>The server won't take ownership of the given EventLoopGroup. It's caller's responsibility
    * to shut it down when it's desired.
    *
-   * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.ServerImpl} will
+   * <p>Grpc uses non-daemon {@link Thread}s by default and thus a {@link io.grpc.Server} will
    * continue to run even after the main thread has terminated. However, users have to be cautious
    * when providing their own {@link EventLoopGroup}s.
    * For example, Netty's {@link EventLoopGroup}s use daemon threads by default
    * and thus an application with only daemon threads running besides the main thread will exit as
    * soon as the main thread completes.
-   * A simple solution to this problem is to call {@link io.grpc.ServerImpl#awaitTermination()} to
+   * A simple solution to this problem is to call {@link io.grpc.Server#awaitTermination()} to
    * keep the main thread alive until the server has terminated.
    */
   public NettyServerBuilder workerEventLoopGroup(EventLoopGroup group) {
diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
index 010dbb9..c814bf3 100644
--- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
+++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java
@@ -41,7 +41,8 @@
 import com.squareup.okhttp.ConnectionSpec;
 import com.squareup.okhttp.TlsVersion;
 
-import io.grpc.AbstractChannelBuilder;
+import io.grpc.ExperimentalApi;
+import io.grpc.internal.AbstractManagedChannelImplBuilder;
 import io.grpc.internal.AbstractReferenceCounted;
 import io.grpc.internal.ClientTransport;
 import io.grpc.internal.ClientTransportFactory;
@@ -55,7 +56,9 @@
 import javax.net.ssl.SSLSocketFactory;
 
 /** Convenience class for building channels with the OkHttp transport. */
-public final class OkHttpChannelBuilder extends AbstractChannelBuilder<OkHttpChannelBuilder> {
+@ExperimentalApi("There is no plan to make this API stable, given transport API instability")
+public final class OkHttpChannelBuilder extends
+        AbstractManagedChannelImplBuilder<OkHttpChannelBuilder> {
 
   public static final ConnectionSpec DEFAULT_CONNECTION_SPEC =
       new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)