blob: 38099f31fead7bf325e7d4822446a51bba147040 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tradefed.service;
import com.android.tradefed.invoker.logger.InvocationMetricLogger;
import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey;
import com.android.tradefed.invoker.tracing.CloseableTraceScope;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.StreamUtil;
import com.proto.tradefed.feature.ErrorInfo;
import com.proto.tradefed.feature.FeatureRequest;
import com.proto.tradefed.feature.FeatureResponse;
import com.proto.tradefed.feature.TradefedInformationGrpc;
import com.proto.tradefed.feature.TradefedInformationGrpc.TradefedInformationBlockingStub;
import java.util.Map;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;
/** A grpc client to request feature execution from the server. */
public class TradefedFeatureClient implements AutoCloseable {
private static final int MAX_MESSAGE_SIZE_BYTES = 33554432; // 32 MB
private TradefedInformationBlockingStub mBlockingStub;
private ManagedChannel mChannel;
public TradefedFeatureClient() {
mChannel =
ManagedChannelBuilder.forAddress("localhost", TradefedFeatureServer.getPort())
.usePlaintext()
.maxInboundMessageSize(MAX_MESSAGE_SIZE_BYTES)
.build();
mBlockingStub = TradefedInformationGrpc.newBlockingStub(mChannel);
}
/**
* Request a feature to the main server to execute and return the response.
*
* @param featureName The name of the feature to trigger.
* @param args The args to invoke the feature.
* @return A {@link FeatureResponse}.
*/
public FeatureResponse triggerFeature(String featureName, Map<String, String> args) {
return triggerFeature(
featureName, System.getenv(TradefedFeatureServer.SERVER_REFERENCE), args);
}
/**
* Request a feature to the main server to execute and return the response.
*
* @param featureName The name of the feature to trigger.
* @param args The args to invoke the feature.
* @return A {@link FeatureResponse}.
*/
private FeatureResponse triggerFeature(
String featureName, String invocationReference, Map<String, String> args) {
if (mChannel == null) {
throw new IllegalStateException(
"Tradefed feature channel is null due to being uninitialized or closed.");
}
FeatureResponse response;
try (CloseableTraceScope ignore =
new CloseableTraceScope("triggerFeature:" + featureName)) {
CLog.d("invoking feature '%s'", featureName);
FeatureRequest.Builder request =
FeatureRequest.newBuilder().setName(featureName).putAllArgs(args);
if (invocationReference != null) {
request.setReferenceId(invocationReference);
} else if (InvocationMetricLogger.getInvocationMetrics().containsKey(InvocationMetricKey.SERVER_REFERENCE.toString())) {
CLog.d("Using reference id from metrics.");
request.setReferenceId(InvocationMetricLogger.getInvocationMetrics().get(InvocationMetricKey.SERVER_REFERENCE.toString()));
} else {
CLog.w("Reference id is null.");
}
CLog.d("%s", request);
response = mBlockingStub.triggerFeature(request.build());
} catch (StatusRuntimeException e) {
response =
FeatureResponse.newBuilder()
.setErrorInfo(
ErrorInfo.newBuilder()
.setErrorTrace(StreamUtil.getStackTrace(e))
.build())
.build();
}
String message = String.format("Feature name: %s. response: %s", featureName, response);
if (response.hasErrorInfo()) {
StringBuilder callsite = new StringBuilder();
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
callsite.append(e.toString());
}
message += String.format(". Callsite: %s", callsite);
CLog.w(message);
} else {
CLog.d(message);
}
return response;
}
@Override
public void close() {
if (mChannel != null) {
mChannel.shutdown();
}
}
}