234 lines
8.9 KiB
C++
234 lines
8.9 KiB
C++
/*
|
|
* Copyright 2020 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.
|
|
*/
|
|
|
|
#ifndef CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_GRPCGRAPHSERVERIMPL_H_
|
|
#define CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_GRPCGRAPHSERVERIMPL_H_
|
|
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
#include <android-base/logging.h>
|
|
#include <grpc++/grpc++.h>
|
|
|
|
#include "GrpcPrebuiltGraphService.grpc.pb.h"
|
|
#include "GrpcPrebuiltGraphService.pb.h"
|
|
#include "Options.pb.h"
|
|
#include "PrebuiltEngineInterface.h"
|
|
#include "PrebuiltGraph.h"
|
|
#include "RunnerComponent.h"
|
|
#include "gmock/gmock-matchers.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
#include "types/Status.h"
|
|
|
|
namespace android {
|
|
namespace automotive {
|
|
namespace computepipe {
|
|
namespace graph {
|
|
|
|
constexpr char kGraphName[] = "Stub graph name";
|
|
constexpr char kSetGraphConfigMessage[] = "Stub set config message";
|
|
constexpr char kSetDebugOptionMessage[] = "Stub set debug option message";
|
|
constexpr char kStartGraphMessage[] = "Stub start graph message";
|
|
constexpr char kStopGraphMessage[] = "Stub stop graph message";
|
|
constexpr char kOutputStreamPacket[] = "Stub output stream packet";
|
|
constexpr char kResetGraphMessage[] = "ResetGraphMessage";
|
|
|
|
// This is a barebones synchronous server implementation. A better implementation would be an
|
|
// asynchronous implementation and it is upto the graph provider to do that. This implementation
|
|
// is very specific to tests being conducted here.
|
|
class GrpcGraphServerImpl : public proto::GrpcGraphService::Service {
|
|
private:
|
|
std::string mServerAddress;
|
|
std::unique_ptr<::grpc::Server> mServer;
|
|
std::mutex mLock;
|
|
std::condition_variable mShutdownCv;
|
|
bool mShutdown = false;
|
|
|
|
public:
|
|
explicit GrpcGraphServerImpl(std::string address) : mServerAddress(address) {}
|
|
|
|
virtual ~GrpcGraphServerImpl() {
|
|
if (mServer) {
|
|
mServer->Shutdown();
|
|
std::unique_lock lock(mLock);
|
|
if (!mShutdown) {
|
|
mShutdownCv.wait_for(lock, std::chrono::seconds(10),
|
|
[this]() { return mShutdown; });
|
|
}
|
|
}
|
|
}
|
|
|
|
void startServer() {
|
|
if (mServer == nullptr) {
|
|
::grpc::ServerBuilder builder;
|
|
builder.RegisterService(this);
|
|
builder.AddListeningPort(mServerAddress, ::grpc::InsecureServerCredentials());
|
|
mServer = builder.BuildAndStart();
|
|
mServer->Wait();
|
|
std::lock_guard lock(mLock);
|
|
mShutdown = true;
|
|
mShutdownCv.notify_one();
|
|
}
|
|
}
|
|
|
|
::grpc::Status GetGraphOptions(::grpc::ServerContext* context,
|
|
const proto::GraphOptionsRequest* request,
|
|
proto::GraphOptionsResponse* response) override {
|
|
proto::Options options;
|
|
options.set_graph_name(kGraphName);
|
|
response->set_serialized_options(options.SerializeAsString());
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status SetGraphConfig(::grpc::ServerContext* context,
|
|
const proto::SetGraphConfigRequest* request,
|
|
proto::StatusResponse* response) override {
|
|
response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
|
|
response->set_message(kSetGraphConfigMessage);
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status SetDebugOption(::grpc::ServerContext* context,
|
|
const proto::SetDebugRequest* request,
|
|
proto::StatusResponse* response) override {
|
|
response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
|
|
response->set_message(kSetDebugOptionMessage);
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status StartGraphExecution(::grpc::ServerContext* context,
|
|
const proto::StartGraphExecutionRequest* request,
|
|
proto::StatusResponse* response) override {
|
|
response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
|
|
response->set_message(kStartGraphMessage);
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status ObserveOutputStream(
|
|
::grpc::ServerContext* context, const proto::ObserveOutputStreamRequest* request,
|
|
::grpc::ServerWriter<proto::OutputStreamResponse>* writer) override {
|
|
// Write as many output packets as stream id. This is just to test different number of
|
|
// packets received with each stream. Also write even numbered stream as a pixel packet
|
|
// and odd numbered stream as a data packet.
|
|
for (int i = 0; i < request->stream_id(); i++) {
|
|
proto::OutputStreamResponse response;
|
|
if (request->stream_id() % 2 == 0) {
|
|
response.mutable_pixel_data()->set_data(kOutputStreamPacket);
|
|
response.mutable_pixel_data()->set_height(1);
|
|
response.mutable_pixel_data()->set_width(sizeof(kOutputStreamPacket));
|
|
response.mutable_pixel_data()->set_step(sizeof(kOutputStreamPacket));
|
|
response.mutable_pixel_data()->set_format(proto::PixelFormat::GRAY);
|
|
EXPECT_TRUE(response.has_pixel_data());
|
|
} else {
|
|
response.set_semantic_data(kOutputStreamPacket);
|
|
EXPECT_TRUE(response.has_semantic_data());
|
|
}
|
|
if (!writer->Write(response)) {
|
|
return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost");
|
|
}
|
|
}
|
|
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status StopGraphExecution(::grpc::ServerContext* context,
|
|
const proto::StopGraphExecutionRequest* request,
|
|
proto::StatusResponse* response) override {
|
|
response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
|
|
response->set_message(kStopGraphMessage);
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status ResetGraph(::grpc::ServerContext* context,
|
|
const proto::ResetGraphRequest* request,
|
|
proto::StatusResponse* response) override {
|
|
response->set_code(proto::RemoteGraphStatusCode::SUCCESS);
|
|
response->set_message(kResetGraphMessage);
|
|
return ::grpc::Status::OK;
|
|
}
|
|
|
|
::grpc::Status GetProfilingData(::grpc::ServerContext* context,
|
|
const proto::ProfilingDataRequest* request,
|
|
proto::ProfilingDataResponse* response) {
|
|
response->set_data(kSetGraphConfigMessage);
|
|
return ::grpc::Status::OK;
|
|
}
|
|
};
|
|
|
|
class PrebuiltEngineInterfaceImpl : public PrebuiltEngineInterface {
|
|
private:
|
|
std::map<int, int> mNumPacketsPerStream;
|
|
std::mutex mLock;
|
|
std::condition_variable mCv;
|
|
bool mGraphTerminated = false;
|
|
|
|
public:
|
|
// Prebuilt to engine interface
|
|
void DispatchPixelData(int streamId, int64_t timestamp,
|
|
const runner::InputFrame& frame) override {
|
|
ASSERT_EQ(streamId % 2, 0);
|
|
std::lock_guard lock(mLock);
|
|
if (mNumPacketsPerStream.find(streamId) == mNumPacketsPerStream.end()) {
|
|
mNumPacketsPerStream[streamId] = 1;
|
|
} else {
|
|
mNumPacketsPerStream[streamId]++;
|
|
}
|
|
}
|
|
|
|
void DispatchSerializedData(int streamId, int64_t timestamp, std::string&& data) override {
|
|
ASSERT_EQ(streamId % 2, 1);
|
|
std::lock_guard lock(mLock);
|
|
if (mNumPacketsPerStream.find(streamId) == mNumPacketsPerStream.end()) {
|
|
mNumPacketsPerStream[streamId] = 1;
|
|
} else {
|
|
mNumPacketsPerStream[streamId]++;
|
|
}
|
|
}
|
|
|
|
void DispatchGraphTerminationMessage(Status status, std::string&& msg) override {
|
|
std::lock_guard lock(mLock);
|
|
mGraphTerminated = true;
|
|
mCv.notify_one();
|
|
}
|
|
|
|
bool waitForTermination() {
|
|
std::unique_lock lock(mLock);
|
|
if (!mGraphTerminated) {
|
|
mCv.wait_for(lock, std::chrono::seconds(10), [this] { return mGraphTerminated; });
|
|
}
|
|
return mGraphTerminated;
|
|
}
|
|
|
|
int numPacketsForStream(int streamId) {
|
|
std::lock_guard lock(mLock);
|
|
auto it = mNumPacketsPerStream.find(streamId);
|
|
if (it == mNumPacketsPerStream.end()) {
|
|
return 0;
|
|
}
|
|
return it->second;
|
|
}
|
|
};
|
|
|
|
} // namespace graph
|
|
} // namespace computepipe
|
|
} // namespace automotive
|
|
} // namespace android
|
|
|
|
#endif // CPP_COMPUTEPIPE_TESTS_RUNNER_GRAPH_INCLUDES_GRPCGRAPHSERVERIMPL_H_
|