core: promote LBv2 classes.
diff --git a/core/src/main/java/io/grpc/Internal.java b/core/src/main/java/io/grpc/Internal.java
index e4cb1a4..479c1b1 100644
--- a/core/src/main/java/io/grpc/Internal.java
+++ b/core/src/main/java/io/grpc/Internal.java
@@ -41,7 +41,7 @@
  * Annotates a program element (class, method, package etc) which is internal to gRPC, not part of
  * the public API, and should not be used by users of gRPC.
  *
- * <p>However, if you want to implement a custom {@link LoadBalancer2}, an alternative transport, or
+ * <p>However, if you want to implement a custom {@link LoadBalancer}, an alternative transport, or
  * anything else that will be wired into gRPC library, you may use the internal parts.  Please
  * consult the gRPC team first, because internal APIs don't have the same API stability guarantee as
  * the public APIs do.
diff --git a/core/src/main/java/io/grpc/LoadBalancer.java b/core/src/main/java/io/grpc/LoadBalancer.java
new file mode 100644
index 0000000..1db9d36
--- /dev/null
+++ b/core/src/main/java/io/grpc/LoadBalancer.java
@@ -0,0 +1,414 @@
+/*
+ * 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.
+ */
+
+package io.grpc;
+
+import com.google.common.base.Preconditions;
+import java.util.List;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import javax.annotation.concurrent.NotThreadSafe;
+import javax.annotation.concurrent.ThreadSafe;
+
+/**
+ * A pluggable component that receives resolved addresses from {@link NameResolver} and provides the
+ * channel a usable subchannel when asked.
+ *
+ * <h3>Overview</h3>
+ *
+ * <p>A LoadBalancer typically implements three interfaces:
+ * <ol>
+ *   <li>{@link LoadBalancer} is the main interface.  All methods on it are invoked sequentially
+ *       from the Channel Executor.  It receives the results from the {@link NameResolver}, updates
+ *       of subchannels' connectivity states, and the channel's request for the LoadBalancer to
+ *       shutdown.</li>
+ *   <li>{@link SubchannelPicker SubchannelPicker} does the actual load-balancing work.  It selects
+ *       a {@link Subchannel Subchannel} for each new RPC.</li>
+ *   <li>{@link Factory Factory} creates a new {@link LoadBalancer} instance.
+ * </ol>
+ *
+ * <p>{@link Helper Helper} is implemented by gRPC library and provided to {@link Factory
+ * Factory}. It provides functionalities that a {@code LoadBalancer} implementation would typically
+ * need.
+ *
+ * <h3>Channel Executor</h3>
+ *
+ * <p>Channel Executor is an internal executor of the channel, which is used to serialize all the
+ * callback methods on the {@link LoadBalancer} interface, thus the balancer implementation doesn't
+ * need to worry about synchronization among them.  However, the actual thread of the Channel
+ * Executor is typically the network thread, thus the following rules must be followed to prevent
+ * blocking or even dead-locking in a network
+ *
+ * <ol>
+ *
+ *   <li><strong>Never block in Channel Executor</strong>.  The callback methods must return
+ *   quickly.  Examples or work that must be avoided: CPU-intensive calculation, waiting on
+ *   synchronization primitives, blocking I/O, blocking RPCs, etc.</li>
+ *
+ *   <li><strong>Avoid calling into other components with lock held</strong>.  Channel Executor may
+ *   run callbacks under a lock, e.g., the transport lock of OkHttp.  If your LoadBalancer has a
+ *   lock, holds the lock in a callback method (e.g., {@link #handleSubchannelState
+ *   handleSubchannelState()}) while calling into another class that may involve locks, be cautious
+ *   of deadlock.  Generally you wouldn't need any locking in the LoadBalancer.</li>
+ *
+ * </ol>
+ *
+ * <p>{@link Helper#runSerialized Helper.runSerialized()} allows you to schedule a task to be run in
+ * the Channel Executor.
+ *
+ * <h3>The canonical implementation pattern</h3>
+ *
+ * <p>A {@link LoadBalancer} keeps states like the latest addresses from NameResolver, the
+ * Subchannel(s) and their latest connectivity states.  These states are mutated within the Channel
+ * Executor.
+ *
+ * <p>A typical {@link SubchannelPicker SubchannelPicker} holds a snapshot of these states.  It may
+ * have its own states, e.g., a picker from a round-robin load-balancer may keep a pointer to the
+ * next Subchannel, which are typically mutated by multiple threads.  The picker should only mutate
+ * its own state, and should not mutate or re-acquire the states of the LoadBalancer.  This way the
+ * picker only needs to synchronize its own states, which is typically trivial to implement.
+ *
+ * <p>When the LoadBalancer states changes, e.g., Subchannels has become or stopped being READY, and
+ * we want subsequent RPCs to use the latest list of READY Subchannels, LoadBalancer would create
+ * a new picker, which holds a snapshot of the latest Subchannel list.  Refer to the javadoc of
+ * {@link #handleSubchannelState handleSubchannelState()} how to do this properly.
+ *
+ * <p>No synchronization should be necessary between LoadBalancer and its pickers if you follow
+ * the pattern above.  It may be possible to implement in a different way, but that would usually
+ * result in more complicated threading.
+ */
+@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
+@NotThreadSafe
+public abstract class LoadBalancer {
+  /**
+   * Handles newly resolved server groups and metadata attributes from name resolution system.
+   * {@code servers} contained in {@link ResolvedServerInfoGroup} should be considered equivalent
+   * but may be flattened into a single list if needed.
+   *
+   * <p>Implementations should not modify the given {@code servers}.
+   *
+   * @param servers the resolved server addresses, never empty.
+   * @param attributes extra metadata from naming system.
+   */
+  public abstract void handleResolvedAddresses(
+      List<ResolvedServerInfoGroup> servers, Attributes attributes);
+
+  /**
+   * Handles an error from the name resolution system.
+   *
+   * @param error a non-OK status
+   */
+  public abstract void handleNameResolutionError(Status error);
+
+  /**
+   * Handles a state change on a Subchannel.
+   *
+   * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial IDLE
+   * state.
+   *
+   * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
+   * Helper#updatePicker Helper.updatePicker()}.  Failing to do so may result in unnecessary delays
+   * of RPCs. Please refer to {@link PickResult#withSubchannel PickResult.withSubchannel()}'s
+   * javadoc for more information.
+   *
+   * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
+   * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The other
+   * is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has already
+   * terminated, thus there won't be further requests to LoadBalancer.  Therefore, SHUTDOWN can be
+   * safely ignored.
+   *
+   * @param subchannel the involved Subchannel
+   * @param stateInfo the new state
+   */
+  public abstract void handleSubchannelState(
+      Subchannel subchannel, ConnectivityStateInfo stateInfo);
+
+  /**
+   * The channel asks the load-balancer to shutdown.  No more callbacks will be called after this
+   * method.  The implementation should shutdown all Subchannels and OOB channels, and do any other
+   * cleanup as necessary.
+   */
+  public abstract void shutdown();
+
+  /**
+   * The main balancing logic.  It <strong>must be thread-safe</strong>. Typically it should only
+   * synchronize on its own state, and avoid synchronizing with the LoadBalancer's state.
+   */
+  @ThreadSafe
+  public abstract static class SubchannelPicker {
+    /**
+     * Make a balancing decision for a new RPC.
+     *
+     * @param affinity the affinity attributes provided via {@link CallOptions#withAffinity}
+     * @param headers the headers container of the RPC. It can be mutated within this method.
+     */
+    public abstract PickResult pickSubchannel(Attributes affinity, Metadata headers);
+  }
+
+  /**
+   * A balancing decision made by {@link SubchannelPicker SubchannelPicker} for an RPC.
+   *
+   * <p>The outcome of the decision will be one of the following:
+   * <ul>
+   *   <li>Proceed: if a Subchannel is provided via {@link #withSubchannel withSubchannel()}, and is
+   *       in READY state when the RPC tries to start on it, the RPC will proceed on that
+   *       Subchannel.</li>
+   *   <li>Error: if an error is provided via {@link #withError withError()}, and the RPC is not
+   *       wait-for-ready (i.e., {@link CallOptions#withWaitForReady} was not called), the RPC will
+   *       fail immediately with the given error.</li>
+   *   <li>Buffer: in all other cases, the RPC will be buffered in the Channel, until the next
+   *       picker is provided via {@link Helper#updatePicker Helper.updatePicker()}, when the RPC
+   *       will go through the same picking process again.</li>
+   * </ul>
+   */
+  @Immutable
+  public static final class PickResult {
+    private static final PickResult NO_RESULT = new PickResult(null, Status.OK);
+
+    @Nullable private final Subchannel subchannel;
+    // An error to be propagated to the application if subchannel == null
+    // Or OK if there is no error.
+    // subchannel being null and error being OK means RPC needs to wait
+    private final Status status;
+
+    private PickResult(Subchannel subchannel, Status status) {
+      this.subchannel = subchannel;
+      this.status = Preconditions.checkNotNull(status, "status");
+    }
+
+    /**
+     * A decision to proceed the RPC on a Subchannel.
+     *
+     * <p>Only Subchannels returned by {@link Helper#createSubchannel Helper.createSubchannel()}
+     * will work.  DO NOT try to use your own implementations of Subchannels, as they won't work.
+     *
+     * <p>When the RPC tries to use the return Subchannel, which is briefly after this method
+     * returns, the state of the Subchannel will decide where the RPC would go:
+     *
+     * <ul>
+     *   <li>READY: the RPC will proceed on this Subchannel.</li>
+     *   <li>IDLE: the RPC will be buffered.  Subchannel will attempt to create connection.</li>
+     *   <li>All other states: the RPC will be buffered.</li>
+     * </ul>
+     *
+     * <p><strong>All buffered RPCs will stay buffered</strong> until the next call of {@link
+     * Helper#updatePicker Helper.updatePicker()}, which will trigger a new picking process.
+     *
+     * <p>Note that Subchannel's state may change at the same time the picker is making the
+     * decision, which means the decision may be made with (to-be) outdated information.  For
+     * example, a picker may return a Subchannel known to be READY, but it has become IDLE when is
+     * about to be used by the RPC, which makes the RPC to be buffered.  The LoadBalancer will soon
+     * learn about the Subchannels' transition from READY to IDLE, create a new picker and allow the
+     * RPC to use another READY transport if there is any.
+     *
+     * <p>You will want to avoid running into a situation where there are READY Subchannels out
+     * there but some RPCs are still buffered for longer than a brief time.
+     * <ul>
+     *   <li>This can happen if you return Subchannels with states other than READY and IDLE.  For
+     *       example, suppose you round-robin on 2 Subchannels, in READY and CONNECTING states
+     *       respectively.  If the picker ignores the state and pick them equally, 50% of RPCs will
+     *       be stuck in buffered state until both Subchannels are READY.</li>
+     *   <li>This can also happen if you don't create a new picker at key state changes of
+     *       Subchannels.  Take the above round-robin example again.  Suppose you do pick only READY
+     *       and IDLE Subchannels, and initially both Subchannels are READY.  Now one becomes IDLE,
+     *       then CONNECTING and stays CONNECTING for a long time.  If you don't create a new picker
+     *       in response to the CONNECTING state to exclude that Subchannel, 50% of RPCs will hit it
+     *       and be buffered even though the other Subchannel is READY.</li>
+     * </ul>
+     *
+     * <p>In order to prevent unnecessary delay of RPCs, the rules of thumb are:
+     * <ol>
+     *   <li>The picker should only pick Subchannels that are known as READY or IDLE.  Whether to
+     *       pick IDLE Subchannels depends on whether you want Subchannels to connect on-demand or
+     *       actively:
+     *       <ul>
+     *         <li>If you want connect-on-demand, include IDLE Subchannels in your pick results,
+     *             because when an RPC tries to use an IDLE Subchannel, the Subchannel will try to
+     *             connect.</li>
+     *         <li>If you want Subchannels to be always connected even when there is no RPC, you
+     *             would call {@link Subchannel#requestConnection Subchannel.requestConnection()}
+     *             whenever the Subchannel has transitioned to IDLE, then you don't need to include
+     *             IDLE Subchannels in your pick results.</li>
+     *       </ul></li>
+     *   <li>Always create a new picker and call {@link Helper#updatePicker Helper.updatePicker()}
+     *       whenever {@link #handleSubchannelState handleSubchannelState()} is called, unless the
+     *       new state is SHUTDOWN. See {@code handleSubchannelState}'s javadoc for more
+     *       details.</li>
+     * </ol>
+     */
+    public static PickResult withSubchannel(Subchannel subchannel) {
+      return new PickResult(Preconditions.checkNotNull(subchannel, "subchannel"), Status.OK);
+    }
+
+    /**
+     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
+     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
+     * with the given error.
+     *
+     * @param error the error status.  Must not be OK.
+     */
+    public static PickResult withError(Status error) {
+      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
+      return new PickResult(null, error);
+    }
+
+    /**
+     * No decision could be made.  The RPC will stay buffered.
+     */
+    public static PickResult withNoResult() {
+      return NO_RESULT;
+    }
+
+    /**
+     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
+     * null otherwise.
+     */
+    @Nullable
+    public Subchannel getSubchannel() {
+      return subchannel;
+    }
+
+    /**
+     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
+     * withError}, or {@code OK} otherwise.
+     */
+    public Status getStatus() {
+      return status;
+    }
+
+    @Override
+    public String toString() {
+      return "[subchannel=" + subchannel + " status=" + status + "]";
+    }
+  }
+
+  /**
+   * Provides essentials for LoadBalancer implementations.
+   */
+  @ThreadSafe
+  public abstract static class Helper {
+    /**
+     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
+     * considered equivalent.  The {@code attrs} are custom attributes associated with this
+     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
+     * Subchannel.getAttributes()}.
+     *
+     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
+     * Subchannels within {@link #shutdown}.
+     */
+    public abstract Subchannel createSubchannel(EquivalentAddressGroup addrs, Attributes attrs);
+
+    /**
+     * Out-of-band channel for LoadBalancer’s own RPC needs, e.g., talking to an external
+     * load-balancer service.
+     *
+     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
+     * channels within {@link #shutdown}.
+     */
+    public abstract ManagedChannel createOobChannel(
+        EquivalentAddressGroup eag, String authority);
+
+    /**
+     * Set a new picker to the channel.
+     *
+     * <p>When a new picker is provided via {@code updatePicker()}, the channel will apply the
+     * picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel
+     * SubchannelPicker.pickSubchannel()}.
+     *
+     * <p>The channel will hold the picker and use it for all RPCs, until {@code updatePicker()} is
+     * called again and a new picker replaces the old one.  If {@code updatePicker()} has never been
+     * called, the channel will buffer all RPCs until a picker is provided.
+     */
+    public abstract void updatePicker(SubchannelPicker picker);
+
+    /**
+     * Schedule a task to be run in the Channel Executor, which serializes the task with the
+     * callback methods on the {@link LoadBalancer} interface.
+     */
+    public abstract void runSerialized(Runnable task);
+
+    /**
+     * Returns the NameResolver of the channel.
+     */
+    public abstract NameResolver.Factory getNameResolverFactory();
+
+    /**
+     * Returns the authority string of the channel, which is derived from the DNS-style target name.
+     */
+    public abstract String getAuthority();
+  }
+
+  /**
+   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
+   * EquivalentAddressGroup}.
+   *
+   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
+   * also keeps track of previous transports that has been shut down but not terminated yet.
+   *
+   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
+   * create a new transport.  It won't actively create transports otherwise.  {@link
+   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
+   * there isn't any.
+   */
+  @ThreadSafe
+  public abstract static class Subchannel {
+    /**
+     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
+     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
+     */
+    public abstract void shutdown();
+
+    /**
+     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
+     */
+    public abstract void requestConnection();
+
+    /**
+     * Returns the addresses that this Subchannel is bound to.
+     */
+    public abstract EquivalentAddressGroup getAddresses();
+
+    /**
+     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
+     * LoadBalancer can use it to attach additional information here, e.g., the shard this
+     * Subchannel belongs to.
+     */
+    public abstract Attributes getAttributes();
+  }
+
+  @ThreadSafe
+  public abstract static class Factory {
+    /**
+     * Creates a {@link LoadBalancer} that will be used inside a channel.
+     */
+    public abstract LoadBalancer newLoadBalancer(Helper helper);
+  }
+}
diff --git a/core/src/main/java/io/grpc/LoadBalancer2.java b/core/src/main/java/io/grpc/LoadBalancer2.java
index a4772df..fe0b0f5 100644
--- a/core/src/main/java/io/grpc/LoadBalancer2.java
+++ b/core/src/main/java/io/grpc/LoadBalancer2.java
@@ -31,390 +31,13 @@
 
 package io.grpc;
 
-import com.google.common.base.Preconditions;
-import java.util.List;
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import javax.annotation.concurrent.NotThreadSafe;
-import javax.annotation.concurrent.ThreadSafe;
-
 /**
- * A pluggable component that receives resolved addresses from {@link NameResolver} and provides the
- * channel a usable subchannel when asked.  This is the new interface that will replace {@link
- * LoadBalancer2}.
+ * An alias for {@link LoadBalancer}.
  *
- * <p><strong>IMPORTANT NOTICE FOR IMPLEMENTORS: </strong>The name of this class is temporary.  It
- * will be renamed to {@code LoadBalancer} eventually.  Make sure you have read through <a
- * href="https://github.com/grpc/grpc-java/issues/2656" target="_blank">#2656</a> to understand the
- * transition path.
- *
- * <h3>Overview</h3>
- *
- * <p>A LoadBalancer typically implements three interfaces:
- * <ol>
- *   <li>{@link LoadBalancer2} is the main interface.  All methods on it are invoked sequentially
- *       from the Channel Executor.  It receives the results from the {@link NameResolver}, updates
- *       of subchannels' connectivity states, and the channel's request for the LoadBalancer to
- *       shutdown.</li>
- *   <li>{@link SubchannelPicker SubchannelPicker} does the actual load-balancing work.  It selects
- *       a {@link Subchannel Subchannel} for each new RPC.</li>
- *   <li>{@link Factory Factory} creates a new {@link LoadBalancer2} instance.
- * </ol>
- *
- * <p>{@link Helper Helper} is implemented by gRPC library and provided to {@link Factory
- * Factory}. It provides functionalities that a {@code LoadBalancer2} implementation would typically
- * need.
- *
- * <h3>Channel Executor</h3>
- *
- * <p>Channel Executor is an internal executor of the channel, which is used to serialize all the
- * callback methods on the {@link LoadBalancer2} interface, thus the balancer implementation doesn't
- * need to worry about synchronization among them.  However, the actual thread of the Channel
- * Executor is typically the network thread, thus the following rules must be followed to prevent
- * blocking or even dead-locking in a network
- *
- * <ol>
- *
- *   <li><strong>Never block in Channel Executor</strong>.  The callback methods must return
- *   quickly.  Examples or work that must be avoided: CPU-intensive calculation, waiting on
- *   synchronization primitives, blocking I/O, blocking RPCs, etc.</li>
- *
- *   <li><strong>Avoid calling into other components with lock held</strong>.  Channel Executor may
- *   run callbacks under a lock, e.g., the transport lock of OkHttp.  If your LoadBalancer has a
- *   lock, holds the lock in a callback method (e.g., {@link #handleSubchannelState
- *   handleSubchannelState()}) while calling into another class that may involve locks, be cautious
- *   of deadlock.  Generally you wouldn't need any locking in the LoadBalancer.</li>
- *
- * </ol>
- *
- * <p>{@link Helper#runSerialized Helper.runSerialized()} allows you to schedule a task to be run in
- * the Channel Executor.
- *
- * <h3>The canonical implementation pattern</h3>
- *
- * <p>A {@link LoadBalancer2} keeps states like the latest addresses from NameResolver, the
- * Subchannel(s) and their latest connectivity states.  These states are mutated within the Channel
- * Executor.
- *
- * <p>A typical {@link SubchannelPicker SubchannelPicker} holds a snapshot of these states.  It may
- * have its own states, e.g., a picker from a round-robin load-balancer may keep a pointer to the
- * next Subchannel, which are typically mutated by multiple threads.  The picker should only mutate
- * its own state, and should not mutate or re-acquire the states of the LoadBalancer.  This way the
- * picker only needs to synchronize its own states, which is typically trivial to implement.
- *
- * <p>When the LoadBalancer states changes, e.g., Subchannels has become or stopped being READY, and
- * we want subsequent RPCs to use the latest list of READY Subchannels, LoadBalancer would create
- * a new picker, which holds a snapshot of the latest Subchannel list.  Refer to the javadoc of
- * {@link #handleSubchannelState handleSubchannelState()} how to do this properly.
- *
- * <p>No synchronization should be necessary between LoadBalancer and its pickers if you follow
- * the pattern above.  It may be possible to implement in a different way, but that would usually
- * result in more complicated threading.
+ * @deprecated this is going to be deleted in the next minor release.  Use {@link LoadBalancer}
+ *             instead.
  */
 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
-@NotThreadSafe
-public abstract class LoadBalancer2 {
-  /**
-   * Handles newly resolved server groups and metadata attributes from name resolution system.
-   * {@code servers} contained in {@link ResolvedServerInfoGroup} should be considered equivalent
-   * but may be flattened into a single list if needed.
-   *
-   * <p>Implementations should not modify the given {@code servers}.
-   *
-   * @param servers the resolved server addresses, never empty.
-   * @param attributes extra metadata from naming system.
-   */
-  public abstract void handleResolvedAddresses(
-      List<ResolvedServerInfoGroup> servers, Attributes attributes);
-
-  /**
-   * Handles an error from the name resolution system.
-   *
-   * @param error a non-OK status
-   */
-  public abstract void handleNameResolutionError(Status error);
-
-  /**
-   * Handles a state change on a Subchannel.
-   *
-   * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial IDLE
-   * state.
-   *
-   * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
-   * Helper#updatePicker Helper.updatePicker()}.  Failing to do so may result in unnecessary delays
-   * of RPCs. Please refer to {@link PickResult#withSubchannel PickResult.withSubchannel()}'s
-   * javadoc for more information.
-   *
-   * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
-   * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The other
-   * is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has already
-   * terminated, thus there won't be further requests to LoadBalancer.  Therefore, SHUTDOWN can be
-   * safely ignored.
-   *
-   * @param subchannel the involved Subchannel
-   * @param stateInfo the new state
-   */
-  public abstract void handleSubchannelState(
-      Subchannel subchannel, ConnectivityStateInfo stateInfo);
-
-  /**
-   * The channel asks the load-balancer to shutdown.  No more callbacks will be called after this
-   * method.  The implementation should shutdown all Subchannels and OOB channels, and do any other
-   * cleanup as necessary.
-   */
-  public abstract void shutdown();
-
-  /**
-   * The main balancing logic.  It <strong>must be thread-safe</strong>. Typically it should only
-   * synchronize on its own state, and avoid synchronizing with the LoadBalancer's state.
-   */
-  @ThreadSafe
-  public abstract static class SubchannelPicker {
-    /**
-     * Make a balancing decision for a new RPC.
-     *
-     * @param affinity the affinity attributes provided via {@link CallOptions#withAffinity}
-     * @param headers the headers container of the RPC. It can be mutated within this method.
-     */
-    public abstract PickResult pickSubchannel(Attributes affinity, Metadata headers);
-  }
-
-  /**
-   * A balancing decision made by {@link SubchannelPicker SubchannelPicker} for an RPC.
-   *
-   * <p>The outcome of the decision will be one of the following:
-   * <ul>
-   *   <li>Proceed: if a Subchannel is provided via {@link #withSubchannel withSubchannel()}, and is
-   *       in READY state when the RPC tries to start on it, the RPC will proceed on that
-   *       Subchannel.</li>
-   *   <li>Error: if an error is provided via {@link #withError withError()}, and the RPC is not
-   *       wait-for-ready (i.e., {@link CallOptions#withWaitForReady} was not called), the RPC will
-   *       fail immediately with the given error.</li>
-   *   <li>Buffer: in all other cases, the RPC will be buffered in the Channel, until the next
-   *       picker is provided via {@link Helper#updatePicker Helper.updatePicker()}, when the RPC
-   *       will go through the same picking process again.</li>
-   * </ul>
-   */
-  @Immutable
-  public static final class PickResult {
-    private static final PickResult NO_RESULT = new PickResult(null, Status.OK);
-
-    @Nullable private final Subchannel subchannel;
-    // An error to be propagated to the application if subchannel == null
-    // Or OK if there is no error.
-    // subchannel being null and error being OK means RPC needs to wait
-    private final Status status;
-
-    private PickResult(Subchannel subchannel, Status status) {
-      this.subchannel = subchannel;
-      this.status = Preconditions.checkNotNull(status, "status");
-    }
-
-    /**
-     * A decision to proceed the RPC on a Subchannel.
-     *
-     * <p>Only Subchannels returned by {@link Helper#createSubchannel Helper.createSubchannel()}
-     * will work.  DO NOT try to use your own implementations of Subchannels, as they won't work.
-     *
-     * <p>When the RPC tries to use the return Subchannel, which is briefly after this method
-     * returns, the state of the Subchannel will decide where the RPC would go:
-     *
-     * <ul>
-     *   <li>READY: the RPC will proceed on this Subchannel.</li>
-     *   <li>IDLE: the RPC will be buffered.  Subchannel will attempt to create connection.</li>
-     *   <li>All other states: the RPC will be buffered.</li>
-     * </ul>
-     *
-     * <p><strong>All buffered RPCs will stay buffered</strong> until the next call of {@link
-     * Helper#updatePicker Helper.updatePicker()}, which will trigger a new picking process.
-     *
-     * <p>Note that Subchannel's state may change at the same time the picker is making the
-     * decision, which means the decision may be made with (to-be) outdated information.  For
-     * example, a picker may return a Subchannel known to be READY, but it has become IDLE when is
-     * about to be used by the RPC, which makes the RPC to be buffered.  The LoadBalancer will soon
-     * learn about the Subchannels' transition from READY to IDLE, create a new picker and allow the
-     * RPC to use another READY transport if there is any.
-     *
-     * <p>You will want to avoid running into a situation where there are READY Subchannels out
-     * there but some RPCs are still buffered for longer than a brief time.
-     * <ul>
-     *   <li>This can happen if you return Subchannels with states other than READY and IDLE.  For
-     *       example, suppose you round-robin on 2 Subchannels, in READY and CONNECTING states
-     *       respectively.  If the picker ignores the state and pick them equally, 50% of RPCs will
-     *       be stuck in buffered state until both Subchannels are READY.</li>
-     *   <li>This can also happen if you don't create a new picker at key state changes of
-     *       Subchannels.  Take the above round-robin example again.  Suppose you do pick only READY
-     *       and IDLE Subchannels, and initially both Subchannels are READY.  Now one becomes IDLE,
-     *       then CONNECTING and stays CONNECTING for a long time.  If you don't create a new picker
-     *       in response to the CONNECTING state to exclude that Subchannel, 50% of RPCs will hit it
-     *       and be buffered even though the other Subchannel is READY.</li>
-     * </ul>
-     *
-     * <p>In order to prevent unnecessary delay of RPCs, the rules of thumb are:
-     * <ol>
-     *   <li>The picker should only pick Subchannels that are known as READY or IDLE.  Whether to
-     *       pick IDLE Subchannels depends on whether you want Subchannels to connect on-demand or
-     *       actively:
-     *       <ul>
-     *         <li>If you want connect-on-demand, include IDLE Subchannels in your pick results,
-     *             because when an RPC tries to use an IDLE Subchannel, the Subchannel will try to
-     *             connect.</li>
-     *         <li>If you want Subchannels to be always connected even when there is no RPC, you
-     *             would call {@link Subchannel#requestConnection Subchannel.requestConnection()}
-     *             whenever the Subchannel has transitioned to IDLE, then you don't need to include
-     *             IDLE Subchannels in your pick results.</li>
-     *       </ul></li>
-     *   <li>Always create a new picker and call {@link Helper#updatePicker Helper.updatePicker()}
-     *       whenever {@link #handleSubchannelState handleSubchannelState()} is called, unless the
-     *       new state is SHUTDOWN. See {@code handleSubchannelState}'s javadoc for more
-     *       details.</li>
-     * </ol>
-     */
-    public static PickResult withSubchannel(Subchannel subchannel) {
-      return new PickResult(Preconditions.checkNotNull(subchannel, "subchannel"), Status.OK);
-    }
-
-    /**
-     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
-     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
-     * with the given error.
-     *
-     * @param error the error status.  Must not be OK.
-     */
-    public static PickResult withError(Status error) {
-      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
-      return new PickResult(null, error);
-    }
-
-    /**
-     * No decision could be made.  The RPC will stay buffered.
-     */
-    public static PickResult withNoResult() {
-      return NO_RESULT;
-    }
-
-    /**
-     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
-     * null otherwise.
-     */
-    @Nullable
-    public Subchannel getSubchannel() {
-      return subchannel;
-    }
-
-    /**
-     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
-     * withError}, or {@code OK} otherwise.
-     */
-    public Status getStatus() {
-      return status;
-    }
-
-    @Override
-    public String toString() {
-      return "[subchannel=" + subchannel + " status=" + status + "]";
-    }
-  }
-
-  /**
-   * Provides essentials for LoadBalancer implementations.
-   */
-  @ThreadSafe
-  public abstract static class Helper {
-    /**
-     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
-     * considered equivalent.  The {@code attrs} are custom attributes associated with this
-     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
-     * Subchannel.getAttributes()}.
-     *
-     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
-     * Subchannels within {@link #shutdown}.
-     */
-    public abstract Subchannel createSubchannel(EquivalentAddressGroup addrs, Attributes attrs);
-
-    /**
-     * Out-of-band channel for LoadBalancer’s own RPC needs, e.g., talking to an external
-     * load-balancer service.
-     *
-     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
-     * channels within {@link #shutdown}.
-     */
-    public abstract ManagedChannel createOobChannel(
-        EquivalentAddressGroup eag, String authority);
-
-    /**
-     * Set a new picker to the channel.
-     *
-     * <p>When a new picker is provided via {@code updatePicker()}, the channel will apply the
-     * picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel
-     * SubchannelPicker.pickSubchannel()}.
-     *
-     * <p>The channel will hold the picker and use it for all RPCs, until {@code updatePicker()} is
-     * called again and a new picker replaces the old one.  If {@code updatePicker()} has never been
-     * called, the channel will buffer all RPCs until a picker is provided.
-     */
-    public abstract void updatePicker(SubchannelPicker picker);
-
-    /**
-     * Schedule a task to be run in the Channel Executor, which serializes the task with the
-     * callback methods on the {@link LoadBalancer2} interface.
-     */
-    public abstract void runSerialized(Runnable task);
-
-    /**
-     * Returns the NameResolver of the channel.
-     */
-    public abstract NameResolver.Factory getNameResolverFactory();
-
-    /**
-     * Returns the authority string of the channel, which is derived from the DNS-style target name.
-     */
-    public abstract String getAuthority();
-  }
-
-  /**
-   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
-   * EquivalentAddressGroup}.
-   *
-   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
-   * also keeps track of previous transports that has been shut down but not terminated yet.
-   *
-   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
-   * create a new transport.  It won't actively create transports otherwise.  {@link
-   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
-   * there isn't any.
-   */
-  @ThreadSafe
-  public abstract static class Subchannel {
-    /**
-     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
-     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
-     */
-    public abstract void shutdown();
-
-    /**
-     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
-     */
-    public abstract void requestConnection();
-
-    /**
-     * Returns the addresses that this Subchannel is bound to.
-     */
-    public abstract EquivalentAddressGroup getAddresses();
-
-    /**
-     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
-     * LoadBalancer can use it to attach additional information here, e.g., the shard this
-     * Subchannel belongs to.
-     */
-    public abstract Attributes getAttributes();
-  }
-
-  @ThreadSafe
-  public abstract static class Factory {
-    /**
-     * Creates a {@link LoadBalancer2} that will be used inside a channel.
-     */
-    public abstract LoadBalancer2 newLoadBalancer(Helper helper);
-  }
+@Deprecated
+public abstract class LoadBalancer2 extends LoadBalancer {
 }
diff --git a/core/src/main/java/io/grpc/ManagedChannelBuilder.java b/core/src/main/java/io/grpc/ManagedChannelBuilder.java
index eb6734c..bd17459 100644
--- a/core/src/main/java/io/grpc/ManagedChannelBuilder.java
+++ b/core/src/main/java/io/grpc/ManagedChannelBuilder.java
@@ -155,9 +155,9 @@
   public abstract T nameResolverFactory(NameResolver.Factory resolverFactory);
 
   /**
-   * Provides a custom {@link LoadBalancer2.Factory} for the channel.
+   * Provides a custom {@link LoadBalancer.Factory} for the channel.
    *
-   * <p>If this method is not called, the builder will use {@link PickFirstBalancerFactory2}
+   * <p>If this method is not called, the builder will use {@link PickFirstBalancerFactory}
    * for the channel.
    *
    * <p>Calling this will make the channel to run the LBv2 code path. See <a
@@ -169,9 +169,7 @@
    * this method will throw.
    */
   @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
-  public T loadBalancerFactory(LoadBalancer2.Factory loadBalancerFactory) {
-    throw new UnsupportedOperationException("Not implemented by " + this.getClass().getName());
-  }
+  public abstract T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory);
 
   /**
    * Set the decompression registry for use in the channel.  This is an advanced API call and
diff --git a/core/src/main/java/io/grpc/PickFirstBalancerFactory2.java b/core/src/main/java/io/grpc/PickFirstBalancerFactory.java
similarity index 78%
rename from core/src/main/java/io/grpc/PickFirstBalancerFactory2.java
rename to core/src/main/java/io/grpc/PickFirstBalancerFactory.java
index 2ef0d44..0c46cdd 100644
--- a/core/src/main/java/io/grpc/PickFirstBalancerFactory2.java
+++ b/core/src/main/java/io/grpc/PickFirstBalancerFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016, Google Inc. All rights reserved.
+ * 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
@@ -31,6 +31,7 @@
 
 package io.grpc;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static io.grpc.ConnectivityState.SHUTDOWN;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -39,44 +40,39 @@
 import java.util.List;
 
 /**
- * A {@link LoadBalancer2} that provides no load balancing mechanism over the
+ * A {@link LoadBalancer} that provides no load balancing mechanism over the
  * addresses from the {@link NameResolver}.  The channel's default behavior
  * (currently pick-first) is used for all addresses found.
- *
- * <p><strong>TECHNICAL PREVIEW: </strong>The name of this class is temporary. It will be renamed to
- * {@code PickFirstBalancerFactory} during <a href="https://github.com/grpc/grpc-java/issues/2656"
- * target="_blank">the transition to LBv2</a>. You should use it only if you want to experiment the
- * LBv2 code path.
  */
 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
-public final class PickFirstBalancerFactory2 extends LoadBalancer2.Factory {
+public final class PickFirstBalancerFactory extends LoadBalancer.Factory {
 
-  private static final PickFirstBalancerFactory2 INSTANCE = new PickFirstBalancerFactory2();
+  private static final PickFirstBalancerFactory INSTANCE = new PickFirstBalancerFactory();
 
-  private PickFirstBalancerFactory2() {
+  private PickFirstBalancerFactory() {
   }
 
-  public static PickFirstBalancerFactory2 getInstance() {
+  public static PickFirstBalancerFactory getInstance() {
     return INSTANCE;
   }
 
   @Override
-  public LoadBalancer2 newLoadBalancer(LoadBalancer2.Helper helper) {
+  public LoadBalancer newLoadBalancer(LoadBalancer.Helper helper) {
     return new PickFirstBalancer(helper);
   }
 
   @VisibleForTesting
-  static class PickFirstBalancer extends LoadBalancer2 {
+  static final class PickFirstBalancer extends LoadBalancer {
     private final Helper helper;
     private Subchannel subchannel;
 
-    public PickFirstBalancer(Helper helper) {
-      this.helper = helper;
+    PickFirstBalancer(Helper helper) {
+      this.helper = checkNotNull(helper, "helper");
     }
 
     @Override
-    public void handleResolvedAddresses(List<ResolvedServerInfoGroup> servers,
-        Attributes attributes) {
+    public void handleResolvedAddresses(
+        List<ResolvedServerInfoGroup> servers, Attributes attributes) {
       // Flatten servers list received from name resolver into single address group. This means that
       // as far as load balancer is concerned, there's virtually one single server with multiple
       // addresses so the connection will be created only for the first address (pick first).
@@ -123,7 +119,7 @@
           pickResult = PickResult.withError(stateInfo.getStatus());
           break;
         default:
-          throw new IllegalStateException();
+          throw new IllegalArgumentException("Unsupported state:" + currentState);
       }
 
       helper.updatePicker(new Picker(pickResult));
@@ -157,15 +153,15 @@
    * received in constructor.
    */
   @VisibleForTesting
-  static class Picker extends LoadBalancer2.SubchannelPicker {
-    private final LoadBalancer2.PickResult result;
+  static final class Picker extends LoadBalancer.SubchannelPicker {
+    private final LoadBalancer.PickResult result;
 
-    Picker(LoadBalancer2.PickResult result) {
-      this.result = result;
+    Picker(LoadBalancer.PickResult result) {
+      this.result = checkNotNull(result, "result");
     }
 
     @Override
-    public LoadBalancer2.PickResult pickSubchannel(Attributes affinity, Metadata headers) {
+    public LoadBalancer.PickResult pickSubchannel(Attributes affinity, Metadata headers) {
       return result;
     }
   }
diff --git a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
index 7c3ba42..a403e26 100644
--- a/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
+++ b/core/src/main/java/io/grpc/internal/AbstractManagedChannelImplBuilder.java
@@ -43,12 +43,12 @@
 import io.grpc.ClientInterceptor;
 import io.grpc.CompressorRegistry;
 import io.grpc.DecompressorRegistry;
-import io.grpc.LoadBalancer2;
+import io.grpc.LoadBalancer;
 import io.grpc.ManagedChannel;
 import io.grpc.ManagedChannelBuilder;
 import io.grpc.NameResolver;
 import io.grpc.NameResolverProvider;
-import io.grpc.PickFirstBalancerFactory2;
+import io.grpc.PickFirstBalancerFactory;
 import io.grpc.ResolvedServerInfo;
 import io.grpc.ResolvedServerInfoGroup;
 import java.net.SocketAddress;
@@ -108,7 +108,7 @@
   @Nullable
   private NameResolver.Factory nameResolverFactory;
 
-  private LoadBalancer2.Factory loadBalancerFactory;
+  private LoadBalancer.Factory loadBalancerFactory;
 
   @Nullable
   private DecompressorRegistry decompressorRegistry;
@@ -193,9 +193,9 @@
   }
 
   @Override
-  public final T loadBalancerFactory(LoadBalancer2.Factory loadBalancerFactory) {
+  public final T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory) {
     Preconditions.checkState(directServerAddress == null,
-        "directServerAddress is set (%s), which forbids the use of LoadBalancerFactory",
+        "directServerAddress is set (%s), which forbids the use of LoadBalancer.Factory",
         directServerAddress);
     this.loadBalancerFactory = loadBalancerFactory;
     return thisT();
@@ -231,7 +231,7 @@
     // We convert to the largest unit to avoid overflow
     if (unit.toDays(value) >= IDLE_MODE_MAX_TIMEOUT_DAYS) {
       // This disables idle mode
-      this.idleTimeoutMillis = ManagedChannelImpl2.IDLE_TIMEOUT_MILLIS_DISABLE;
+      this.idleTimeoutMillis = ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE;
     } else {
       this.idleTimeoutMillis = Math.max(unit.toMillis(value), IDLE_MODE_MIN_TIMEOUT_MILLIS);
     }
@@ -275,21 +275,25 @@
       // getResource(), then this shouldn't be a problem unless called on the UI thread.
       nameResolverFactory = NameResolverProvider.asFactory();
     }
-    return new ManagedChannelImpl2(
+    return new ManagedChannelImpl(
         target,
         // TODO(carl-mastrangelo): Allow clients to pass this in
         new ExponentialBackoffPolicy.Provider(),
         nameResolverFactory,
         getNameResolverParams(),
-        firstNonNull(loadBalancerFactory, PickFirstBalancerFactory2.getInstance()),
+        firstNonNull(loadBalancerFactory, PickFirstBalancerFactory.getInstance()),
         transportFactory,
         firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
         firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
         SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE),
         getExecutorPool(executor),
         SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
-        GrpcUtil.STOPWATCH_SUPPLIER, idleTimeoutMillis,
-        userAgent, interceptors, firstNonNull(statsFactory,
+        GrpcUtil.STOPWATCH_SUPPLIER,
+        idleTimeoutMillis,
+        userAgent,
+        interceptors,
+        firstNonNull(
+            statsFactory,
             firstNonNull(Stats.getStatsContextFactory(), NoopStatsContextFactory.INSTANCE)));
   }
 
diff --git a/core/src/main/java/io/grpc/internal/ChannelExecutor.java b/core/src/main/java/io/grpc/internal/ChannelExecutor.java
index 3bf549d..6ab8e3b 100644
--- a/core/src/main/java/io/grpc/internal/ChannelExecutor.java
+++ b/core/src/main/java/io/grpc/internal/ChannelExecutor.java
@@ -42,7 +42,7 @@
 
 /**
  * The thread-less Channel Executor used to run the state mutation logic in {@link
- * ManagedChannelImpl}, {@link InternalSubchannel} and {@link io.grpc.LoadBalancer2}s.
+ * ManagedChannelImpl}, {@link InternalSubchannel} and {@link io.grpc.LoadBalancer}s.
  *
  * <p>Tasks are queued until {@link #drain} is called.  Tasks are guaranteed to be run in the same
  * order as they are submitted.
diff --git a/core/src/main/java/io/grpc/internal/DelayedClientTransport2.java b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java
similarity index 95%
rename from core/src/main/java/io/grpc/internal/DelayedClientTransport2.java
rename to core/src/main/java/io/grpc/internal/DelayedClientTransport.java
index 3318db8..aa91dae 100644
--- a/core/src/main/java/io/grpc/internal/DelayedClientTransport2.java
+++ b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java
@@ -34,8 +34,8 @@
 import com.google.common.annotations.VisibleForTesting;
 import io.grpc.CallOptions;
 import io.grpc.Context;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
 import io.grpc.Status;
@@ -55,7 +55,7 @@
  * for that stream, at which point the ownership of the stream is transferred to the real transport,
  * thus the delayed transport stops owning the stream.
  */
-final class DelayedClientTransport2 implements ManagedClientTransport {
+final class DelayedClientTransport implements ManagedClientTransport {
   private final LogId lodId = LogId.allocate(getClass().getName());
 
   private final Object lock = new Object();
@@ -96,7 +96,7 @@
    * @param channelExecutor all listener callbacks of the delayed transport will be run from this
    *        ChannelExecutor.
    */
-  DelayedClientTransport2(Executor defaultAppExecutor, ChannelExecutor channelExecutor) {
+  DelayedClientTransport(Executor defaultAppExecutor, ChannelExecutor channelExecutor) {
     this.defaultAppExecutor = defaultAppExecutor;
     this.channelExecutor = channelExecutor;
   }
@@ -188,13 +188,16 @@
     return newStream(method, headers, CallOptions.DEFAULT, StatsTraceContext.NOOP);
   }
 
-  // Caller must call channelExecutor.drain() outside of lock because this method may schedule
-  // tasks on channelExecutor
+  /**
+   * Caller must call {@code channelExecutor.drain()} outside of lock because this method may
+   * schedule tasks on channelExecutor.
+   */
   @GuardedBy("lock")
-  private PendingStream createPendingStream(MethodDescriptor<?, ?> method, Metadata headers,
-      CallOptions callOptions, StatsTraceContext statsTraceCtx) {
-    PendingStream pendingStream = new PendingStream(method, headers, callOptions,
-        statsTraceCtx);
+  private PendingStream createPendingStream(
+      MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions,
+      StatsTraceContext statsTraceCtx) {
+    PendingStream pendingStream =
+        new PendingStream(method, headers, callOptions, statsTraceCtx);
     pendingStreams.add(pendingStream);
     if (pendingStreams.size() == 1) {
       channelExecutor.executeLater(reportTransportInUse);
diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java
index c532fe2..385551e 100644
--- a/core/src/main/java/io/grpc/internal/GrpcUtil.java
+++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java
@@ -40,8 +40,8 @@
 import com.google.common.base.Supplier;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.Subchannel;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.Subchannel;
 import io.grpc.Metadata;
 import io.grpc.Status;
 import io.grpc.internal.SharedResourceHolder.Resource;
diff --git a/core/src/main/java/io/grpc/internal/InUseStateAggregator2.java b/core/src/main/java/io/grpc/internal/InUseStateAggregator.java
similarity index 98%
rename from core/src/main/java/io/grpc/internal/InUseStateAggregator2.java
rename to core/src/main/java/io/grpc/internal/InUseStateAggregator.java
index 6333f36..9668e27 100644
--- a/core/src/main/java/io/grpc/internal/InUseStateAggregator2.java
+++ b/core/src/main/java/io/grpc/internal/InUseStateAggregator.java
@@ -38,7 +38,7 @@
  * Aggregates the in-use state of a set of objects.
  */
 @NotThreadSafe
-abstract class InUseStateAggregator2<T> {
+abstract class InUseStateAggregator<T> {
 
   private final HashSet<T> inUseObjects = new HashSet<T>();
 
diff --git a/core/src/main/java/io/grpc/internal/InternalSubchannel.java b/core/src/main/java/io/grpc/internal/InternalSubchannel.java
index d221803..1ec7f16 100644
--- a/core/src/main/java/io/grpc/internal/InternalSubchannel.java
+++ b/core/src/main/java/io/grpc/internal/InternalSubchannel.java
@@ -118,8 +118,8 @@
       new ArrayList<ConnectionClientTransport>();
 
   // Must only be used from channelExecutor
-  private final InUseStateAggregator2<ConnectionClientTransport> inUseStateAggregator =
-      new InUseStateAggregator2<ConnectionClientTransport>() {
+  private final InUseStateAggregator<ConnectionClientTransport> inUseStateAggregator =
+      new InUseStateAggregator<ConnectionClientTransport>() {
         @Override
         void handleInUse() {
           callback.onInUse(InternalSubchannel.this);
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl2.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
similarity index 96%
rename from core/src/main/java/io/grpc/internal/ManagedChannelImpl2.java
rename to core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
index 04b7474..bc75ea1 100644
--- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl2.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -51,9 +51,9 @@
 import io.grpc.ConnectivityStateInfo;
 import io.grpc.DecompressorRegistry;
 import io.grpc.EquivalentAddressGroup;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
@@ -81,8 +81,8 @@
 
 /** A communication channel for making outgoing RPCs. */
 @ThreadSafe
-public final class ManagedChannelImpl2 extends ManagedChannel implements WithLogId {
-  private static final Logger log = Logger.getLogger(ManagedChannelImpl2.class.getName());
+public final class ManagedChannelImpl extends ManagedChannel implements WithLogId {
+  private static final Logger log = Logger.getLogger(ManagedChannelImpl.class.getName());
 
   // Matching this pattern means the target string is a URI target or at least intended to be one.
   // A URI target must be an absolute hierarchical URI.
@@ -102,7 +102,7 @@
   private final String target;
   private final NameResolver.Factory nameResolverFactory;
   private final Attributes nameResolverParams;
-  private final LoadBalancer2.Factory loadBalancerFactory;
+  private final LoadBalancer.Factory loadBalancerFactory;
   private final ClientTransportFactory transportFactory;
   private final Executor executor;
   private final ObjectPool<? extends Executor> executorPool;
@@ -140,7 +140,7 @@
 
   // null when channel is in idle mode.  Must be assigned from channelExecutor.
   @Nullable
-  private LoadBalancer2 loadBalancer;
+  private LoadBalancer loadBalancer;
 
   // Must be assigned from channelExecutor.  null if channel is in idle mode.
   @Nullable
@@ -155,7 +155,7 @@
   private final Set<InternalSubchannel> oobChannels = new HashSet<InternalSubchannel>(1, .75f);
 
   // reprocess() must be run from channelExecutor
-  private final DelayedClientTransport2 delayedTransport;
+  private final DelayedClientTransport delayedTransport;
 
   // Shutdown states.
   //
@@ -234,8 +234,8 @@
 
   // Must be accessed from channelExecutor
   @VisibleForTesting
-  final InUseStateAggregator2<Object> inUseStateAggregator =
-      new InUseStateAggregator2<Object>() {
+  final InUseStateAggregator<Object> inUseStateAggregator =
+      new InUseStateAggregator<Object>() {
         @Override
         void handleInUse() {
           exitIdleMode();
@@ -381,9 +381,9 @@
     }
   };
 
-  ManagedChannelImpl2(String target, BackoffPolicy.Provider backoffPolicyProvider,
+  ManagedChannelImpl(String target, BackoffPolicy.Provider backoffPolicyProvider,
       NameResolver.Factory nameResolverFactory, Attributes nameResolverParams,
-      LoadBalancer2.Factory loadBalancerFactory, ClientTransportFactory transportFactory,
+      LoadBalancer.Factory loadBalancerFactory, ClientTransportFactory transportFactory,
       DecompressorRegistry decompressorRegistry, CompressorRegistry compressorRegistry,
       ObjectPool<ScheduledExecutorService> timerServicePool,
       ObjectPool<? extends Executor> executorPool, ObjectPool<? extends Executor> oobExecutorPool,
@@ -398,7 +398,7 @@
     this.executorPool = checkNotNull(executorPool, "executorPool");
     this.oobExecutorPool = checkNotNull(oobExecutorPool, "oobExecutorPool");
     this.executor = checkNotNull(executorPool.getObject(), "executor");
-    this.delayedTransport = new DelayedClientTransport2(this.executor, this.channelExecutor);
+    this.delayedTransport = new DelayedClientTransport(this.executor, this.channelExecutor);
     this.delayedTransport.start(delayedTransportListener);
     this.backoffPolicyProvider = backoffPolicyProvider;
     this.transportFactory =
@@ -473,7 +473,7 @@
    * cancelled.
    */
   @Override
-  public ManagedChannelImpl2 shutdown() {
+  public ManagedChannelImpl shutdown() {
     log.log(Level.FINE, "[{0}] shutdown() called", getLogId());
     if (!shutdown.compareAndSet(false, true)) {
       return this;
@@ -495,7 +495,7 @@
    * return {@code false} immediately after this method returns.
    */
   @Override
-  public ManagedChannelImpl2 shutdownNow() {
+  public ManagedChannelImpl shutdownNow() {
     log.log(Level.FINE, "[{0}] shutdownNow() called", getLogId());
     shutdown();
     delayedTransport.shutdownNow(SHUTDOWN_NOW_STATUS);
@@ -547,7 +547,7 @@
         CallOptions callOptions) {
       Executor executor = callOptions.getExecutor();
       if (executor == null) {
-        executor = ManagedChannelImpl2.this.executor;
+        executor = ManagedChannelImpl.this.executor;
       }
       StatsTraceContext statsTraceCtx = StatsTraceContext.newClientContext(
           method.getFullMethodName(), statsFactory, stopwatchSupplier);
@@ -588,8 +588,8 @@
     }
   }
 
-  private class LbHelperImpl extends LoadBalancer2.Helper {
-    LoadBalancer2 lb;
+  private class LbHelperImpl extends LoadBalancer.Helper {
+    LoadBalancer lb;
     final NameResolver nr;
 
     LbHelperImpl(NameResolver nr) {
@@ -702,7 +702,7 @@
 
     @Override
     public String getAuthority() {
-      return ManagedChannelImpl2.this.authority();
+      return ManagedChannelImpl.this.authority();
     }
 
     @Override
@@ -733,8 +733,8 @@
   }
 
   private class NameResolverListenerImpl implements NameResolver.Listener {
-    final LoadBalancer2 balancer;
-    final LoadBalancer2.Helper helper;
+    final LoadBalancer balancer;
+    final LoadBalancer.Helper helper;
 
     NameResolverListenerImpl(LbHelperImpl helperImpl) {
       this.balancer = helperImpl.lb;
diff --git a/core/src/main/java/io/grpc/internal/OobChannel.java b/core/src/main/java/io/grpc/internal/OobChannel.java
index 0dfdfed..996f0e9 100644
--- a/core/src/main/java/io/grpc/internal/OobChannel.java
+++ b/core/src/main/java/io/grpc/internal/OobChannel.java
@@ -41,9 +41,9 @@
 import io.grpc.ClientCall;
 import io.grpc.ConnectivityStateInfo;
 import io.grpc.EquivalentAddressGroup;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
@@ -58,7 +58,7 @@
 import javax.annotation.concurrent.ThreadSafe;
 
 /**
- * A ManagedChannel backed by a single {@link InternalSubchannel} and used for {@link LoadBalancer2}
+ * A ManagedChannel backed by a single {@link InternalSubchannel} and used for {@link LoadBalancer}
  * to its own RPC needs.
  */
 @ThreadSafe
@@ -71,7 +71,7 @@
   private final LogId logId = LogId.allocate(getClass().getName());
   private final StatsContextFactory statsFactory;
   private final String authority;
-  private final DelayedClientTransport2 delayedTransport;
+  private final DelayedClientTransport delayedTransport;
   private final ObjectPool<? extends Executor> executorPool;
   private final Executor executor;
   private final ScheduledExecutorService deadlineCancellationExecutor;
@@ -100,7 +100,7 @@
     this.deadlineCancellationExecutor = checkNotNull(
         deadlineCancellationExecutor, "deadlineCancellationExecutor");
     this.stopwatchSupplier = checkNotNull(stopwatchSupplier, "stopwatchSupplier");
-    this.delayedTransport = new DelayedClientTransport2(executor, channelExecutor);
+    this.delayedTransport = new DelayedClientTransport(executor, channelExecutor);
     this.delayedTransport.start(new ManagedClientTransport.Listener() {
         @Override
         public void transportShutdown(Status s) {
diff --git a/core/src/main/java/io/grpc/internal/SubchannelImpl.java b/core/src/main/java/io/grpc/internal/SubchannelImpl.java
index c352187..1a966ae 100644
--- a/core/src/main/java/io/grpc/internal/SubchannelImpl.java
+++ b/core/src/main/java/io/grpc/internal/SubchannelImpl.java
@@ -31,14 +31,14 @@
 
 package io.grpc.internal;
 
-import io.grpc.LoadBalancer2;
+import io.grpc.LoadBalancer;
 import javax.annotation.Nullable;
 
 /**
  * The base interface of the Subchannels returned by {@link
- * io.grpc.LoadBalancer2.Helper#createSubchannel}.
+ * io.grpc.LoadBalancer.Helper#createSubchannel}.
  */
-abstract class SubchannelImpl extends LoadBalancer2.Subchannel {
+abstract class SubchannelImpl extends LoadBalancer.Subchannel {
   /**
    * Same as {@link InternalSubchannel#obtainActiveTransport}.
    */
diff --git a/core/src/main/java/io/grpc/util/RoundRobinLoadBalancerFactory2.java b/core/src/main/java/io/grpc/util/RoundRobinLoadBalancerFactory.java
similarity index 87%
rename from core/src/main/java/io/grpc/util/RoundRobinLoadBalancerFactory2.java
rename to core/src/main/java/io/grpc/util/RoundRobinLoadBalancerFactory.java
index 072a531..20b36bb 100644
--- a/core/src/main/java/io/grpc/util/RoundRobinLoadBalancerFactory2.java
+++ b/core/src/main/java/io/grpc/util/RoundRobinLoadBalancerFactory.java
@@ -41,10 +41,10 @@
 import io.grpc.ConnectivityStateInfo;
 import io.grpc.EquivalentAddressGroup;
 import io.grpc.ExperimentalApi;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.Subchannel;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.Subchannel;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.Metadata;
 import io.grpc.NameResolver;
 import io.grpc.ResolvedServerInfo;
@@ -64,35 +64,30 @@
 import javax.annotation.concurrent.GuardedBy;
 
 /**
- * A {@link LoadBalancer2} that provides round-robin load balancing mechanism over the
+ * A {@link LoadBalancer} that provides round-robin load balancing mechanism over the
  * addresses from the {@link NameResolver}.  The sub-lists received from the name resolver
  * are considered to be an {@link EquivalentAddressGroup} and each of these sub-lists is
  * what is then balanced across.
- *
- * <p><strong>TECHNICAL PREVIEW: </strong>The name of this class is temporary. It will be renamed to
- * {@code RoundRobinLoadBalancerFactory} during the
- * <a href="https://github.com/grpc/grpc-java/issues/2656" target="_blank">transition to LBv2</a>.
- * You should use it only if you want to experiment the LBv2 code path.
  */
 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
-public class RoundRobinLoadBalancerFactory2 extends LoadBalancer2.Factory {
-  private static final RoundRobinLoadBalancerFactory2 INSTANCE =
-      new RoundRobinLoadBalancerFactory2();
+public class RoundRobinLoadBalancerFactory extends LoadBalancer.Factory {
+  private static final RoundRobinLoadBalancerFactory INSTANCE =
+      new RoundRobinLoadBalancerFactory();
 
-  private RoundRobinLoadBalancerFactory2() {
+  private RoundRobinLoadBalancerFactory() {
   }
 
-  public static RoundRobinLoadBalancerFactory2 getInstance() {
+  public static RoundRobinLoadBalancerFactory getInstance() {
     return INSTANCE;
   }
 
   @Override
-  public LoadBalancer2 newLoadBalancer(LoadBalancer2.Helper helper) {
+  public LoadBalancer newLoadBalancer(LoadBalancer.Helper helper) {
     return new RoundRobinLoadBalancer(helper);
   }
 
   @VisibleForTesting
-  static class RoundRobinLoadBalancer extends LoadBalancer2 {
+  static class RoundRobinLoadBalancer extends LoadBalancer {
     private final Helper helper;
     private final Map<EquivalentAddressGroup, Subchannel> subchannels =
         new HashMap<EquivalentAddressGroup, Subchannel>();
@@ -101,13 +96,13 @@
     static final Attributes.Key<AtomicReference<ConnectivityStateInfo>> STATE_INFO =
         Attributes.Key.of("state-info");
 
-    public RoundRobinLoadBalancer(Helper helper) {
-      this.helper = helper;
+    RoundRobinLoadBalancer(Helper helper) {
+      this.helper = checkNotNull(helper, "helper");
     }
 
     @Override
-    public void handleResolvedAddresses(List<ResolvedServerInfoGroup> servers,
-        Attributes attributes) {
+    public void handleResolvedAddresses(
+        List<ResolvedServerInfoGroup> servers, Attributes attributes) {
       Set<EquivalentAddressGroup> currentAddrs = subchannels.keySet();
       Set<EquivalentAddressGroup> latestAddrs =
           resolvedServerInfoGroupToEquivalentAddressGroup(servers);
@@ -237,7 +232,7 @@
   }
 
   @VisibleForTesting
-  static class Picker extends SubchannelPicker {
+  static final class Picker extends SubchannelPicker {
     @Nullable
     private final Status status;
     private final List<Subchannel> list;
diff --git a/core/src/test/java/io/grpc/PickFirstLoadBalancer2Test.java b/core/src/test/java/io/grpc/PickFirstLoadBalancerTest.java
similarity index 96%
rename from core/src/test/java/io/grpc/PickFirstLoadBalancer2Test.java
rename to core/src/test/java/io/grpc/PickFirstLoadBalancerTest.java
index 541f6da..d8d1505 100644
--- a/core/src/test/java/io/grpc/PickFirstLoadBalancer2Test.java
+++ b/core/src/test/java/io/grpc/PickFirstLoadBalancerTest.java
@@ -44,11 +44,11 @@
 import static org.mockito.Mockito.when;
 
 import com.google.common.collect.Lists;
-import io.grpc.LoadBalancer2.Helper;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.Subchannel;
-import io.grpc.PickFirstBalancerFactory2.PickFirstBalancer;
-import io.grpc.PickFirstBalancerFactory2.Picker;
+import io.grpc.LoadBalancer.Helper;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.Subchannel;
+import io.grpc.PickFirstBalancerFactory.PickFirstBalancer;
+import io.grpc.PickFirstBalancerFactory.Picker;
 import java.net.SocketAddress;
 import java.util.List;
 import org.junit.Before;
@@ -62,9 +62,9 @@
 import org.mockito.MockitoAnnotations;
 
 
-/** Unit test for {@link PickFirstBalancerFactory2}. */
+/** Unit test for {@link PickFirstBalancerFactory}. */
 @RunWith(JUnit4.class)
-public class PickFirstLoadBalancer2Test {
+public class PickFirstLoadBalancerTest {
   private PickFirstBalancer loadBalancer;
   private List<ResolvedServerInfoGroup> servers = Lists.newArrayList();
   private List<SocketAddress> socketAddresses = Lists.newArrayList();
@@ -96,7 +96,7 @@
     when(mockHelper.createSubchannel(any(EquivalentAddressGroup.class), any(Attributes.class)))
         .thenReturn(mockSubchannel);
 
-    loadBalancer = (PickFirstBalancer) PickFirstBalancerFactory2.getInstance().newLoadBalancer(
+    loadBalancer = (PickFirstBalancer) PickFirstBalancerFactory.getInstance().newLoadBalancer(
         mockHelper);
   }
 
diff --git a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java
index c825a5f..3413e77 100644
--- a/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java
+++ b/core/src/test/java/io/grpc/internal/AbstractManagedChannelImplBuilderTest.java
@@ -78,11 +78,11 @@
         builder.getIdleTimeoutMillis());
 
     builder.idleTimeout(Long.MAX_VALUE, TimeUnit.DAYS);
-    assertEquals(ManagedChannelImpl2.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis());
+    assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis());
 
     builder.idleTimeout(AbstractManagedChannelImplBuilder.IDLE_MODE_MAX_TIMEOUT_DAYS,
         TimeUnit.DAYS);
-    assertEquals(ManagedChannelImpl2.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis());
+    assertEquals(ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, builder.getIdleTimeoutMillis());
 
     try {
       builder.idleTimeout(0, TimeUnit.SECONDS);
diff --git a/core/src/test/java/io/grpc/internal/DelayedClientTransport2Test.java b/core/src/test/java/io/grpc/internal/DelayedClientTransportTest.java
similarity index 98%
rename from core/src/test/java/io/grpc/internal/DelayedClientTransport2Test.java
rename to core/src/test/java/io/grpc/internal/DelayedClientTransportTest.java
index a2c503d..39f7aee 100644
--- a/core/src/test/java/io/grpc/internal/DelayedClientTransport2Test.java
+++ b/core/src/test/java/io/grpc/internal/DelayedClientTransportTest.java
@@ -51,8 +51,8 @@
 import io.grpc.Attributes;
 import io.grpc.CallOptions;
 import io.grpc.IntegerMarshaller;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
 import io.grpc.MethodDescriptor.MethodType;
@@ -76,10 +76,10 @@
 import org.mockito.stubbing.Answer;
 
 /**
- * Unit tests for {@link DelayedClientTransport2}.
+ * Unit tests for {@link DelayedClientTransport}.
  */
 @RunWith(JUnit4.class)
-public class DelayedClientTransport2Test {
+public class DelayedClientTransportTest {
   @Mock private ManagedClientTransport.Listener transportListener;
   @Mock private SubchannelPicker mockPicker;
   @Mock private SubchannelImpl mockSubchannel;
@@ -117,7 +117,7 @@
 
   private final FakeClock fakeExecutor = new FakeClock();
 
-  private final DelayedClientTransport2 delayedTransport = new DelayedClientTransport2(
+  private final DelayedClientTransport delayedTransport = new DelayedClientTransport(
       fakeExecutor.getScheduledExecutorService(), new ChannelExecutor());
 
   @Before public void setUp() {
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java
index 3e57b62..cd6d599 100644
--- a/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplGetNameResolverTest.java
@@ -43,7 +43,7 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-/** Unit tests for {@link ManagedChannelImpl2#getNameResolver}. */
+/** Unit tests for {@link ManagedChannelImpl#getNameResolver}. */
 @RunWith(JUnit4.class)
 public class ManagedChannelImplGetNameResolverTest {
   private static final Attributes NAME_RESOLVER_PARAMS =
@@ -121,7 +121,7 @@
       }
     };
     try {
-      ManagedChannelImpl2.getNameResolver(
+      ManagedChannelImpl.getNameResolver(
           "foo.googleapis.com:8080", nameResolverFactory, NAME_RESOLVER_PARAMS);
       fail("Should fail");
     } catch (IllegalArgumentException e) {
@@ -131,7 +131,7 @@
 
   private void testValidTarget(String target, String expectedUriString, URI expectedUri) {
     Factory nameResolverFactory = new FakeNameResolverFactory(expectedUri.getScheme());
-    FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl2.getNameResolver(
+    FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver(
         target, nameResolverFactory, NAME_RESOLVER_PARAMS);
     assertNotNull(nameResolver);
     assertEquals(expectedUri, nameResolver.uri);
@@ -142,7 +142,7 @@
     Factory nameResolverFactory = new FakeNameResolverFactory("dns");
 
     try {
-      FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl2.getNameResolver(
+      FakeNameResolver nameResolver = (FakeNameResolver) ManagedChannelImpl.getNameResolver(
           target, nameResolverFactory, NAME_RESOLVER_PARAMS);
       fail("Should have failed, but got resolver with " + nameResolver.uri);
     } catch (IllegalArgumentException e) {
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImpl2IdlenessTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java
similarity index 96%
rename from core/src/test/java/io/grpc/internal/ManagedChannelImpl2IdlenessTest.java
rename to core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java
index f3b64bb..d205038 100644
--- a/core/src/test/java/io/grpc/internal/ManagedChannelImpl2IdlenessTest.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplIdlenessTest.java
@@ -52,11 +52,11 @@
 import io.grpc.DecompressorRegistry;
 import io.grpc.EquivalentAddressGroup;
 import io.grpc.IntegerMarshaller;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.Helper;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.Subchannel;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.Helper;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.Subchannel;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
@@ -90,14 +90,14 @@
  * Unit tests for {@link ManagedChannelImpl}'s idle mode.
  */
 @RunWith(JUnit4.class)
-public class ManagedChannelImpl2IdlenessTest {
+public class ManagedChannelImplIdlenessTest {
   private final FakeClock timer = new FakeClock();
   private final FakeClock executor = new FakeClock();
   private final FakeClock oobExecutor = new FakeClock();
   private static final String AUTHORITY = "fakeauthority";
   private static final String USER_AGENT = "fakeagent";
   private static final long IDLE_TIMEOUT_SECONDS = 30;
-  private ManagedChannelImpl2 channel;
+  private ManagedChannelImpl channel;
 
   private final MethodDescriptor<String, Integer> method =
       MethodDescriptor.<String, Integer>newBuilder()
@@ -115,8 +115,8 @@
   @Mock private ObjectPool<Executor> executorPool;
   @Mock private ObjectPool<Executor> oobExecutorPool;
   @Mock private ClientTransportFactory mockTransportFactory;
-  @Mock private LoadBalancer2 mockLoadBalancer;
-  @Mock private LoadBalancer2.Factory mockLoadBalancerFactory;
+  @Mock private LoadBalancer mockLoadBalancer;
+  @Mock private LoadBalancer.Factory mockLoadBalancerFactory;
   @Mock private NameResolver mockNameResolver;
   @Mock private NameResolver.Factory mockNameResolverFactory;
   @Mock private ClientCall.Listener<Integer> mockCallListener;
@@ -136,7 +136,7 @@
         .newNameResolver(any(URI.class), any(Attributes.class)))
         .thenReturn(mockNameResolver);
 
-    channel = new ManagedChannelImpl2("fake://target", new FakeBackoffPolicyProvider(),
+    channel = new ManagedChannelImpl("fake://target", new FakeBackoffPolicyProvider(),
         mockNameResolverFactory, Attributes.EMPTY, mockLoadBalancerFactory,
         mockTransportFactory, DecompressorRegistry.getDefaultInstance(),
         CompressorRegistry.getDefaultInstance(), timerServicePool, executorPool, oobExecutorPool,
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImpl2Test.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
similarity index 96%
rename from core/src/test/java/io/grpc/internal/ManagedChannelImpl2Test.java
rename to core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
index af2586a..8bca0a4 100644
--- a/core/src/test/java/io/grpc/internal/ManagedChannelImpl2Test.java
+++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
@@ -71,11 +71,11 @@
 import io.grpc.DecompressorRegistry;
 import io.grpc.EquivalentAddressGroup;
 import io.grpc.IntegerMarshaller;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.Helper;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.Subchannel;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.Helper;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.Subchannel;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
@@ -116,9 +116,9 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-/** Unit tests for {@link ManagedChannelImpl2}. */
+/** Unit tests for {@link ManagedChannelImpl}. */
 @RunWith(JUnit4.class)
-public class ManagedChannelImpl2Test {
+public class ManagedChannelImplTest {
   private static final List<ClientInterceptor> NO_INTERCEPTOR =
       Collections.<ClientInterceptor>emptyList();
   private static final Attributes NAME_RESOLVER_PARAMS =
@@ -147,16 +147,16 @@
 
   @Rule public final ExpectedException thrown = ExpectedException.none();
 
-  private ManagedChannelImpl2 channel;
+  private ManagedChannelImpl channel;
   private Helper helper;
   @Captor
   private ArgumentCaptor<Status> statusCaptor;
   @Captor
   private ArgumentCaptor<StatsTraceContext> statsTraceCtxCaptor;
   @Mock
-  private LoadBalancer2.Factory mockLoadBalancerFactory;
+  private LoadBalancer.Factory mockLoadBalancerFactory;
   @Mock
-  private LoadBalancer2 mockLoadBalancer;
+  private LoadBalancer mockLoadBalancer;
   @Captor
   private ArgumentCaptor<ConnectivityStateInfo> stateInfoCaptor;
   @Mock
@@ -188,11 +188,11 @@
 
   private void createChannel(
       NameResolver.Factory nameResolverFactory, List<ClientInterceptor> interceptors) {
-    channel = new ManagedChannelImpl2(target, new FakeBackoffPolicyProvider(),
+    channel = new ManagedChannelImpl(target, new FakeBackoffPolicyProvider(),
         nameResolverFactory, NAME_RESOLVER_PARAMS, mockLoadBalancerFactory,
         mockTransportFactory, DecompressorRegistry.getDefaultInstance(),
         CompressorRegistry.getDefaultInstance(), timerServicePool, executorPool, oobExecutorPool,
-        timer.getStopwatchSupplier(),  ManagedChannelImpl2.IDLE_TIMEOUT_MILLIS_DISABLE, userAgent,
+        timer.getStopwatchSupplier(),  ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE, userAgent,
         interceptors, statsCtxFactory);
     // Force-exit the initial idle-mode
     channel.exitIdleMode();
@@ -365,7 +365,7 @@
       assertTrue(nameResolverFactory.resolvers.get(0).shutdown);
       // call should have been aborted by delayed transport
       executor.runDueTasks();
-      verify(mockCallListener).onClose(same(ManagedChannelImpl2.SHUTDOWN_NOW_STATUS),
+      verify(mockCallListener).onClose(same(ManagedChannelImpl.SHUTDOWN_NOW_STATUS),
           any(Metadata.class));
     } else {
       // LoadBalancer and NameResolver are still running.
@@ -389,7 +389,7 @@
 
     if (shutdownNow) {
       // Channel shutdownNow() all subchannels after shutting down LoadBalancer
-      verify(mockTransport).shutdownNow(ManagedChannelImpl2.SHUTDOWN_NOW_STATUS);
+      verify(mockTransport).shutdownNow(ManagedChannelImpl.SHUTDOWN_NOW_STATUS);
     } else {
       verify(mockTransport, never()).shutdownNow(any(Status.class));
     }
@@ -755,7 +755,7 @@
 
     // shutdown() has a delay
     sub1.shutdown();
-    timer.forwardTime(ManagedChannelImpl2.SUBCHANNEL_SHUTDOWN_DELAY_SECONDS - 1, TimeUnit.SECONDS);
+    timer.forwardTime(ManagedChannelImpl.SUBCHANNEL_SHUTDOWN_DELAY_SECONDS - 1, TimeUnit.SECONDS);
     sub1.shutdown();
     verify(transportInfo1.transport, never()).shutdown();
     timer.forwardTime(1, TimeUnit.SECONDS);
@@ -991,12 +991,12 @@
 
   @Test
   public void uriPattern() {
-    assertTrue(ManagedChannelImpl2.URI_PATTERN.matcher("a:/").matches());
-    assertTrue(ManagedChannelImpl2.URI_PATTERN.matcher("Z019+-.:/!@ #~ ").matches());
-    assertFalse(ManagedChannelImpl2.URI_PATTERN.matcher("a/:").matches()); // "/:" not matched
-    assertFalse(ManagedChannelImpl2.URI_PATTERN.matcher("0a:/").matches()); // '0' not matched
-    assertFalse(ManagedChannelImpl2.URI_PATTERN.matcher("a,:/").matches()); // ',' not matched
-    assertFalse(ManagedChannelImpl2.URI_PATTERN.matcher(" a:/").matches()); // space not matched
+    assertTrue(ManagedChannelImpl.URI_PATTERN.matcher("a:/").matches());
+    assertTrue(ManagedChannelImpl.URI_PATTERN.matcher("Z019+-.:/!@ #~ ").matches());
+    assertFalse(ManagedChannelImpl.URI_PATTERN.matcher("a/:").matches()); // "/:" not matched
+    assertFalse(ManagedChannelImpl.URI_PATTERN.matcher("0a:/").matches()); // '0' not matched
+    assertFalse(ManagedChannelImpl.URI_PATTERN.matcher("a,:/").matches()); // ',' not matched
+    assertFalse(ManagedChannelImpl.URI_PATTERN.matcher(" a:/").matches()); // space not matched
   }
 
   /**
diff --git a/core/src/test/java/io/grpc/util/RoundRobinLoadBalancer2Test.java b/core/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java
similarity index 95%
rename from core/src/test/java/io/grpc/util/RoundRobinLoadBalancer2Test.java
rename to core/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java
index fb28afa..d260919 100644
--- a/core/src/test/java/io/grpc/util/RoundRobinLoadBalancer2Test.java
+++ b/core/src/test/java/io/grpc/util/RoundRobinLoadBalancerTest.java
@@ -34,7 +34,7 @@
 import static com.google.common.truth.Truth.assertThat;
 import static io.grpc.ConnectivityState.IDLE;
 import static io.grpc.ConnectivityState.READY;
-import static io.grpc.util.RoundRobinLoadBalancerFactory2.RoundRobinLoadBalancer.STATE_INFO;
+import static io.grpc.util.RoundRobinLoadBalancerFactory.RoundRobinLoadBalancer.STATE_INFO;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.mockito.Matchers.any;
@@ -53,15 +53,15 @@
 import io.grpc.ConnectivityState;
 import io.grpc.ConnectivityStateInfo;
 import io.grpc.EquivalentAddressGroup;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.Helper;
-import io.grpc.LoadBalancer2.Subchannel;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.Helper;
+import io.grpc.LoadBalancer.Subchannel;
 import io.grpc.Metadata;
 import io.grpc.ResolvedServerInfo;
 import io.grpc.ResolvedServerInfoGroup;
 import io.grpc.Status;
-import io.grpc.util.RoundRobinLoadBalancerFactory2.Picker;
-import io.grpc.util.RoundRobinLoadBalancerFactory2.RoundRobinLoadBalancer;
+import io.grpc.util.RoundRobinLoadBalancerFactory.Picker;
+import io.grpc.util.RoundRobinLoadBalancerFactory.RoundRobinLoadBalancer;
 import java.net.SocketAddress;
 import java.util.Collections;
 import java.util.List;
@@ -79,9 +79,9 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-/** Unit test for {@link RoundRobinLoadBalancerFactory2}. */
+/** Unit test for {@link RoundRobinLoadBalancerFactory}. */
 @RunWith(JUnit4.class)
-public class RoundRobinLoadBalancer2Test {
+public class RoundRobinLoadBalancerTest {
   private RoundRobinLoadBalancer loadBalancer;
   private Map<ResolvedServerInfoGroup, EquivalentAddressGroup> servers = Maps.newHashMap();
   private Map<EquivalentAddressGroup, Subchannel> subchannels = Maps.newLinkedHashMap();
@@ -117,7 +117,7 @@
           }
         });
 
-    loadBalancer = (RoundRobinLoadBalancer) RoundRobinLoadBalancerFactory2.getInstance()
+    loadBalancer = (RoundRobinLoadBalancer) RoundRobinLoadBalancerFactory.getInstance()
         .newLoadBalancer(mockHelper);
   }
 
@@ -323,7 +323,7 @@
     Status error = Status.NOT_FOUND.withDescription("nameResolutionError");
     loadBalancer.handleNameResolutionError(error);
     verify(mockHelper).updatePicker(pickerCaptor.capture());
-    LoadBalancer2.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(Attributes.EMPTY,
+    LoadBalancer.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(Attributes.EMPTY,
         new Metadata());
     assertNull(pickResult.getSubchannel());
     assertEquals(error, pickResult.getStatus());
@@ -341,12 +341,12 @@
         any(Attributes.class));
     verify(mockHelper, times(2)).updatePicker(pickerCaptor.capture());
 
-    LoadBalancer2.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(Attributes.EMPTY,
+    LoadBalancer.PickResult pickResult = pickerCaptor.getValue().pickSubchannel(Attributes.EMPTY,
         new Metadata());
     assertEquals(readySubchannel, pickResult.getSubchannel());
     assertEquals(Status.OK.getCode(), pickResult.getStatus().getCode());
 
-    LoadBalancer2.PickResult pickResult2 = pickerCaptor.getValue().pickSubchannel(Attributes.EMPTY,
+    LoadBalancer.PickResult pickResult2 = pickerCaptor.getValue().pickSubchannel(Attributes.EMPTY,
         new Metadata());
     assertEquals(readySubchannel, pickResult2.getSubchannel());
     verifyNoMoreInteractions(mockHelper);
diff --git a/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer2.java b/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer.java
similarity index 97%
rename from grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer2.java
rename to grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer.java
index d3b9507..63fa54b 100644
--- a/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer2.java
+++ b/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer.java
@@ -43,7 +43,7 @@
 import io.grpc.Attributes;
 import io.grpc.ConnectivityStateInfo;
 import io.grpc.EquivalentAddressGroup;
-import io.grpc.LoadBalancer2;
+import io.grpc.LoadBalancer;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.ResolvedServerInfoGroup;
@@ -67,13 +67,13 @@
 import javax.annotation.Nullable;
 
 /**
- * A {@link LoadBalancer2} that uses the GRPCLB protocol.
+ * A {@link LoadBalancer} that uses the GRPCLB protocol.
  *
  * <p>Optionally, when requested by the naming system, will delegate the work to a local pick-first
  * or round-robin balancer.
  */
-class GrpclbLoadBalancer2 extends LoadBalancer2 implements WithLogId {
-  private static final Logger logger = Logger.getLogger(GrpclbLoadBalancer2.class.getName());
+class GrpclbLoadBalancer extends LoadBalancer implements WithLogId {
+  private static final Logger logger = Logger.getLogger(GrpclbLoadBalancer.class.getName());
 
   @VisibleForTesting
   static final SubchannelPicker BUFFER_PICKER = new SubchannelPicker() {
@@ -104,7 +104,7 @@
 
   // If not null, all work is delegated to it.
   @Nullable
-  private LoadBalancer2 delegate;
+  private LoadBalancer delegate;
   private LbPolicy lbPolicy;
 
   ///////////////////////////////////////////////////////////////////////////////
@@ -128,7 +128,7 @@
   // A null element indicate a simulated error for throttling purpose
   private List<EquivalentAddressGroup> roundRobinList = Collections.emptyList();
 
-  GrpclbLoadBalancer2(Helper helper, Factory pickFirstBalancerFactory,
+  GrpclbLoadBalancer(Helper helper, Factory pickFirstBalancerFactory,
       Factory roundRobinBalancerFactory) {
     this.helper = checkNotNull(helper, "helper");
     this.serviceName = checkNotNull(helper.getAuthority(), "helper returns null authority");
@@ -450,7 +450,7 @@
   }
 
   @VisibleForTesting
-  LoadBalancer2 getDelegate() {
+  LoadBalancer getDelegate() {
     return delegate;
   }
 
diff --git a/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancerFactory2.java b/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancerFactory.java
similarity index 65%
rename from grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancerFactory2.java
rename to grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancerFactory.java
index 3471265..8ac2ffe 100644
--- a/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancerFactory2.java
+++ b/grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancerFactory.java
@@ -32,36 +32,32 @@
 package io.grpc.grpclb;
 
 import io.grpc.ExperimentalApi;
-import io.grpc.LoadBalancer2;
-import io.grpc.PickFirstBalancerFactory2;
-import io.grpc.util.RoundRobinLoadBalancerFactory2;
+import io.grpc.LoadBalancer;
+import io.grpc.PickFirstBalancerFactory;
+import io.grpc.util.RoundRobinLoadBalancerFactory;
 
 /**
- * A factory for {@link LoadBalancer2}s that uses the GRPCLB protocol.
- *
- * <p><strong>TECHNICAL PREVIEW: </strong>The name of this class is temporary. It will be renamed to
- * {@code GrpclbLoadBalancerFactory} during <a href="https://github.com/grpc/grpc-java/issues/2656">
- * transition to LBv2</a>. You should use it only if you want to experiment the LBv2 code path.
+ * A factory for {@link LoadBalancer}s that uses the GRPCLB protocol.
  *
  * <p><b>Experimental:</b>This only works with the GRPCLB load-balancer service, which is not
  * available yet. Right now it's only good for internal testing.
  */
 @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1782")
-public class GrpclbLoadBalancerFactory2 extends LoadBalancer2.Factory {
+public class GrpclbLoadBalancerFactory extends LoadBalancer.Factory {
 
-  private static final GrpclbLoadBalancerFactory2 instance = new GrpclbLoadBalancerFactory2();
+  private static final GrpclbLoadBalancerFactory instance = new GrpclbLoadBalancerFactory();
 
-  private GrpclbLoadBalancerFactory2() {
+  private GrpclbLoadBalancerFactory() {
   }
 
-  public static GrpclbLoadBalancerFactory2 getInstance() {
+  public static GrpclbLoadBalancerFactory getInstance() {
     return instance;
   }
 
   @Override
-  public LoadBalancer2 newLoadBalancer(LoadBalancer2.Helper helper) {
-    return new GrpclbLoadBalancer2(
-        helper, PickFirstBalancerFactory2.getInstance(),
-        RoundRobinLoadBalancerFactory2.getInstance());
+  public LoadBalancer newLoadBalancer(LoadBalancer.Helper helper) {
+    return new GrpclbLoadBalancer(
+        helper, PickFirstBalancerFactory.getInstance(),
+        RoundRobinLoadBalancerFactory.getInstance());
   }
 }
diff --git a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancer2Test.java b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java
similarity index 96%
rename from grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancer2Test.java
rename to grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java
index 28d25fd..a99e0db 100644
--- a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancer2Test.java
+++ b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java
@@ -62,11 +62,11 @@
 import io.grpc.CallOptions;
 import io.grpc.ConnectivityStateInfo;
 import io.grpc.EquivalentAddressGroup;
-import io.grpc.LoadBalancer2;
-import io.grpc.LoadBalancer2.Helper;
-import io.grpc.LoadBalancer2.PickResult;
-import io.grpc.LoadBalancer2.Subchannel;
-import io.grpc.LoadBalancer2.SubchannelPicker;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancer.Helper;
+import io.grpc.LoadBalancer.PickResult;
+import io.grpc.LoadBalancer.Subchannel;
+import io.grpc.LoadBalancer.SubchannelPicker;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
 import io.grpc.MethodDescriptor;
@@ -76,8 +76,8 @@
 import io.grpc.Status;
 import io.grpc.StatusRuntimeException;
 import io.grpc.grpclb.GrpclbConstants.LbPolicy;
-import io.grpc.grpclb.GrpclbLoadBalancer2.ErrorPicker;
-import io.grpc.grpclb.GrpclbLoadBalancer2.RoundRobinPicker;
+import io.grpc.grpclb.GrpclbLoadBalancer.ErrorPicker;
+import io.grpc.grpclb.GrpclbLoadBalancer.RoundRobinPicker;
 import io.grpc.inprocess.InProcessChannelBuilder;
 import io.grpc.inprocess.InProcessServerBuilder;
 import io.grpc.internal.SerializingExecutor;
@@ -105,9 +105,9 @@
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-/** Unit tests for {@link GrpclbLoadBalancer2}. */
+/** Unit tests for {@link GrpclbLoadBalancer}. */
 @RunWith(JUnit4.class)
-public class GrpclbLoadBalancer2Test {
+public class GrpclbLoadBalancerTest {
   private static final Attributes.Key<String> RESOLUTION_ATTR =
       Attributes.Key.of("resolution-attr");
   private static final String SERVICE_AUTHORITY = "api.google.com";
@@ -159,14 +159,14 @@
       new SerializingExecutor(MoreExecutors.directExecutor());
   private final Metadata headers = new Metadata();
   @Mock
-  private LoadBalancer2.Factory pickFirstBalancerFactory;
+  private LoadBalancer.Factory pickFirstBalancerFactory;
   @Mock
-  private LoadBalancer2 pickFirstBalancer;
+  private LoadBalancer pickFirstBalancer;
   @Mock
-  private LoadBalancer2.Factory roundRobinBalancerFactory;
+  private LoadBalancer.Factory roundRobinBalancerFactory;
   @Mock
-  private LoadBalancer2 roundRobinBalancer;
-  private GrpclbLoadBalancer2 balancer;
+  private LoadBalancer roundRobinBalancer;
+  private GrpclbLoadBalancer balancer;
 
   @SuppressWarnings("unchecked")
   @Before
@@ -240,7 +240,7 @@
         }
       }).when(helper).runSerialized(any(Runnable.class));
     when(helper.getAuthority()).thenReturn(SERVICE_AUTHORITY);
-    balancer = new GrpclbLoadBalancer2(helper, pickFirstBalancerFactory, roundRobinBalancerFactory);
+    balancer = new GrpclbLoadBalancer(helper, pickFirstBalancerFactory, roundRobinBalancerFactory);
   }
 
   @After
@@ -290,7 +290,7 @@
   @Test
   public void bufferPicker() {
     assertEquals(PickResult.withNoResult(),
-        GrpclbLoadBalancer2.BUFFER_PICKER.pickSubchannel(Attributes.EMPTY, headers));
+        GrpclbLoadBalancer.BUFFER_PICKER.pickSubchannel(Attributes.EMPTY, headers));
   }
 
   @Test
@@ -553,11 +553,11 @@
     assertEquals(new EquivalentAddressGroup(backends1.get(1)), subchannel2.getAddresses());
 
     // Before any subchannel is READY, a buffer picker will be provided
-    inOrder.verify(helper).updatePicker(same(GrpclbLoadBalancer2.BUFFER_PICKER));
+    inOrder.verify(helper).updatePicker(same(GrpclbLoadBalancer.BUFFER_PICKER));
 
     deliverSubchannelState(subchannel1, ConnectivityStateInfo.forNonError(CONNECTING));
     deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(CONNECTING));
-    inOrder.verify(helper, times(2)).updatePicker(same(GrpclbLoadBalancer2.BUFFER_PICKER));
+    inOrder.verify(helper, times(2)).updatePicker(same(GrpclbLoadBalancer.BUFFER_PICKER));
 
     // Let subchannels be connected
     deliverSubchannelState(subchannel2, ConnectivityStateInfo.forNonError(READY));
@@ -724,7 +724,7 @@
         eq(new EquivalentAddressGroup(backends.get(0))), any(Attributes.class));
     inOrder.verify(helper).createSubchannel(
         eq(new EquivalentAddressGroup(backends.get(1))), any(Attributes.class));
-    inOrder.verify(helper).updatePicker(same(GrpclbLoadBalancer2.BUFFER_PICKER));
+    inOrder.verify(helper).updatePicker(same(GrpclbLoadBalancer.BUFFER_PICKER));
     inOrder.verifyNoMoreInteractions();
   }
 
@@ -806,7 +806,7 @@
       Subchannel subchannel = subchannels[i];
       if (subchannel == null) {
         assertSame("list[" + i + "] should be drop",
-            GrpclbLoadBalancer2.THROTTLED_RESULT, picker.list.get(i));
+            GrpclbLoadBalancer.THROTTLED_RESULT, picker.list.get(i));
       } else {
         assertEquals("list[" + i + "] should be Subchannel",
             subchannel, picker.list.get(i).getSubchannel());