Reduce number of codegen'd classes needed for Services

This reduces the number of classes defined, which reduces memory usage.
It also reduces the number of methods defined, which is important
because of the dex limit.

This should have virtually zero performance degradation because the
contiguous switch uses tableswitch bytecode.
diff --git a/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp
index f27463d..49a1f54 100644
--- a/compiler/src/java_plugin/cpp/java_generator.cpp
+++ b/compiler/src/java_plugin/cpp/java_generator.cpp
@@ -1,7 +1,9 @@
 #include "java_generator.h"
 
+#include <algorithm>
 #include <iostream>
 #include <map>
+#include <vector>
 #include <google/protobuf/compiler/java/java_names.h>
 #include <google/protobuf/descriptor.pb.h>
 #include <google/protobuf/io/printer.h>
@@ -57,6 +59,10 @@
   return "METHOD_" + ToAllUpperCase(method->name());
 }
 
+static inline string MethodIdFieldName(const MethodDescriptor* method) {
+  return "METHODID_" + ToAllUpperCase(method->name());
+}
+
 static inline string MessageFullJavaName(bool nano, const Descriptor* desc) {
   string name = google::protobuf::compiler::java::ClassName(desc);
   if (nano && !desc->file()->options().javanano_use_deprecated_package()) {
@@ -449,6 +455,123 @@
   p->Print("}\n\n");
 }
 
+static bool CompareMethodClientStreaming(const MethodDescriptor* method1,
+                                         const MethodDescriptor* method2)
+{
+  return method1->client_streaming() < method2->client_streaming();
+}
+
+// Place all method invocations into a single class to reduce memory footprint
+// on Android.
+static void PrintMethodHandlerClass(const ServiceDescriptor* service,
+                                   map<string, string>* vars,
+                                   Printer* p,
+                                   bool generate_nano) {
+  // Sort method ids based on client_streaming() so switch tables are compact.
+  vector<const MethodDescriptor*> sorted_methods(service->method_count());
+  for (int i = 0; i < service->method_count(); ++i) {
+    sorted_methods[i] = service->method(i);
+  }
+  stable_sort(sorted_methods.begin(), sorted_methods.end(),
+              CompareMethodClientStreaming);
+  for (int i = 0; i < sorted_methods.size(); i++) {
+    const MethodDescriptor* method = sorted_methods[i];
+    (*vars)["method_id"] = to_string(i);
+    (*vars)["method_id_name"] = MethodIdFieldName(method);
+    p->Print(
+        *vars,
+        "private static final int $method_id_name$ = $method_id$;\n");
+  }
+  p->Print("\n");
+  (*vars)["service_name"] = service->name();
+  p->Print(
+      *vars,
+      "private static class MethodHandlers<Req, Resp> implements\n"
+      "    io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,\n"
+      "    io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,\n"
+      "    io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,\n"
+      "    io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {\n"
+      "  private final $service_name$ serviceImpl;\n"
+      "  private final int methodId;\n"
+      "\n"
+      "  public MethodHandlers($service_name$ serviceImpl, int methodId) {\n"
+      "    this.serviceImpl = serviceImpl;\n"
+      "    this.methodId = methodId;\n"
+      "  }\n\n");
+  p->Indent();
+  p->Print(
+      *vars,
+      "@java.lang.SuppressWarnings(\"unchecked\")\n"
+      "public void invoke(Req request, $StreamObserver$<Resp> responseObserver) {\n"
+      "  switch (methodId) {\n");
+  p->Indent();
+  p->Indent();
+
+  for (int i = 0; i < service->method_count(); ++i) {
+    const MethodDescriptor* method = service->method(i);
+    if (method->client_streaming()) {
+      continue;
+    }
+    (*vars)["method_id_name"] = MethodIdFieldName(method);
+    (*vars)["lower_method_name"] = LowerMethodName(method);
+    (*vars)["input_type"] = MessageFullJavaName(generate_nano,
+                                                method->input_type());
+    (*vars)["output_type"] = MessageFullJavaName(generate_nano,
+                                                 method->output_type());
+    p->Print(
+        *vars,
+        "case $method_id_name$:\n"
+        "  serviceImpl.$lower_method_name$(($input_type$) request,\n"
+        "      ($StreamObserver$<$output_type$>) responseObserver);\n"
+        "  break;\n");
+  }
+  p->Print("default:\n"
+           "  throw new AssertionError();\n");
+
+  p->Outdent();
+  p->Outdent();
+  p->Print("  }\n"
+           "}\n\n");
+
+  p->Print(
+      *vars,
+      "@java.lang.SuppressWarnings(\"unchecked\")\n"
+      "public $StreamObserver$<Req> invoke(\n"
+      "    $StreamObserver$<Resp> responseObserver) {\n"
+      "  switch (methodId) {\n");
+  p->Indent();
+  p->Indent();
+
+  for (int i = 0; i < service->method_count(); ++i) {
+    const MethodDescriptor* method = service->method(i);
+    if (!method->client_streaming()) {
+      continue;
+    }
+    (*vars)["method_id_name"] = MethodIdFieldName(method);
+    (*vars)["lower_method_name"] = LowerMethodName(method);
+    (*vars)["input_type"] = MessageFullJavaName(generate_nano,
+                                                method->input_type());
+    (*vars)["output_type"] = MessageFullJavaName(generate_nano,
+                                                 method->output_type());
+    p->Print(
+        *vars,
+        "case $method_id_name$:\n"
+        "  return ($StreamObserver$<Req>) serviceImpl.$lower_method_name$(\n"
+        "      ($StreamObserver$<$output_type$>) responseObserver);\n");
+  }
+  p->Print("default:\n"
+           "  throw new AssertionError();\n");
+
+  p->Outdent();
+  p->Outdent();
+  p->Print("  }\n"
+           "}\n");
+
+
+  p->Outdent();
+  p->Print("}\n\n");
+}
+
 static void PrintBindServiceMethod(const ServiceDescriptor* service,
                                    map<string, string>* vars,
                                    Printer* p,
@@ -463,6 +586,7 @@
            "return "
            "$ServerServiceDefinition$.builder(SERVICE_NAME)\n");
   p->Indent();
+  p->Indent();
   for (int i = 0; i < service->method_count(); ++i) {
     const MethodDescriptor* method = service->method(i);
     (*vars)["lower_method_name"] = LowerMethodName(method);
@@ -471,27 +595,20 @@
                                                 method->input_type());
     (*vars)["output_type"] = MessageFullJavaName(generate_nano,
                                                  method->output_type());
+    (*vars)["method_id_name"] = MethodIdFieldName(method);
     bool client_streaming = method->client_streaming();
     bool server_streaming = method->server_streaming();
     if (client_streaming) {
       if (server_streaming) {
         (*vars)["calls_method"] = "asyncBidiStreamingCall";
-        (*vars)["invocation_class"] =
-            "io.grpc.stub.ServerCalls.BidiStreamingMethod";
       } else {
         (*vars)["calls_method"] = "asyncClientStreamingCall";
-        (*vars)["invocation_class"] =
-            "io.grpc.stub.ServerCalls.ClientStreamingMethod";
       }
     } else {
       if (server_streaming) {
         (*vars)["calls_method"] = "asyncServerStreamingCall";
-        (*vars)["invocation_class"] =
-            "io.grpc.stub.ServerCalls.ServerStreamingMethod";
       } else {
         (*vars)["calls_method"] = "asyncUnaryCall";
-        (*vars)["invocation_class"] =
-            "io.grpc.stub.ServerCalls.UnaryMethod";
       }
     }
     p->Print(*vars, ".addMethod(\n");
@@ -503,38 +620,15 @@
     p->Indent();
     p->Print(
         *vars,
-        "new $invocation_class$<\n"
-        "    $input_type$,\n"
-        "    $output_type$>() {\n");
-    p->Indent();
-    p->Print(
-        *vars,
-        "@$Override$\n");
-    if (client_streaming) {
-      p->Print(
-          *vars,
-          "public $StreamObserver$<$input_type$> invoke(\n"
-          "    $StreamObserver$<$output_type$> responseObserver) {\n"
-          "  return serviceImpl.$lower_method_name$(responseObserver);\n"
-          "}\n");
-    } else {
-      p->Print(
-          *vars,
-          "public void invoke(\n"
-          "    $input_type$ request,\n"
-          "    $StreamObserver$<$output_type$> responseObserver) {\n"
-          "  serviceImpl.$lower_method_name$(request, responseObserver);\n"
-          "}\n");
-    }
-    p->Outdent();
-    p->Print("}))");
-    if (i == service->method_count() - 1) {
-      p->Print(".build();");
-    }
-    p->Print("\n");
+        "new MethodHandlers<\n"
+        "  $input_type$,\n"
+        "  $output_type$>(\n"
+        "    serviceImpl, $method_id_name$)))\n");
     p->Outdent();
     p->Outdent();
   }
+  p->Print(".build();\n");
+  p->Outdent();
   p->Outdent();
   p->Outdent();
   p->Print("}\n");
@@ -598,6 +692,7 @@
   PrintStub(service, vars, p, ASYNC_CLIENT_IMPL, generate_nano);
   PrintStub(service, vars, p, BLOCKING_CLIENT_IMPL, generate_nano);
   PrintStub(service, vars, p, FUTURE_CLIENT_IMPL, generate_nano);
+  PrintMethodHandlerClass(service, vars, p, generate_nano);
   PrintBindServiceMethod(service, vars, p, generate_nano);
   p->Outdent();
   p->Print("}\n");
diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt
index e263f67..77d5bb2 100644
--- a/compiler/src/test/golden/TestService.java.txt
+++ b/compiler/src/test/golden/TestService.java.txt
@@ -222,70 +222,98 @@
     }
   }
 
+  private static final int METHODID_UNARY_CALL = 0;
+  private static final int METHODID_STREAMING_OUTPUT_CALL = 1;
+  private static final int METHODID_STREAMING_INPUT_CALL = 2;
+  private static final int METHODID_FULL_BIDI_CALL = 3;
+  private static final int METHODID_HALF_BIDI_CALL = 4;
+
+  private static class MethodHandlers<Req, Resp> implements
+      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
+    private final TestService serviceImpl;
+    private final int methodId;
+
+    public MethodHandlers(TestService serviceImpl, int methodId) {
+      this.serviceImpl = serviceImpl;
+      this.methodId = methodId;
+    }
+
+    @java.lang.SuppressWarnings("unchecked")
+    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_UNARY_CALL:
+          serviceImpl.unaryCall((io.grpc.testing.integration.Test.SimpleRequest) request,
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse>) responseObserver);
+          break;
+        case METHODID_STREAMING_OUTPUT_CALL:
+          serviceImpl.streamingOutputCall((io.grpc.testing.integration.Test.StreamingOutputCallRequest) request,
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse>) responseObserver);
+          break;
+        default:
+          throw new AssertionError();
+      }
+    }
+
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver<Req> invoke(
+        io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_STREAMING_INPUT_CALL:
+          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.streamingInputCall(
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse>) responseObserver);
+        case METHODID_FULL_BIDI_CALL:
+          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.fullBidiCall(
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse>) responseObserver);
+        case METHODID_HALF_BIDI_CALL:
+          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.halfBidiCall(
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse>) responseObserver);
+        default:
+          throw new AssertionError();
+      }
+    }
+  }
+
   public static io.grpc.ServerServiceDefinition bindService(
       final TestService serviceImpl) {
     return io.grpc.ServerServiceDefinition.builder(SERVICE_NAME)
-      .addMethod(
-        METHOD_UNARY_CALL,
-        asyncUnaryCall(
-          new io.grpc.stub.ServerCalls.UnaryMethod<
+        .addMethod(
+          METHOD_UNARY_CALL,
+          asyncUnaryCall(
+            new MethodHandlers<
               io.grpc.testing.integration.Test.SimpleRequest,
-              io.grpc.testing.integration.Test.SimpleResponse>() {
-            @java.lang.Override
-            public void invoke(
-                io.grpc.testing.integration.Test.SimpleRequest request,
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.SimpleResponse> responseObserver) {
-              serviceImpl.unaryCall(request, responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_STREAMING_OUTPUT_CALL,
-        asyncServerStreamingCall(
-          new io.grpc.stub.ServerCalls.ServerStreamingMethod<
+              io.grpc.testing.integration.Test.SimpleResponse>(
+                serviceImpl, METHODID_UNARY_CALL)))
+        .addMethod(
+          METHOD_STREAMING_OUTPUT_CALL,
+          asyncServerStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.Test.StreamingOutputCallRequest,
-              io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
-            @java.lang.Override
-            public void invoke(
-                io.grpc.testing.integration.Test.StreamingOutputCallRequest request,
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
-              serviceImpl.streamingOutputCall(request, responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_STREAMING_INPUT_CALL,
-        asyncClientStreamingCall(
-          new io.grpc.stub.ServerCalls.ClientStreamingMethod<
+              io.grpc.testing.integration.Test.StreamingOutputCallResponse>(
+                serviceImpl, METHODID_STREAMING_OUTPUT_CALL)))
+        .addMethod(
+          METHOD_STREAMING_INPUT_CALL,
+          asyncClientStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.Test.StreamingInputCallRequest,
-              io.grpc.testing.integration.Test.StreamingInputCallResponse>() {
-            @java.lang.Override
-            public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallRequest> invoke(
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingInputCallResponse> responseObserver) {
-              return serviceImpl.streamingInputCall(responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_FULL_BIDI_CALL,
-        asyncBidiStreamingCall(
-          new io.grpc.stub.ServerCalls.BidiStreamingMethod<
+              io.grpc.testing.integration.Test.StreamingInputCallResponse>(
+                serviceImpl, METHODID_STREAMING_INPUT_CALL)))
+        .addMethod(
+          METHOD_FULL_BIDI_CALL,
+          asyncBidiStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.Test.StreamingOutputCallRequest,
-              io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
-            @java.lang.Override
-            public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> invoke(
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
-              return serviceImpl.fullBidiCall(responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_HALF_BIDI_CALL,
-        asyncBidiStreamingCall(
-          new io.grpc.stub.ServerCalls.BidiStreamingMethod<
+              io.grpc.testing.integration.Test.StreamingOutputCallResponse>(
+                serviceImpl, METHODID_FULL_BIDI_CALL)))
+        .addMethod(
+          METHOD_HALF_BIDI_CALL,
+          asyncBidiStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.Test.StreamingOutputCallRequest,
-              io.grpc.testing.integration.Test.StreamingOutputCallResponse>() {
-            @java.lang.Override
-            public io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallRequest> invoke(
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.Test.StreamingOutputCallResponse> responseObserver) {
-              return serviceImpl.halfBidiCall(responseObserver);
-            }
-          })).build();
+              io.grpc.testing.integration.Test.StreamingOutputCallResponse>(
+                serviceImpl, METHODID_HALF_BIDI_CALL)))
+        .build();
   }
 }
diff --git a/compiler/src/test/golden/TestServiceNano.java.txt b/compiler/src/test/golden/TestServiceNano.java.txt
index 7fd611f..f8c1ff3 100644
--- a/compiler/src/test/golden/TestServiceNano.java.txt
+++ b/compiler/src/test/golden/TestServiceNano.java.txt
@@ -300,70 +300,98 @@
     }
   }
 
+  private static final int METHODID_UNARY_CALL = 0;
+  private static final int METHODID_STREAMING_OUTPUT_CALL = 1;
+  private static final int METHODID_STREAMING_INPUT_CALL = 2;
+  private static final int METHODID_FULL_BIDI_CALL = 3;
+  private static final int METHODID_HALF_BIDI_CALL = 4;
+
+  private static class MethodHandlers<Req, Resp> implements
+      io.grpc.stub.ServerCalls.UnaryMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ServerStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.ClientStreamingMethod<Req, Resp>,
+      io.grpc.stub.ServerCalls.BidiStreamingMethod<Req, Resp> {
+    private final TestService serviceImpl;
+    private final int methodId;
+
+    public MethodHandlers(TestService serviceImpl, int methodId) {
+      this.serviceImpl = serviceImpl;
+      this.methodId = methodId;
+    }
+
+    @java.lang.SuppressWarnings("unchecked")
+    public void invoke(Req request, io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_UNARY_CALL:
+          serviceImpl.unaryCall((io.grpc.testing.integration.nano.Test.SimpleRequest) request,
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.SimpleResponse>) responseObserver);
+          break;
+        case METHODID_STREAMING_OUTPUT_CALL:
+          serviceImpl.streamingOutputCall((io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest) request,
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>) responseObserver);
+          break;
+        default:
+          throw new AssertionError();
+      }
+    }
+
+    @java.lang.SuppressWarnings("unchecked")
+    public io.grpc.stub.StreamObserver<Req> invoke(
+        io.grpc.stub.StreamObserver<Resp> responseObserver) {
+      switch (methodId) {
+        case METHODID_STREAMING_INPUT_CALL:
+          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.streamingInputCall(
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingInputCallResponse>) responseObserver);
+        case METHODID_FULL_BIDI_CALL:
+          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.fullBidiCall(
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>) responseObserver);
+        case METHODID_HALF_BIDI_CALL:
+          return (io.grpc.stub.StreamObserver<Req>) serviceImpl.halfBidiCall(
+              (io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>) responseObserver);
+        default:
+          throw new AssertionError();
+      }
+    }
+  }
+
   public static io.grpc.ServerServiceDefinition bindService(
       final TestService serviceImpl) {
     return io.grpc.ServerServiceDefinition.builder(SERVICE_NAME)
-      .addMethod(
-        METHOD_UNARY_CALL,
-        asyncUnaryCall(
-          new io.grpc.stub.ServerCalls.UnaryMethod<
+        .addMethod(
+          METHOD_UNARY_CALL,
+          asyncUnaryCall(
+            new MethodHandlers<
               io.grpc.testing.integration.nano.Test.SimpleRequest,
-              io.grpc.testing.integration.nano.Test.SimpleResponse>() {
-            @java.lang.Override
-            public void invoke(
-                io.grpc.testing.integration.nano.Test.SimpleRequest request,
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.SimpleResponse> responseObserver) {
-              serviceImpl.unaryCall(request, responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_STREAMING_OUTPUT_CALL,
-        asyncServerStreamingCall(
-          new io.grpc.stub.ServerCalls.ServerStreamingMethod<
+              io.grpc.testing.integration.nano.Test.SimpleResponse>(
+                serviceImpl, METHODID_UNARY_CALL)))
+        .addMethod(
+          METHOD_STREAMING_OUTPUT_CALL,
+          asyncServerStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest,
-              io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>() {
-            @java.lang.Override
-            public void invoke(
-                io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest request,
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver) {
-              serviceImpl.streamingOutputCall(request, responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_STREAMING_INPUT_CALL,
-        asyncClientStreamingCall(
-          new io.grpc.stub.ServerCalls.ClientStreamingMethod<
+              io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>(
+                serviceImpl, METHODID_STREAMING_OUTPUT_CALL)))
+        .addMethod(
+          METHOD_STREAMING_INPUT_CALL,
+          asyncClientStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.nano.Test.StreamingInputCallRequest,
-              io.grpc.testing.integration.nano.Test.StreamingInputCallResponse>() {
-            @java.lang.Override
-            public io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingInputCallRequest> invoke(
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingInputCallResponse> responseObserver) {
-              return serviceImpl.streamingInputCall(responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_FULL_BIDI_CALL,
-        asyncBidiStreamingCall(
-          new io.grpc.stub.ServerCalls.BidiStreamingMethod<
+              io.grpc.testing.integration.nano.Test.StreamingInputCallResponse>(
+                serviceImpl, METHODID_STREAMING_INPUT_CALL)))
+        .addMethod(
+          METHOD_FULL_BIDI_CALL,
+          asyncBidiStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest,
-              io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>() {
-            @java.lang.Override
-            public io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest> invoke(
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver) {
-              return serviceImpl.fullBidiCall(responseObserver);
-            }
-          }))
-      .addMethod(
-        METHOD_HALF_BIDI_CALL,
-        asyncBidiStreamingCall(
-          new io.grpc.stub.ServerCalls.BidiStreamingMethod<
+              io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>(
+                serviceImpl, METHODID_FULL_BIDI_CALL)))
+        .addMethod(
+          METHOD_HALF_BIDI_CALL,
+          asyncBidiStreamingCall(
+            new MethodHandlers<
               io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest,
-              io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>() {
-            @java.lang.Override
-            public io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallRequest> invoke(
-                io.grpc.stub.StreamObserver<io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse> responseObserver) {
-              return serviceImpl.halfBidiCall(responseObserver);
-            }
-          })).build();
+              io.grpc.testing.integration.nano.Test.StreamingOutputCallResponse>(
+                serviceImpl, METHODID_HALF_BIDI_CALL)))
+        .build();
   }
 }