@Override
    public <I, O> ClientCall<I, O> newCall(MethodDescriptor<I, O> method, CallOptions callOptions) {
        final RequestHeadersBuilder headersBuilder =
                RequestHeaders.builder(HttpMethod.POST, uri().getPath() + method.getFullMethodName())
                              .contentType(serializationFormat.mediaType())
                              .set(HttpHeaderNames.TE, HttpHeaderValues.TRAILERS.toString());
        final String callAuthority = callOptions.getAuthority();
        if (!Strings.isNullOrEmpty(callAuthority)) {
            headersBuilder.authority(callAuthority);
        }

        final HttpRequestWriter req = HttpRequest.streaming(headersBuilder.build());
        final DefaultClientRequestContext ctx = newContext(HttpMethod.POST, req, method);

        GrpcCallOptions.set(ctx, callOptions);

        ctx.logBuilder().serializationFormat(serializationFormat);
        ctx.logBuilder().defer(RequestLogProperty.REQUEST_CONTENT,
                               RequestLogProperty.RESPONSE_CONTENT);

        final HttpClient client;

        CallCredentials credentials = callOptions.getCredentials();
        if (credentials == NullCallCredentials.INSTANCE) {
            credentials = null;
        }
        if (credentials == null) {
            if (credentials0 != NullCallCredentials.INSTANCE) {
                credentials = credentials0;
            }
        }
        if (credentials != null) {
            client = new CallCredentialsDecoratingClient(
                    httpClient, credentials, method,
                    !Strings.isNullOrEmpty(callAuthority) ? callAuthority : authority());
        } else {
            client = httpClient;
        }

        final BiFunction<ClientRequestContext, Throwable, HttpResponse> errorResponseFactory =
                (unused, cause) -> {
                    final StatusAndMetadata statusAndMetadata = exceptionHandler.handle(ctx, cause);
                    Status status = statusAndMetadata.status();
                    if (status.getDescription() == null) {
                        status = status.withDescription(cause.getMessage());
                    }
                    return HttpResponse.ofFailure(status.asRuntimeException());
                };
        final HttpPreClient preClient =
                options().clientPreprocessors()
                         .decorate(TailPreClient.of(client, HttpResponse::of, errorResponseFactory));

        return new ArmeriaClientCall<>(
                ctx,
                req,
                method,
                simpleMethodNames,
                maxOutboundMessageSizeBytes,
                maxInboundMessageSizeBytes,
                callOptions,
                compressor,
                CompressorRegistry.getDefaultInstance(),
                decompressorRegistry,
                serializationFormat,
                jsonMarshaller,
                unsafeWrapResponseBuffers,
                exceptionHandler,
                useMethodMarshaller,
                preClient,
                errorResponseFactory);
    }
A {@link Channel} backed by an armeria {@link HttpClient}. Stores the {@link ClientBuilderParams} and other
{@link HttpClient} params for the associated gRPC stub.
grpc/src/main/java/com/linecorp/armeria/internal/client/grpc/ArmeriaChannel.java