core: re-organize RealChannel with updateConfigSelector()

As mentioned in https://github.com/grpc/grpc-java/pull/7413#issuecomment-690756200 `RealChannel` did not manage `configSelector`, and therefore `configSelector.get()`, `configSelector.set()` and `drainPendingCalls()` were scattered everywhere in `ManagedChannelImpl`. This PR re-organizes `RealChannel` to manage `configSelector`.
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
index 10aa197..494899b 100644
--- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -263,10 +263,6 @@
   // Must be mutated and read from constructor or syncContext
   // used for channel tracing when value changed
   private ManagedChannelServiceConfig lastServiceConfig = EMPTY_SERVICE_CONFIG;
-  // Reference to null if no config selector is available from resolution result
-  // Reference must be set() from syncContext
-  private final AtomicReference<InternalConfigSelector> configSelector =
-      new AtomicReference<>(INITIAL_PENDING_SELECTOR);
 
   @Nullable
   private final ManagedChannelServiceConfig defaultServiceConfig;
@@ -750,7 +746,7 @@
 
   @VisibleForTesting
   InternalConfigSelector getConfigSelector() {
-    return configSelector.get();
+    return realChannel.configSelector.get();
   }
 
   /**
@@ -891,6 +887,10 @@
   }
 
   private class RealChannel extends Channel {
+    // Reference to null if no config selector is available from resolution result
+    // Reference must be set() from syncContext
+    private final AtomicReference<InternalConfigSelector> configSelector =
+        new AtomicReference<>(INITIAL_PENDING_SELECTOR);
     // Set when the NameResolver is initially created. When we create a new NameResolver for the
     // same target, the new instance must have the same value.
     private final String authority;
@@ -954,12 +954,20 @@
     }
 
     // Must run in SynchronizationContext.
-    private void drainPendingCalls() {
-      if (pendingCalls == null) {
-        return;
+    void updateConfigSelector(@Nullable InternalConfigSelector config) {
+      InternalConfigSelector prevConfig = configSelector.get();
+      configSelector.set(config);
+      if (prevConfig == INITIAL_PENDING_SELECTOR && pendingCalls != null) {
+        for (RealChannel.PendingCall<?, ?> pendingCall : pendingCalls) {
+          pendingCall.reprocess();
+        }
       }
-      for (RealChannel.PendingCall<?, ?> pendingCall : pendingCalls) {
-        pendingCall.reprocess();
+    }
+
+    // Must run in SynchronizationContext.
+    void onConfigError() {
+      if (configSelector.get() == INITIAL_PENDING_SELECTOR) {
+        updateConfigSelector(null);
       }
     }
 
@@ -1568,7 +1576,6 @@
           Status serviceConfigError = configOrError != null ? configOrError.getError() : null;
 
           ManagedChannelServiceConfig effectiveServiceConfig;
-          InternalConfigSelector prevConfigSelector = configSelector.get();
           if (!lookUpServiceConfig) {
             if (validServiceConfig != null) {
               channelLogger.log(
@@ -1582,14 +1589,14 @@
                   ChannelLogLevel.INFO,
                   "Config selector from name resolver discarded by channel settings");
             }
-            configSelector.set(effectiveServiceConfig.getDefaultConfigSelector());
+            realChannel.updateConfigSelector(effectiveServiceConfig.getDefaultConfigSelector());
           } else {
             // Try to use config if returned from name resolver
             // Otherwise, try to use the default config if available
             if (validServiceConfig != null) {
               effectiveServiceConfig = validServiceConfig;
               if (resolvedConfigSelector != null) {
-                configSelector.set(resolvedConfigSelector);
+                realChannel.updateConfigSelector(resolvedConfigSelector);
                 if (effectiveServiceConfig.getDefaultConfigSelector() != null) {
                   channelLogger.log(
                       ChannelLogLevel.DEBUG,
@@ -1597,11 +1604,11 @@
                           + "config-selector");
                 }
               } else {
-                configSelector.set(effectiveServiceConfig.getDefaultConfigSelector());
+                realChannel.updateConfigSelector(effectiveServiceConfig.getDefaultConfigSelector());
               }
             } else if (defaultServiceConfig != null) {
               effectiveServiceConfig = defaultServiceConfig;
-              configSelector.set(effectiveServiceConfig.getDefaultConfigSelector());
+              realChannel.updateConfigSelector(effectiveServiceConfig.getDefaultConfigSelector());
               channelLogger.log(
                   ChannelLogLevel.INFO,
                   "Received no service config, using default service config");
@@ -1618,7 +1625,7 @@
               }
             } else {
               effectiveServiceConfig = EMPTY_SERVICE_CONFIG;
-              configSelector.set(null);
+              realChannel.updateConfigSelector(null);
             }
             if (!effectiveServiceConfig.equals(lastServiceConfig)) {
               channelLogger.log(
@@ -1640,9 +1647,6 @@
                   re);
             }
           }
-          if (prevConfigSelector == INITIAL_PENDING_SELECTOR) {
-            realChannel.drainPendingCalls();
-          }
 
           Attributes effectiveAttrs = resolutionResult.getAttributes();
           // Call LB only if it's not shutdown.  If LB is shutdown, lbHelper won't match.
@@ -1690,10 +1694,7 @@
     private void handleErrorInSyncContext(Status error) {
       logger.log(Level.WARNING, "[{0}] Failed to resolve name. status={1}",
           new Object[] {getLogId(), error});
-      if (configSelector.get() == INITIAL_PENDING_SELECTOR) {
-        configSelector.set(null);
-        realChannel.drainPendingCalls();
-      }
+      realChannel.onConfigError();
       if (lastResolutionState != ResolutionState.ERROR) {
         channelLogger.log(ChannelLogLevel.WARNING, "Failed to resolve name: {0}", error);
         lastResolutionState = ResolutionState.ERROR;