AIDL VHAL GRPC Client
Bug: 266001013 Test: `atest GRPCVehicleHardwareUnitTest` Change-Id: I89b1c260aa2c34f353e88547a92718bb1cc37e5f
This commit is contained in:
parent
3af3d5bd13
commit
6cb8689d10
7 changed files with 609 additions and 0 deletions
102
automotive/vehicle/aidl/impl/grpc/Android.bp
Normal file
102
automotive/vehicle/aidl/impl/grpc/Android.bp
Normal file
|
@ -0,0 +1,102 @@
|
|||
// Copyright (C) 2023 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 {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "VehicleServerProtoStub_h@default-grpc",
|
||||
tools: [
|
||||
"aprotoc",
|
||||
"protoc-gen-grpc-cpp-plugin",
|
||||
],
|
||||
cmd: "$(location aprotoc) -I$$(dirname $(in)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
|
||||
srcs: [
|
||||
"proto/VehicleServer.proto",
|
||||
],
|
||||
out: [
|
||||
"VehicleServer.pb.h",
|
||||
"VehicleServer.grpc.pb.h",
|
||||
],
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "VehicleServerProtoStub_cc@default-grpc",
|
||||
tools: [
|
||||
"aprotoc",
|
||||
"protoc-gen-grpc-cpp-plugin",
|
||||
],
|
||||
cmd: "$(location aprotoc) -I$$(dirname $(in)) -Ihardware/interfaces/automotive/vehicle/aidl/impl/proto -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
|
||||
srcs: [
|
||||
"proto/VehicleServer.proto",
|
||||
],
|
||||
out: [
|
||||
"VehicleServer.pb.cc",
|
||||
"VehicleServer.grpc.pb.cc",
|
||||
],
|
||||
visibility: ["//visibility:private"],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "android.hardware.automotive.vehicle@default-grpc-libgrpc",
|
||||
vendor: true,
|
||||
host_supported: true,
|
||||
include_dirs: [
|
||||
"external/protobuf/src",
|
||||
],
|
||||
generated_headers: [
|
||||
"VehicleServerProtoStub_h@default-grpc",
|
||||
],
|
||||
export_generated_headers: [
|
||||
"VehicleServerProtoStub_h@default-grpc",
|
||||
],
|
||||
generated_sources: [
|
||||
"VehicleServerProtoStub_cc@default-grpc",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"VehicleHalProtos",
|
||||
],
|
||||
shared_libs: [
|
||||
"libgrpc++",
|
||||
],
|
||||
cflags: [
|
||||
"-Wno-unused-parameter",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "android.hardware.automotive.vehicle@default-grpc-hardware-lib",
|
||||
defaults: ["VehicleHalDefaults"],
|
||||
vendor: true,
|
||||
srcs: [
|
||||
"GRPCVehicleHardware.cpp",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.automotive.vehicle@default-grpc-libgrpc",
|
||||
"VehicleHalProtoMessageConverter",
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleHardware",
|
||||
],
|
||||
shared_libs: [
|
||||
"libgrpc++",
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
export_include_dirs: ["."],
|
||||
cflags: [
|
||||
"-Wno-unused-parameter",
|
||||
],
|
||||
}
|
221
automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
Normal file
221
automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.
|
||||
*/
|
||||
|
||||
#include <GRPCVehicleHardware.h>
|
||||
|
||||
#include "ProtoMessageConverter.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <grpc++/grpc++.h>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <utility>
|
||||
|
||||
namespace android::hardware::automotive::vehicle::virtualization {
|
||||
|
||||
static std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
|
||||
// TODO(chenhaosjtuacm): get secured credentials here
|
||||
return ::grpc::InsecureChannelCredentials();
|
||||
}
|
||||
|
||||
GRPCVehicleHardware::GRPCVehicleHardware(std::string service_addr)
|
||||
: mServiceAddr(std::move(service_addr)),
|
||||
mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())),
|
||||
mGrpcStub(proto::VehicleServer::NewStub(mGrpcChannel)),
|
||||
mValuePollingThread([this] { ValuePollingLoop(); }) {}
|
||||
|
||||
GRPCVehicleHardware::~GRPCVehicleHardware() {
|
||||
{
|
||||
std::lock_guard lck(mShutdownMutex);
|
||||
mShuttingDownFlag.store(true);
|
||||
}
|
||||
mShutdownCV.notify_all();
|
||||
mValuePollingThread.join();
|
||||
}
|
||||
|
||||
std::vector<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getAllPropertyConfigs() const {
|
||||
std::vector<aidlvhal::VehiclePropConfig> configs;
|
||||
::grpc::ClientContext context;
|
||||
auto config_stream = mGrpcStub->GetAllPropertyConfig(&context, ::google::protobuf::Empty());
|
||||
proto::VehiclePropConfig protoConfig;
|
||||
while (config_stream->Read(&protoConfig)) {
|
||||
aidlvhal::VehiclePropConfig config;
|
||||
proto_msg_converter::protoToAidl(protoConfig, &config);
|
||||
configs.push_back(std::move(config));
|
||||
}
|
||||
auto grpc_status = config_stream->Finish();
|
||||
if (!grpc_status.ok()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": GRPC GetAllPropertyConfig Failed: " << grpc_status.error_message();
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
aidlvhal::StatusCode GRPCVehicleHardware::setValues(
|
||||
std::shared_ptr<const SetValuesCallback> callback,
|
||||
const std::vector<aidlvhal::SetValueRequest>& requests) {
|
||||
::grpc::ClientContext context;
|
||||
proto::VehiclePropValueRequests protoRequests;
|
||||
proto::SetValueResults protoResults;
|
||||
for (const auto& request : requests) {
|
||||
auto& protoRequest = *protoRequests.add_requests();
|
||||
protoRequest.set_request_id(request.requestId);
|
||||
proto_msg_converter::aidlToProto(request.value, protoRequest.mutable_value());
|
||||
}
|
||||
// TODO(chenhaosjtuacm): Make it Async.
|
||||
auto grpc_status = mGrpcStub->SetValues(&context, protoRequests, &protoResults);
|
||||
if (!grpc_status.ok()) {
|
||||
LOG(ERROR) << __func__ << ": GRPC SetValues Failed: " << grpc_status.error_message();
|
||||
{
|
||||
std::shared_lock lck(mCallbackMutex);
|
||||
// TODO(chenhaosjtuacm): call on-set-error callback.
|
||||
}
|
||||
return aidlvhal::StatusCode::INTERNAL_ERROR;
|
||||
}
|
||||
std::vector<aidlvhal::SetValueResult> results;
|
||||
for (const auto& protoResult : protoResults.results()) {
|
||||
auto& result = results.emplace_back();
|
||||
result.requestId = protoResult.request_id();
|
||||
result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
|
||||
// TODO(chenhaosjtuacm): call on-set-error callback.
|
||||
}
|
||||
(*callback)(std::move(results));
|
||||
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
|
||||
aidlvhal::StatusCode GRPCVehicleHardware::getValues(
|
||||
std::shared_ptr<const GetValuesCallback> callback,
|
||||
const std::vector<aidlvhal::GetValueRequest>& requests) const {
|
||||
::grpc::ClientContext context;
|
||||
proto::VehiclePropValueRequests protoRequests;
|
||||
proto::GetValueResults protoResults;
|
||||
for (const auto& request : requests) {
|
||||
auto& protoRequest = *protoRequests.add_requests();
|
||||
protoRequest.set_request_id(request.requestId);
|
||||
proto_msg_converter::aidlToProto(request.prop, protoRequest.mutable_value());
|
||||
}
|
||||
// TODO(chenhaosjtuacm): Make it Async.
|
||||
auto grpc_status = mGrpcStub->GetValues(&context, protoRequests, &protoResults);
|
||||
if (!grpc_status.ok()) {
|
||||
LOG(ERROR) << __func__ << ": GRPC GetValues Failed: " << grpc_status.error_message();
|
||||
return aidlvhal::StatusCode::INTERNAL_ERROR;
|
||||
}
|
||||
std::vector<aidlvhal::GetValueResult> results;
|
||||
for (const auto& protoResult : protoResults.results()) {
|
||||
auto& result = results.emplace_back();
|
||||
result.requestId = protoResult.request_id();
|
||||
result.status = static_cast<aidlvhal::StatusCode>(protoResult.status());
|
||||
if (protoResult.has_value()) {
|
||||
aidlvhal::VehiclePropValue value;
|
||||
proto_msg_converter::protoToAidl(protoResult.value(), &value);
|
||||
result.prop = std::move(value);
|
||||
}
|
||||
}
|
||||
(*callback)(std::move(results));
|
||||
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
|
||||
void GRPCVehicleHardware::registerOnPropertyChangeEvent(
|
||||
std::unique_ptr<const PropertyChangeCallback> callback) {
|
||||
std::lock_guard lck(mCallbackMutex);
|
||||
if (mOnPropChange) {
|
||||
LOG(ERROR) << __func__ << " must only be called once.";
|
||||
return;
|
||||
}
|
||||
mOnPropChange = std::move(callback);
|
||||
}
|
||||
|
||||
void GRPCVehicleHardware::registerOnPropertySetErrorEvent(
|
||||
std::unique_ptr<const PropertySetErrorCallback> callback) {
|
||||
std::lock_guard lck(mCallbackMutex);
|
||||
if (mOnSetErr) {
|
||||
LOG(ERROR) << __func__ << " must only be called once.";
|
||||
return;
|
||||
}
|
||||
mOnSetErr = std::move(callback);
|
||||
}
|
||||
|
||||
DumpResult GRPCVehicleHardware::dump(const std::vector<std::string>& /* options */) {
|
||||
// TODO(chenhaosjtuacm): To be implemented.
|
||||
return {};
|
||||
}
|
||||
|
||||
aidlvhal::StatusCode GRPCVehicleHardware::checkHealth() {
|
||||
// TODO(chenhaosjtuacm): To be implemented.
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
|
||||
aidlvhal::StatusCode GRPCVehicleHardware::updateSampleRate(int32_t /* propId */,
|
||||
int32_t /* areaId */,
|
||||
float /* sampleRate */) {
|
||||
// TODO(chenhaosjtuacm): To be implemented.
|
||||
return aidlvhal::StatusCode::OK;
|
||||
}
|
||||
|
||||
bool GRPCVehicleHardware::waitForConnected(std::chrono::milliseconds waitTime) {
|
||||
return mGrpcChannel->WaitForConnected(gpr_time_add(
|
||||
gpr_now(GPR_CLOCK_MONOTONIC), gpr_time_from_millis(waitTime.count(), GPR_TIMESPAN)));
|
||||
}
|
||||
|
||||
void GRPCVehicleHardware::ValuePollingLoop() {
|
||||
while (!mShuttingDownFlag.load()) {
|
||||
::grpc::ClientContext context;
|
||||
|
||||
bool rpc_stopped{false};
|
||||
std::thread shuttingdown_watcher([this, &rpc_stopped, &context]() {
|
||||
std::unique_lock<std::mutex> lck(mShutdownMutex);
|
||||
mShutdownCV.wait(lck, [this, &rpc_stopped]() {
|
||||
return rpc_stopped || mShuttingDownFlag.load();
|
||||
});
|
||||
context.TryCancel();
|
||||
});
|
||||
|
||||
auto value_stream =
|
||||
mGrpcStub->StartPropertyValuesStream(&context, ::google::protobuf::Empty());
|
||||
LOG(INFO) << __func__ << ": GRPC Value Streaming Started";
|
||||
proto::VehiclePropValues protoValues;
|
||||
while (!mShuttingDownFlag.load() && value_stream->Read(&protoValues)) {
|
||||
std::vector<aidlvhal::VehiclePropValue> values;
|
||||
for (const auto protoValue : protoValues.values()) {
|
||||
values.push_back(aidlvhal::VehiclePropValue());
|
||||
proto_msg_converter::protoToAidl(protoValue, &values.back());
|
||||
}
|
||||
std::shared_lock lck(mCallbackMutex);
|
||||
if (mOnPropChange) {
|
||||
(*mOnPropChange)(values);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lck(mShutdownMutex);
|
||||
rpc_stopped = true;
|
||||
}
|
||||
mShutdownCV.notify_all();
|
||||
shuttingdown_watcher.join();
|
||||
|
||||
auto grpc_status = value_stream->Finish();
|
||||
// never reach here until connection lost
|
||||
LOG(ERROR) << __func__ << ": GRPC Value Streaming Failed: " << grpc_status.error_message();
|
||||
|
||||
// try to reconnect
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android::hardware::automotive::vehicle::virtualization
|
100
automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
Normal file
100
automotive/vehicle/aidl/impl/grpc/GRPCVehicleHardware.h
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IVehicleHardware.h>
|
||||
#include <VehicleHalTypes.h>
|
||||
#include <VehicleUtils.h>
|
||||
#include <android-base/result.h>
|
||||
|
||||
#include "VehicleServer.grpc.pb.h"
|
||||
#include "VehicleServer.pb.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace android::hardware::automotive::vehicle::virtualization {
|
||||
|
||||
namespace aidlvhal = ::aidl::android::hardware::automotive::vehicle;
|
||||
|
||||
class GRPCVehicleHardware : public IVehicleHardware {
|
||||
public:
|
||||
explicit GRPCVehicleHardware(std::string service_addr);
|
||||
|
||||
~GRPCVehicleHardware();
|
||||
|
||||
// Get all the property configs.
|
||||
std::vector<aidlvhal::VehiclePropConfig> getAllPropertyConfigs() const override;
|
||||
|
||||
// Set property values asynchronously. Server could return before the property set requests
|
||||
// are sent to vehicle bus or before property set confirmation is received. The callback is
|
||||
// safe to be called after the function returns and is safe to be called in a different thread.
|
||||
aidlvhal::StatusCode setValues(std::shared_ptr<const SetValuesCallback> callback,
|
||||
const std::vector<aidlvhal::SetValueRequest>& requests) override;
|
||||
|
||||
// Get property values asynchronously. Server could return before the property values are ready.
|
||||
// The callback is safe to be called after the function returns and is safe to be called in a
|
||||
// different thread.
|
||||
aidlvhal::StatusCode getValues(
|
||||
std::shared_ptr<const GetValuesCallback> callback,
|
||||
const std::vector<aidlvhal::GetValueRequest>& requests) const override;
|
||||
|
||||
// Dump debug information in the server.
|
||||
DumpResult dump(const std::vector<std::string>& options) override;
|
||||
|
||||
// Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
|
||||
aidlvhal::StatusCode checkHealth() override;
|
||||
|
||||
// Register a callback that would be called when there is a property change event from vehicle.
|
||||
void registerOnPropertyChangeEvent(
|
||||
std::unique_ptr<const PropertyChangeCallback> callback) override;
|
||||
|
||||
// Register a callback that would be called when there is a property set error event from
|
||||
// vehicle.
|
||||
void registerOnPropertySetErrorEvent(
|
||||
std::unique_ptr<const PropertySetErrorCallback> callback) override;
|
||||
|
||||
// Update the sample rate for the [propId, areaId] pair.
|
||||
aidlvhal::StatusCode updateSampleRate(int32_t propId, int32_t areaId,
|
||||
float sampleRate) override;
|
||||
|
||||
bool waitForConnected(std::chrono::milliseconds waitTime);
|
||||
|
||||
private:
|
||||
void ValuePollingLoop();
|
||||
|
||||
std::string mServiceAddr;
|
||||
std::shared_ptr<::grpc::Channel> mGrpcChannel;
|
||||
std::unique_ptr<proto::VehicleServer::Stub> mGrpcStub;
|
||||
std::thread mValuePollingThread;
|
||||
|
||||
std::shared_mutex mCallbackMutex;
|
||||
std::unique_ptr<const PropertyChangeCallback> mOnPropChange;
|
||||
std::unique_ptr<const PropertySetErrorCallback> mOnSetErr;
|
||||
|
||||
std::mutex mShutdownMutex;
|
||||
std::condition_variable mShutdownCV;
|
||||
std::atomic<bool> mShuttingDownFlag{false};
|
||||
};
|
||||
|
||||
} // namespace android::hardware::automotive::vehicle::virtualization
|
3
automotive/vehicle/aidl/impl/grpc/OWNERS
Normal file
3
automotive/vehicle/aidl/impl/grpc/OWNERS
Normal file
|
@ -0,0 +1,3 @@
|
|||
shanyu@google.com
|
||||
chenhaosjtuacm@google.com
|
||||
egranata@google.com
|
43
automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
Normal file
43
automotive/vehicle/aidl/impl/grpc/proto/VehicleServer.proto
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.
|
||||
*/
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package android.hardware.automotive.vehicle.proto;
|
||||
|
||||
import "android/hardware/automotive/vehicle/StatusCode.proto";
|
||||
import "android/hardware/automotive/vehicle/VehiclePropConfig.proto";
|
||||
import "android/hardware/automotive/vehicle/VehiclePropValue.proto";
|
||||
import "android/hardware/automotive/vehicle/VehiclePropValueRequest.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
|
||||
message VehicleHalCallStatus {
|
||||
StatusCode status_code = 1;
|
||||
}
|
||||
|
||||
message VehiclePropValues {
|
||||
repeated VehiclePropValue values = 1;
|
||||
}
|
||||
|
||||
service VehicleServer {
|
||||
rpc GetAllPropertyConfig(google.protobuf.Empty) returns (stream VehiclePropConfig) {}
|
||||
|
||||
rpc SetValues(VehiclePropValueRequests) returns (SetValueResults) {}
|
||||
|
||||
rpc GetValues(VehiclePropValueRequests) returns (GetValueResults) {}
|
||||
|
||||
rpc StartPropertyValuesStream(google.protobuf.Empty) returns (stream VehiclePropValues) {}
|
||||
}
|
46
automotive/vehicle/aidl/impl/grpc/test/Android.bp
Normal file
46
automotive/vehicle/aidl/impl/grpc/test/Android.bp
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright (C) 2023 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 {
|
||||
default_applicable_licenses: ["Android-Apache-2.0"],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "GRPCVehicleHardwareUnitTest",
|
||||
vendor: true,
|
||||
srcs: ["GRPCVehicleHardwareUnitTest.cpp"],
|
||||
whole_static_libs: [
|
||||
"android.hardware.automotive.vehicle@default-grpc-hardware-lib",
|
||||
],
|
||||
header_libs: [
|
||||
"IVehicleHardware",
|
||||
],
|
||||
static_libs: [
|
||||
"libgtest",
|
||||
"libgmock",
|
||||
],
|
||||
shared_libs: [
|
||||
"libgrpc++",
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
// libgrpc++.so is installed as root, require root to access it.
|
||||
require_root: true,
|
||||
defaults: [
|
||||
"VehicleHalDefaults",
|
||||
],
|
||||
cflags: [
|
||||
"-Wno-unused-parameter",
|
||||
],
|
||||
test_suites: ["device-tests"],
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (C) 2023 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.
|
||||
|
||||
#include "GRPCVehicleHardware.h"
|
||||
#include "VehicleServer.grpc.pb.h"
|
||||
#include "VehicleServer.pb.h"
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include <grpc++/grpc++.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace android::hardware::automotive::vehicle::virtualization {
|
||||
|
||||
const std::string kFakeServerAddr = "0.0.0.0:54321";
|
||||
|
||||
class FakeVehicleServer : public proto::VehicleServer::Service {
|
||||
public:
|
||||
::grpc::Status StartPropertyValuesStream(
|
||||
::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
|
||||
::grpc::ServerWriter<proto::VehiclePropValues>* stream) override {
|
||||
stream->Write(proto::VehiclePropValues());
|
||||
// A fake disconnection.
|
||||
return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
|
||||
}
|
||||
|
||||
// Functions that we do not care.
|
||||
::grpc::Status GetAllPropertyConfig(
|
||||
::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
|
||||
::grpc::ServerWriter<proto::VehiclePropConfig>* stream) override {
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
::grpc::Status SetValues(::grpc::ServerContext* context,
|
||||
const proto::VehiclePropValueRequests* requests,
|
||||
proto::SetValueResults* results) override {
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
|
||||
::grpc::Status GetValues(::grpc::ServerContext* context,
|
||||
const proto::VehiclePropValueRequests* requests,
|
||||
proto::GetValueResults* results) override {
|
||||
return ::grpc::Status::OK;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(GRPCVehicleHardwareUnitTest, Reconnect) {
|
||||
auto receivedUpdate = std::make_shared<std::atomic<int>>(0);
|
||||
auto vehicleHardware = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
|
||||
vehicleHardware->registerOnPropertyChangeEvent(
|
||||
std::make_unique<const IVehicleHardware::PropertyChangeCallback>(
|
||||
[receivedUpdate](const auto&) { receivedUpdate->fetch_add(1); }));
|
||||
|
||||
constexpr size_t kServerRestartTimes = 5;
|
||||
for (size_t serverStart = 0; serverStart < kServerRestartTimes; ++serverStart) {
|
||||
EXPECT_EQ(receivedUpdate->load(), 0);
|
||||
auto fakeServer = std::make_unique<FakeVehicleServer>();
|
||||
::grpc::ServerBuilder builder;
|
||||
builder.RegisterService(fakeServer.get());
|
||||
builder.AddListeningPort(kFakeServerAddr, ::grpc::InsecureServerCredentials());
|
||||
auto grpcServer = builder.BuildAndStart();
|
||||
|
||||
// Wait until the vehicle hardware received the second update (after one fake
|
||||
// disconnection).
|
||||
constexpr auto kMaxWaitTime = std::chrono::seconds(5);
|
||||
auto startTime = std::chrono::steady_clock::now();
|
||||
while (receivedUpdate->load() <= 1 &&
|
||||
std::chrono::steady_clock::now() - startTime < kMaxWaitTime)
|
||||
;
|
||||
|
||||
grpcServer->Shutdown();
|
||||
grpcServer->Wait();
|
||||
EXPECT_GT(receivedUpdate->load(), 1);
|
||||
|
||||
// Reset for the next round.
|
||||
receivedUpdate->store(0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android::hardware::automotive::vehicle::virtualization
|
Loading…
Reference in a new issue