Implement supported values API in GRPC VHAL client/server.

Define new protobuf interface for GRPC VHAL. Implement the GRPC
VHAL client/server.

Test: Manual test on cf.
atest GRPCVehicleHardwareUnitTest GRPCVehicleProxyServerUnitTest
Flag: EXEMPT HAL
Bug: 393154530

Change-Id: I9252d6f42a5f43f1829f431887126142d69102f9
diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp
index 8750375..e64c696 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.cpp
@@ -29,19 +29,45 @@
 
 namespace android::hardware::automotive::vehicle::virtualization {
 
+using ::grpc::ChannelCredentials;
+using ::grpc::ClientContext;
+using ::grpc::CreateChannel;
+using ::grpc::InsecureChannelCredentials;
+using ::grpc::Status;
+
 namespace {
 
 constexpr size_t MAX_RETRY_COUNT = 5;
 
-std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
-    return ::grpc::InsecureChannelCredentials();
+std::shared_ptr<ChannelCredentials> getChannelCredentials() {
+    return InsecureChannelCredentials();
+}
+
+template <class ProtoRequestType>
+void fillPropIdAreaIdsToProtoRequest(const std::vector<PropIdAreaId>& propIdAreaIds,
+                                     ProtoRequestType* protoRequest) {
+    for (const auto& propIdAreaId : propIdAreaIds) {
+        proto_msg_converter::aidlToProto(propIdAreaId, protoRequest->add_prop_id_area_id());
+    }
+}
+
+template <class AidlResultType, class ProtoResultType>
+std::vector<AidlResultType> convertSupportedValueProtoResultToAidlResults(
+        const std::vector<PropIdAreaId>& propIdAreaIds, const ProtoResultType& protoResult) {
+    std::vector<AidlResultType> aidlResults;
+    for (const auto& protoResultPerRequest : protoResult.result()) {
+        AidlResultType aidlResult = {};
+        proto_msg_converter::protoToAidl(protoResultPerRequest, &aidlResult);
+        aidlResults.push_back(std::move(aidlResult));
+    }
+    return aidlResults;
 }
 
 }  // namespace
 
 GRPCVehicleHardware::GRPCVehicleHardware(std::string service_addr)
     : mServiceAddr(std::move(service_addr)),
-      mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())),
+      mGrpcChannel(CreateChannel(mServiceAddr, getChannelCredentials())),
       mGrpcStub(proto::VehicleServer::NewStub(mGrpcChannel)),
       mValuePollingThread([this] { ValuePollingLoop(); }) {}
 
@@ -67,7 +93,7 @@
 
 std::vector<aidlvhal::VehiclePropConfig> GRPCVehicleHardware::getAllPropertyConfigs() const {
     std::vector<aidlvhal::VehiclePropConfig> configs;
-    ::grpc::ClientContext context;
+    ClientContext context;
     auto config_stream = mGrpcStub->GetAllPropertyConfig(&context, ::google::protobuf::Empty());
     proto::VehiclePropConfig protoConfig;
     while (config_stream->Read(&protoConfig)) {
@@ -97,7 +123,7 @@
 aidlvhal::StatusCode GRPCVehicleHardware::setValues(
         std::shared_ptr<const SetValuesCallback> callback,
         const std::vector<aidlvhal::SetValueRequest>& requests) {
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::VehiclePropValueRequests protoRequests;
     proto::SetValueResults protoResults;
     for (const auto& request : requests) {
@@ -160,7 +186,7 @@
     }
 
     // TODO(chenhaosjtuacm): Make it Async.
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::GetValueResults protoResults;
     auto grpc_status = mGrpcStub->GetValues(&context, protoRequests, &protoResults);
     if (!grpc_status.ok()) {
@@ -262,7 +288,7 @@
 }
 
 DumpResult GRPCVehicleHardware::dump(const std::vector<std::string>& options) {
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::DumpOptions protoDumpOptions;
     proto::DumpResult protoDumpResult;
     for (const auto& option : options) {
@@ -281,7 +307,7 @@
 }
 
 aidlvhal::StatusCode GRPCVehicleHardware::checkHealth() {
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::VehicleHalCallStatus protoStatus;
     auto grpc_status = mGrpcStub->CheckHealth(&context, ::google::protobuf::Empty(), &protoStatus);
     if (!grpc_status.ok()) {
@@ -293,7 +319,7 @@
 
 aidlvhal::StatusCode GRPCVehicleHardware::subscribe(aidlvhal::SubscribeOptions options) {
     proto::SubscribeRequest request;
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::VehicleHalCallStatus protoStatus;
     proto_msg_converter::aidlToProto(options, request.mutable_options());
     auto grpc_status = mGrpcStub->Subscribe(&context, request, &protoStatus);
@@ -311,7 +337,7 @@
 
 aidlvhal::StatusCode GRPCVehicleHardware::unsubscribe(int32_t propId, int32_t areaId) {
     proto::UnsubscribeRequest request;
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::VehicleHalCallStatus protoStatus;
     request.set_prop_id(propId);
     request.set_area_id(areaId);
@@ -330,7 +356,7 @@
 
 aidlvhal::StatusCode GRPCVehicleHardware::updateSampleRate(int32_t propId, int32_t areaId,
                                                            float sampleRate) {
-    ::grpc::ClientContext context;
+    ClientContext context;
     proto::UpdateSampleRateRequest request;
     proto::VehicleHalCallStatus protoStatus;
     request.set_prop(propId);
@@ -357,7 +383,7 @@
 }
 
 void GRPCVehicleHardware::pollValue() {
-    ::grpc::ClientContext context;
+    ClientContext context;
 
     bool rpc_stopped{false};
     std::thread shuttingdown_watcher([this, &rpc_stopped, &context]() {
@@ -408,4 +434,56 @@
     LOG(ERROR) << __func__ << ": GRPC Value Streaming Failed: " << grpc_status.error_message();
 }
 
+std::vector<aidlvhal::MinMaxSupportedValueResult> GRPCVehicleHardware::getMinMaxSupportedValues(
+        const std::vector<PropIdAreaId>& propIdAreaIds) {
+    ClientContext context;
+    proto::GetMinMaxSupportedValuesRequest protoRequest = {};
+    proto::GetMinMaxSupportedValuesResult protoResult = {};
+    fillPropIdAreaIdsToProtoRequest(propIdAreaIds, &protoRequest);
+
+    auto grpc_status = mGrpcStub->GetMinMaxSupportedValues(&context, protoRequest, &protoResult);
+    std::vector<aidlvhal::MinMaxSupportedValueResult> aidlResults;
+    if (!grpc_status.ok()) {
+        LOG(ERROR) << __func__
+                   << ": GRPC GetMinMaxSupportedValues Failed: " << grpc_status.error_message();
+        for (const auto& propIdAreaId : propIdAreaIds) {
+            aidlResults.push_back({
+                    .status = aidlvhal::StatusCode::INTERNAL_ERROR,
+            });
+        }
+        return aidlResults;
+    }
+    aidlResults =
+            convertSupportedValueProtoResultToAidlResults<aidlvhal::MinMaxSupportedValueResult,
+                                                          proto::GetMinMaxSupportedValuesResult>(
+                    propIdAreaIds, protoResult);
+    return aidlResults;
+}
+
+std::vector<aidlvhal::SupportedValuesListResult> GRPCVehicleHardware::getSupportedValuesLists(
+        const std::vector<PropIdAreaId>& propIdAreaIds) {
+    ClientContext context;
+    proto::GetSupportedValuesListsRequest protoRequest = {};
+    proto::GetSupportedValuesListsResult protoResult = {};
+    fillPropIdAreaIdsToProtoRequest(propIdAreaIds, &protoRequest);
+
+    auto grpc_status = mGrpcStub->GetSupportedValuesLists(&context, protoRequest, &protoResult);
+    std::vector<aidlvhal::SupportedValuesListResult> aidlResults;
+    if (!grpc_status.ok()) {
+        LOG(ERROR) << __func__
+                   << ": GRPC GetSupportedValuesLists Failed: " << grpc_status.error_message();
+        for (const auto& propIdAreaId : propIdAreaIds) {
+            aidlResults.push_back({
+                    .status = aidlvhal::StatusCode::INTERNAL_ERROR,
+            });
+        }
+        return aidlResults;
+    }
+    aidlResults =
+            convertSupportedValueProtoResultToAidlResults<aidlvhal::SupportedValuesListResult,
+                                                          proto::GetSupportedValuesListsResult>(
+                    propIdAreaIds, protoResult);
+    return aidlResults;
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h
index ad2f512..7fc3d79 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleHardware.h
@@ -90,6 +90,12 @@
 
     aidlvhal::StatusCode unsubscribe(int32_t propId, int32_t areaId) override;
 
+    std::vector<aidlvhal::MinMaxSupportedValueResult> getMinMaxSupportedValues(
+            const std::vector<PropIdAreaId>& propIdAreaIds) override;
+
+    std::vector<aidlvhal::SupportedValuesListResult> getSupportedValuesLists(
+            const std::vector<PropIdAreaId>& propIdAreaIds) override;
+
     bool waitForConnected(std::chrono::milliseconds waitTime);
 
   protected:
diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp
index 927a595..f216683 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp
+++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.cpp
@@ -31,13 +31,33 @@
 
 namespace android::hardware::automotive::vehicle::virtualization {
 
-std::atomic<uint64_t> GrpcVehicleProxyServer::ConnectionDescriptor::connection_id_counter_{0};
-
-static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
-    // TODO(chenhaosjtuacm): get secured credentials here
+namespace {
+std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
     return ::grpc::InsecureServerCredentials();
 }
 
+template <class ProtoRequestType>
+std::vector<PropIdAreaId> getPropIdAreaIdsFromProtoRequest(const ProtoRequestType* request) {
+    std::vector<PropIdAreaId> propIdAreaIds;
+    for (const proto::PropIdAreaId& protoPropIdAreaId : request->prop_id_area_id()) {
+        PropIdAreaId aidlPropIdAreaId = {};
+        proto_msg_converter::protoToAidl(protoPropIdAreaId, &aidlPropIdAreaId);
+        propIdAreaIds.push_back(aidlPropIdAreaId);
+    }
+    return propIdAreaIds;
+}
+
+template <class AidlResultType, class ProtoResultType>
+void aidlResultsToProtoResults(const AidlResultType& aidlResults, ProtoResultType* result) {
+    for (const auto& aidlResult : aidlResults) {
+        auto* protoResult = result->add_result();
+        proto_msg_converter::aidlToProto(aidlResult, protoResult);
+    }
+}
+}  // namespace
+
+std::atomic<uint64_t> GrpcVehicleProxyServer::ConnectionDescriptor::connection_id_counter_{0};
+
 GrpcVehicleProxyServer::GrpcVehicleProxyServer(std::string serverAddr,
                                                std::unique_ptr<IVehicleHardware>&& hardware)
     : GrpcVehicleProxyServer(std::vector<std::string>({serverAddr}), std::move(hardware)) {};
@@ -243,6 +263,26 @@
     return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
 }
 
+::grpc::Status GrpcVehicleProxyServer::GetMinMaxSupportedValues(
+        ::grpc::ServerContext* context, const proto::GetMinMaxSupportedValuesRequest* request,
+        proto::GetMinMaxSupportedValuesResult* result) {
+    std::vector<PropIdAreaId> propIdAreaIds = getPropIdAreaIdsFromProtoRequest(request);
+    std::vector<aidlvhal::MinMaxSupportedValueResult> minMaxSupportedValueResults =
+            mHardware->getMinMaxSupportedValues(propIdAreaIds);
+    aidlResultsToProtoResults(minMaxSupportedValueResults, result);
+    return ::grpc::Status::OK;
+}
+
+::grpc::Status GrpcVehicleProxyServer::GetSupportedValuesLists(
+        ::grpc::ServerContext* context, const proto::GetSupportedValuesListsRequest* request,
+        proto::GetSupportedValuesListsResult* result) {
+    std::vector<PropIdAreaId> propIdAreaIds = getPropIdAreaIdsFromProtoRequest(request);
+    std::vector<aidlvhal::SupportedValuesListResult> supportedValuesListResults =
+            mHardware->getSupportedValuesLists(propIdAreaIds);
+    aidlResultsToProtoResults(supportedValuesListResults, result);
+    return ::grpc::Status::OK;
+}
+
 void GrpcVehicleProxyServer::OnVehiclePropChange(
         const std::vector<aidlvhal::VehiclePropValue>& values) {
     std::unordered_set<uint64_t> brokenConn;
diff --git a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h
index 5ffb531..eb261ca 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h
+++ b/automotive/vehicle/aidl/impl/current/grpc/GRPCVehicleProxyServer.h
@@ -77,6 +77,14 @@
             ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
             ::grpc::ServerWriter<proto::VehiclePropValues>* stream) override;
 
+    ::grpc::Status GetMinMaxSupportedValues(
+            ::grpc::ServerContext* context, const proto::GetMinMaxSupportedValuesRequest* requests,
+            proto::GetMinMaxSupportedValuesResult* results) override;
+
+    ::grpc::Status GetSupportedValuesLists(::grpc::ServerContext* context,
+                                           const proto::GetSupportedValuesListsRequest* requests,
+                                           proto::GetSupportedValuesListsResult* results) override;
+
     GrpcVehicleProxyServer& Start();
 
     GrpcVehicleProxyServer& Shutdown();
diff --git a/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto b/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto
index 732957f..3364ed7 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto
+++ b/automotive/vehicle/aidl/impl/current/grpc/proto/VehicleServer.proto
@@ -20,6 +20,8 @@
 
 import "android/hardware/automotive/vehicle/DumpOptions.proto";
 import "android/hardware/automotive/vehicle/DumpResult.proto";
+import "android/hardware/automotive/vehicle/GetMinMaxSupportedValuesTypes.proto";
+import "android/hardware/automotive/vehicle/GetSupportedValuesListsTypes.proto";
 import "android/hardware/automotive/vehicle/SubscribeRequest.proto";
 import "android/hardware/automotive/vehicle/StatusCode.proto";
 import "android/hardware/automotive/vehicle/UnsubscribeRequest.proto";
@@ -46,4 +48,10 @@
     rpc Subscribe(SubscribeRequest) returns (VehicleHalCallStatus) {}
 
     rpc Unsubscribe(UnsubscribeRequest) returns (VehicleHalCallStatus) {}
+
+    rpc GetMinMaxSupportedValues(GetMinMaxSupportedValuesRequest)
+            returns (GetMinMaxSupportedValuesResult) {}
+
+    rpc GetSupportedValuesLists(GetSupportedValuesListsRequest)
+            returns (GetSupportedValuesListsResult) {}
 }
diff --git a/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp
index 20af231..343e5b2 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleHardwareUnitTest.cpp
@@ -442,4 +442,119 @@
     EXPECT_LT(gotResults[0].prop->timestamp, elapsedRealtimeNano());
 }
 
+TEST_F(GRPCVehicleHardwareUnitTest, testGetMinMaxSupportedValues) {
+    int32_t testPropId = 1234;
+    int32_t testAreaId = 4321;
+    int32_t testValue1 = 12345;
+    int32_t testValue2 = 123456;
+    std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
+
+    EXPECT_CALL(*mGrpcStub, GetMinMaxSupportedValues(_, _, _))
+            .WillOnce([=](::grpc::ClientContext* context,
+                          const proto::GetMinMaxSupportedValuesRequest& request,
+                          proto::GetMinMaxSupportedValuesResult* response) {
+                for (const auto& propIdAreaId : request.prop_id_area_id()) {
+                    proto::MinMaxSupportedValueResult* individualResult = response->add_result();
+                    individualResult->set_status(proto::StatusCode::OK);
+                    individualResult->mutable_min_supported_value()->add_int32_values(testValue1);
+                    individualResult->mutable_max_supported_value()->add_int32_values(testValue2);
+                }
+                return ::grpc::Status::OK;
+            });
+
+    auto results = mHardware->getMinMaxSupportedValues(propIdAreaIds);
+
+    ASSERT_THAT(results, ::testing::SizeIs(1));
+    EXPECT_EQ(results[0].status, aidlvhal::StatusCode::OK);
+    ASSERT_TRUE(results[0].minSupportedValue.has_value());
+    EXPECT_EQ(results[0].minSupportedValue.value(),
+              aidlvhal::RawPropValues{.int32Values = {testValue1}});
+    ASSERT_TRUE(results[0].maxSupportedValue.has_value());
+    EXPECT_EQ(results[0].maxSupportedValue.value(),
+              aidlvhal::RawPropValues{.int32Values = {testValue2}});
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, testGetMinMaxSupportedValues_noMaxValue) {
+    int32_t testPropId = 1234;
+    int32_t testAreaId = 4321;
+    int32_t testValue1 = 12345;
+    std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
+
+    EXPECT_CALL(*mGrpcStub, GetMinMaxSupportedValues(_, _, _))
+            .WillOnce([=](::grpc::ClientContext* context,
+                          const proto::GetMinMaxSupportedValuesRequest& request,
+                          proto::GetMinMaxSupportedValuesResult* response) {
+                for (const auto& propIdAreaId : request.prop_id_area_id()) {
+                    proto::MinMaxSupportedValueResult* individualResult = response->add_result();
+                    individualResult->set_status(proto::StatusCode::OK);
+                    individualResult->mutable_min_supported_value()->add_int32_values(testValue1);
+                }
+                return ::grpc::Status::OK;
+            });
+
+    auto results = mHardware->getMinMaxSupportedValues(propIdAreaIds);
+
+    ASSERT_THAT(results, ::testing::SizeIs(1));
+    EXPECT_EQ(results[0].status, aidlvhal::StatusCode::OK);
+    ASSERT_TRUE(results[0].minSupportedValue.has_value());
+    EXPECT_EQ(results[0].minSupportedValue.value(),
+              aidlvhal::RawPropValues{.int32Values = {testValue1}});
+    ASSERT_FALSE(results[0].maxSupportedValue.has_value());
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, testGetSupportedValuesLists) {
+    int32_t testPropId = 1234;
+    int32_t testAreaId = 4321;
+    int32_t testValue1 = 12345;
+    int32_t testValue2 = 123456;
+    std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
+
+    EXPECT_CALL(*mGrpcStub, GetSupportedValuesLists(_, _, _))
+            .WillOnce([=](::grpc::ClientContext* context,
+                          const proto::GetSupportedValuesListsRequest& request,
+                          proto::GetSupportedValuesListsResult* response) {
+                for (const auto& propIdAreaId : request.prop_id_area_id()) {
+                    proto::SupportedValuesListResult* individualResult = response->add_result();
+                    individualResult->set_status(proto::StatusCode::OK);
+                    individualResult->add_supported_values_list()->add_int32_values(testValue1);
+                    individualResult->add_supported_values_list()->add_int32_values(testValue2);
+                }
+                return ::grpc::Status::OK;
+            });
+
+    auto results = mHardware->getSupportedValuesLists(propIdAreaIds);
+
+    ASSERT_THAT(results, ::testing::SizeIs(1));
+    EXPECT_EQ(results[0].status, aidlvhal::StatusCode::OK);
+    ASSERT_TRUE(results[0].supportedValuesList.has_value());
+    ASSERT_THAT(results[0].supportedValuesList.value(), ::testing::SizeIs(2));
+    EXPECT_EQ(results[0].supportedValuesList.value()[0],
+              aidlvhal::RawPropValues{.int32Values = {testValue1}});
+    EXPECT_EQ(results[0].supportedValuesList.value()[1],
+              aidlvhal::RawPropValues{.int32Values = {testValue2}});
+}
+
+TEST_F(GRPCVehicleHardwareUnitTest, testGetSupportedValuesLists_noSupportedValue) {
+    int32_t testPropId = 1234;
+    int32_t testAreaId = 4321;
+    std::vector<PropIdAreaId> propIdAreaIds = {{.propId = testPropId, .areaId = testAreaId}};
+
+    EXPECT_CALL(*mGrpcStub, GetSupportedValuesLists(_, _, _))
+            .WillOnce([=](::grpc::ClientContext* context,
+                          const proto::GetSupportedValuesListsRequest& request,
+                          proto::GetSupportedValuesListsResult* response) {
+                for (const auto& propIdAreaId : request.prop_id_area_id()) {
+                    proto::SupportedValuesListResult* individualResult = response->add_result();
+                    individualResult->set_status(proto::StatusCode::INTERNAL_ERROR);
+                }
+                return ::grpc::Status::OK;
+            });
+
+    auto results = mHardware->getSupportedValuesLists(propIdAreaIds);
+
+    ASSERT_THAT(results, ::testing::SizeIs(1));
+    EXPECT_EQ(results[0].status, aidlvhal::StatusCode::INTERNAL_ERROR);
+    ASSERT_FALSE(results[0].supportedValuesList.has_value());
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization
diff --git a/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
index ca5c2d5..c07c629 100644
--- a/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
+++ b/automotive/vehicle/aidl/impl/current/grpc/test/GRPCVehicleProxyServerUnitTest.cpp
@@ -105,6 +105,10 @@
     MOCK_METHOD(aidlvhal::StatusCode, unsubscribe, (int32_t propId, int32_t areaId), (override));
     MOCK_METHOD(aidlvhal::StatusCode, updateSampleRate,
                 (int32_t propId, int32_t areaId, float sampleRate), (override));
+    MOCK_METHOD(std::vector<aidlvhal::MinMaxSupportedValueResult>, getMinMaxSupportedValues,
+                (const std::vector<PropIdAreaId>& propIdAreaIds), (override));
+    MOCK_METHOD(std::vector<aidlvhal::SupportedValuesListResult>, getSupportedValuesLists,
+                (const std::vector<PropIdAreaId>& propIdAreaIds), (override));
 };
 
 TEST(GRPCVehicleProxyServerUnitTest, ClientConnectDisconnect) {
@@ -117,7 +121,7 @@
 
     constexpr auto kWaitForConnectionMaxTime = std::chrono::seconds(5);
     constexpr auto kWaitForStreamStartTime = std::chrono::seconds(1);
-    constexpr auto kWaitForUpdateDeliveryTime = std::chrono::milliseconds(100);
+    constexpr auto kWaitForUpdateDeliveryTime = std::chrono::seconds(1);
 
     auto updateReceived1 = std::make_shared<bool>(false);
     auto vehicleHardware1 = std::make_unique<GRPCVehicleHardware>(kFakeServerAddr);
@@ -129,7 +133,7 @@
 
     // Client hardware 1 received update from the server.
     EXPECT_FALSE(*updateReceived1);
-    testHardwareRaw->onPropertyEvent({});
+    testHardwareRaw->onPropertyEvent({aidlvhal::VehiclePropValue{.prop = 1}});
     // Wait for the update delivery.
     std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
     EXPECT_TRUE(*updateReceived1);
@@ -148,7 +152,7 @@
     // Both client hardware 1 and 2 received update from the server.
     EXPECT_FALSE(*updateReceived1);
     EXPECT_FALSE(*updateReceived2);
-    testHardwareRaw->onPropertyEvent({});
+    testHardwareRaw->onPropertyEvent({aidlvhal::VehiclePropValue{.prop = 1}});
     // Wait for the update delivery.
     std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
     EXPECT_TRUE(*updateReceived1);
@@ -163,7 +167,7 @@
     // Client 1 exited, only client hardware 2 received update from the server.
     EXPECT_FALSE(*updateReceived1);
     EXPECT_FALSE(*updateReceived2);
-    testHardwareRaw->onPropertyEvent({});
+    testHardwareRaw->onPropertyEvent({aidlvhal::VehiclePropValue{.prop = 1}});
     // Wait for the update delivery.
     std::this_thread::sleep_for(kWaitForUpdateDeliveryTime);
     EXPECT_FALSE(*updateReceived1);
@@ -238,4 +242,85 @@
     EXPECT_EQ(returnStatus.status_code(), proto::StatusCode::OK);
 }
 
+TEST(GRPCVehicleProxyServerUnitTest, testGetMinMaxSupportedValues) {
+    int32_t testPropId = 1234;
+    int32_t testAreaId = 4321;
+    int32_t testValue1 = 12345;
+    int32_t testValue2 = 54321;
+    auto mockHardware = std::make_unique<MockVehicleHardware>();
+    // We make sure this is alive inside the function scope.
+    MockVehicleHardware* mockHardwarePtr = mockHardware.get();
+    GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
+    ::grpc::ServerContext context;
+    proto::GetMinMaxSupportedValuesRequest request;
+    proto::GetMinMaxSupportedValuesResult result;
+    auto* requestPropIdAreaId = request.add_prop_id_area_id();
+    requestPropIdAreaId->set_prop_id(testPropId);
+    requestPropIdAreaId->set_area_id(testAreaId);
+    std::vector<PropIdAreaId> propIdAreaIds;
+    std::vector<aidlvhal::MinMaxSupportedValueResult> resultFromHardware = {{
+            .status = aidlvhal::StatusCode::OK,
+            .minSupportedValue = aidlvhal::RawPropValues{.int32Values = {testValue1}},
+            .maxSupportedValue = aidlvhal::RawPropValues{.int32Values = {testValue2}},
+    }};
+
+    EXPECT_CALL(*mockHardwarePtr, getMinMaxSupportedValues(_))
+            .WillOnce(DoAll(SaveArg<0>(&propIdAreaIds), Return(resultFromHardware)));
+
+    auto grpcStatus = server.GetMinMaxSupportedValues(&context, &request, &result);
+
+    ASSERT_THAT(propIdAreaIds, ::testing::SizeIs(1));
+    EXPECT_EQ(propIdAreaIds[0], PropIdAreaId({.propId = testPropId, .areaId = testAreaId}));
+
+    ASSERT_TRUE(grpcStatus.ok());
+    ASSERT_THAT(result.result(), ::testing::SizeIs(1));
+    EXPECT_EQ(result.result()[0].status(), proto::StatusCode::OK);
+    ASSERT_THAT(result.result()[0].min_supported_value().int32_values(), ::testing::SizeIs(1));
+    EXPECT_EQ(result.result()[0].min_supported_value().int32_values()[0], testValue1);
+    ASSERT_THAT(result.result()[0].max_supported_value().int32_values(), ::testing::SizeIs(1));
+    EXPECT_EQ(result.result()[0].max_supported_value().int32_values()[0], testValue2);
+}
+
+TEST(GRPCVehicleProxyServerUnitTest, testGetSupportedValuesLists) {
+    int32_t testPropId = 1234;
+    int32_t testAreaId = 4321;
+    int32_t testValue1 = 12345;
+    int32_t testValue2 = 54321;
+    auto mockHardware = std::make_unique<MockVehicleHardware>();
+    // We make sure this is alive inside the function scope.
+    MockVehicleHardware* mockHardwarePtr = mockHardware.get();
+    GrpcVehicleProxyServer server = GrpcVehicleProxyServer("", std::move(mockHardware));
+    ::grpc::ServerContext context;
+    proto::GetSupportedValuesListsRequest request;
+    proto::GetSupportedValuesListsResult result;
+    auto* requestPropIdAreaId = request.add_prop_id_area_id();
+    requestPropIdAreaId->set_prop_id(testPropId);
+    requestPropIdAreaId->set_area_id(testAreaId);
+    std::vector<PropIdAreaId> propIdAreaIds;
+    std::vector<aidlvhal::SupportedValuesListResult> resultFromHardware = {{
+            .status = aidlvhal::StatusCode::OK,
+            .supportedValuesList = std::vector<std::optional<aidlvhal::RawPropValues>>({
+                    aidlvhal::RawPropValues{.int32Values = {testValue1}},
+                    aidlvhal::RawPropValues{.int32Values = {testValue2}},
+            }),
+    }};
+
+    EXPECT_CALL(*mockHardwarePtr, getSupportedValuesLists(_))
+            .WillOnce(DoAll(SaveArg<0>(&propIdAreaIds), Return(resultFromHardware)));
+
+    auto grpcStatus = server.GetSupportedValuesLists(&context, &request, &result);
+
+    ASSERT_THAT(propIdAreaIds, ::testing::SizeIs(1));
+    EXPECT_EQ(propIdAreaIds[0], PropIdAreaId({.propId = testPropId, .areaId = testAreaId}));
+
+    ASSERT_TRUE(grpcStatus.ok());
+    ASSERT_THAT(result.result(), ::testing::SizeIs(1));
+    EXPECT_EQ(result.result()[0].status(), proto::StatusCode::OK);
+    ASSERT_THAT(result.result()[0].supported_values_list(), ::testing::SizeIs(2));
+    ASSERT_THAT(result.result()[0].supported_values_list()[0].int32_values(), ::testing::SizeIs(1));
+    EXPECT_THAT(result.result()[0].supported_values_list()[0].int32_values()[0], testValue1);
+    ASSERT_THAT(result.result()[0].supported_values_list()[1].int32_values(), ::testing::SizeIs(1));
+    EXPECT_THAT(result.result()[0].supported_values_list()[1].int32_values()[0], testValue2);
+}
+
 }  // namespace android::hardware::automotive::vehicle::virtualization