Implement getPropConfigs in Default VHAL.

Test: atest DefaultVehicleHalTest
Bug: 200737967
Change-Id: Id0152cb2dbf489f5d709845108b87961f6d9a019
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
index dfc2efc..dcd9208 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp
@@ -22,10 +22,17 @@
     name: "FakeVehicleHardware",
     vendor: true,
     srcs: ["src/*.cpp"],
-    cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
-    defaults: ["VehicleHalDefaults"],
+    defaults: [
+        "VehicleHalDefaults",
+        "FakeVehicleHardwareDefaults",
+    ],
+}
+
+cc_defaults {
+    name: "FakeVehicleHardwareDefaults",
+    cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
     header_libs: [
         "IVehicleHardware",
         "VehicleHalDefaultConfig",
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 104147a..5b2003e 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -62,27 +62,6 @@
 const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/";
 const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override";
 
-template <class T>
-StatusCode getErrorCode(const Result<T>& result) {
-    if (result.ok()) {
-        return StatusCode::OK;
-    }
-    return static_cast<StatusCode>(result.error().code());
-}
-
-template <class T>
-int getIntErrorCode(const Result<T>& result) {
-    return toInt(getErrorCode(result));
-}
-
-template <class T>
-std::string getErrorMsg(const Result<T>& result) {
-    if (result.ok()) {
-        return "";
-    }
-    return result.error().message();
-}
-
 }  // namespace
 
 void FakeVehicleHardware::storePropInitialValue(const defaultconfig::ConfigDeclaration& config) {
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index 95e58c6..dfc7cbf 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -18,6 +18,8 @@
 #define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
 
 #include <VehicleHalTypes.h>
+
+#include <android-base/result.h>
 #include <utils/Log.h>
 
 namespace android {
@@ -183,6 +185,29 @@
     return size;
 }
 
+template <class T>
+::aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode(
+        const ::android::base::Result<T>& result) {
+    if (result.ok()) {
+        return ::aidl::android::hardware::automotive::vehicle::StatusCode::OK;
+    }
+    return static_cast<::aidl::android::hardware::automotive::vehicle::StatusCode>(
+            result.error().code());
+}
+
+template <class T>
+int getIntErrorCode(const ::android::base::Result<T>& result) {
+    return toInt(getErrorCode(result));
+}
+
+template <class T>
+std::string getErrorMsg(const ::android::base::Result<T>& result) {
+    if (result.ok()) {
+        return "";
+    }
+    return result.error().message();
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index 0704107..ef1d0f1 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -1,37 +1,65 @@
-// 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.
+/*
+ * 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 {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_interfaces_license"],
+    default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
 cc_binary {
     name: "android.hardware.automotive.vehicle-aidl-default-service",
-    defaults: ["VehicleHalDefaults"],
-    local_include_dirs: ["include"],
+    vendor: true,
+    defaults: [
+        "FakeVehicleHardwareDefaults",
+        "VehicleHalDefaults",
+        "android-automotive-large-parcelable-defaults",
+    ],
     vintf_fragments: ["vhal-default-service.xml"],
     init_rc: ["vhal-default-service.rc"],
-    vendor: true,
     relative_install_path: "hw",
-    srcs: ["src/*.cpp"],
+    srcs: ["src/VehicleService.cpp"],
+    static_libs: [
+        "DefaultVehicleHal",
+        "FakeVehicleHardware",
+        "VehicleHalUtils",
+        "android-automotive-large-parcelable-vendor-lib",
+    ],
+    header_libs: [
+        "IVehicleHardware",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+}
+
+cc_library {
+    name: "DefaultVehicleHal",
+    vendor: true,
+    defaults: [
+        "VehicleHalDefaults",
+        "android-automotive-large-parcelable-defaults",
+    ],
+    local_include_dirs: ["include"],
+    export_include_dirs: ["include"],
+    srcs: ["src/DefaultVehicleHal.cpp"],
     static_libs: [
         "VehicleHalUtils",
+        "android-automotive-large-parcelable-vendor-lib",
+    ],
+    header_libs: [
+        "IVehicleHardware",
     ],
     shared_libs: [
         "libbinder_ndk",
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index 49c501e..43bdca2 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -17,14 +17,68 @@
 #ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_
 #define android_hardware_automotive_vehicle_aidl_impl_vhal_include_DefaultVehicleHal_H_
 
+#include <IVehicleHardware.h>
+#include <LargeParcelableBase.h>
+#include <VehicleUtils.h>
 #include <aidl/android/hardware/automotive/vehicle/BnVehicle.h>
+#include <android/binder_auto_utils.h>
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
 
 namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
 
+// private namespace
+namespace defaultvehiclehal_impl {
+
+constexpr int INVALID_MEMORY_FD = -1;
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(
+        const ::android::base::Result<T>& result,
+        ::aidl::android::hardware::automotive::vehicle::StatusCode status) {
+    if (result.ok()) {
+        return ::ndk::ScopedAStatus::ok();
+    }
+    return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(toInt(status),
+                                                                     getErrorMsg(result).c_str());
+}
+
+template <class T>
+::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result<T>& result) {
+    return toScopedAStatus(result, getErrorCode(result));
+}
+
+template <class T1, class T2>
+::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector<T1>& values, T2* output) {
+    auto result = ::android::automotive::car_binder_lib::LargeParcelableBase::
+            parcelableVectorToStableLargeParcelable(values);
+    if (!result.ok()) {
+        return toScopedAStatus(
+                result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR);
+    }
+    auto& fd = result.value();
+    if (fd == nullptr) {
+        output->payloads = values;
+    } else {
+        // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in
+        // 'sharedMemoryFd' field.
+        output->sharedMemoryFd.set(fd->get());
+        *(fd->getR()) = INVALID_MEMORY_FD;
+    }
+    return ::ndk::ScopedAStatus::ok();
+}
+
+}  // namespace defaultvehiclehal_impl
+
 class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::vehicle::BnVehicle {
+  public:
+    explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
+
     ::ndk::ScopedAStatus getAllPropConfigs(
             ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs)
             override;
@@ -56,6 +110,14 @@
             const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>&
                     callback,
             int64_t sharedMemoryId) override;
+
+    IVehicleHardware* getHardware();
+
+  private:
+    const std::unique_ptr<IVehicleHardware> mVehicleHardware;
+    std::unordered_map<int32_t, ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
+            mConfigsByPropId;
+    std::unique_ptr<::ndk::ScopedFileDescriptor> mConfigFile;
 };
 
 }  // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 5a31643..fd9e331 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -18,7 +18,11 @@
 
 #include <DefaultVehicleHal.h>
 
+#include <LargeParcelableBase.h>
 #include <VehicleHalTypes.h>
+#include <VehicleUtils.h>
+#include <android-base/result.h>
+#include <utils/Log.h>
 
 namespace android {
 namespace hardware {
@@ -28,12 +32,41 @@
 using ::aidl::android::hardware::automotive::vehicle::GetValueRequests;
 using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback;
 using ::aidl::android::hardware::automotive::vehicle::SetValueRequests;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
 using ::aidl::android::hardware::automotive::vehicle::SubscribeOptions;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::android::automotive::car_binder_lib::LargeParcelableBase;
+using ::android::base::Result;
 using ::ndk::ScopedAStatus;
 
-ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs*) {
-    // TODO(b/200737967): implement this.
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware)
+    : mVehicleHardware(std::move(hardware)) {
+    auto configs = mVehicleHardware->getAllPropertyConfigs();
+    for (auto& config : configs) {
+        mConfigsByPropId[config.prop] = config;
+    }
+    auto result = LargeParcelableBase::parcelableVectorToStableLargeParcelable(configs);
+    if (!result.ok()) {
+        ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
+              getErrorMsg(result).c_str(), getIntErrorCode(result));
+        return;
+    }
+
+    if (result.value() != nullptr) {
+        mConfigFile = std::move(result.value());
+    }
+}
+
+ScopedAStatus DefaultVehicleHal::getAllPropConfigs(VehiclePropConfigs* output) {
+    if (mConfigFile != nullptr) {
+        output->sharedMemoryFd.set(dup(mConfigFile->get()));
+        return ScopedAStatus::ok();
+    }
+    output->payloads.reserve(mConfigsByPropId.size());
+    for (const auto& [_, config] : mConfigsByPropId) {
+        output->payloads.push_back(config);
+    }
     return ScopedAStatus::ok();
 }
 
@@ -49,9 +82,15 @@
     return ScopedAStatus::ok();
 }
 
-ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>&, VehiclePropConfigs*) {
-    // TODO(b/200737967): implement this.
-    return ScopedAStatus::ok();
+ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector<int32_t>& props,
+                                                VehiclePropConfigs* output) {
+    std::vector<VehiclePropConfig> configs;
+    for (int32_t prop : props) {
+        if (mConfigsByPropId.find(prop) != mConfigsByPropId.end()) {
+            configs.push_back(mConfigsByPropId[prop]);
+        }
+    }
+    return defaultvehiclehal_impl::vectorToStableLargeParcelable(configs, output);
 }
 
 ScopedAStatus DefaultVehicleHal::subscribe(const std::shared_ptr<IVehicleCallback>&,
@@ -72,6 +111,10 @@
     return ScopedAStatus::ok();
 }
 
+IVehicleHardware* DefaultVehicleHal::getHardware() {
+    return mVehicleHardware.get();
+}
+
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
index 7c623ea..14224a5 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/VehicleService.cpp
@@ -17,15 +17,19 @@
 #define LOG_TAG "VehicleService"
 
 #include <DefaultVehicleHal.h>
+#include <FakeVehicleHardware.h>
 
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
 #include <utils/Log.h>
 
 using ::android::hardware::automotive::vehicle::DefaultVehicleHal;
+using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware;
 
 int main(int /* argc */, char* /* argv */[]) {
-    std::shared_ptr<DefaultVehicleHal> vhal = ndk::SharedRefBase::make<DefaultVehicleHal>();
+    std::unique_ptr<FakeVehicleHardware> hardware = std::make_unique<FakeVehicleHardware>();
+    std::shared_ptr<DefaultVehicleHal> vhal =
+            ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
 
     ALOGI("Registering as service...");
     binder_exception_t err = AServiceManager_addService(vhal->asBinder().get(),
diff --git a/automotive/vehicle/aidl/impl/vhal/test/Android.bp b/automotive/vehicle/aidl/impl/vhal/test/Android.bp
new file mode 100644
index 0000000..bf16475
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/Android.bp
@@ -0,0 +1,46 @@
+/*
+ * 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "DefaultVehicleHalTest",
+    vendor: true,
+    srcs: ["*.cpp"],
+    static_libs: [
+        "DefaultVehicleHal",
+        "VehicleHalUtils",
+        "android-automotive-large-parcelable-vendor-lib",
+        "libgtest",
+        "libgmock",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "liblog",
+        "libutils",
+    ],
+    header_libs: [
+        "IVehicleHardware",
+    ],
+    defaults: [
+        "VehicleHalDefaults",
+        "android-automotive-large-parcelable-defaults",
+    ],
+    test_suites: ["device-tests"],
+}
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
new file mode 100644
index 0000000..62a7098
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+#include "DefaultVehicleHal.h"
+
+#include <IVehicleHardware.h>
+#include <LargeParcelableBase.h>
+#include <aidl/android/hardware/automotive/vehicle/IVehicle.h>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <optional>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::IVehicle;
+using ::aidl::android::hardware::automotive::vehicle::SetValueRequest;
+using ::aidl::android::hardware::automotive::vehicle::SetValueResult;
+using ::aidl::android::hardware::automotive::vehicle::StatusCode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+using ::android::automotive::car_binder_lib::LargeParcelableBase;
+using ::android::base::Result;
+
+using ::testing::Eq;
+using ::testing::WhenSortedBy;
+
+class MockVehicleHardware final : public IVehicleHardware {
+  public:
+    std::vector<VehiclePropConfig> getAllPropertyConfigs() const override {
+        return mPropertyConfigs;
+    }
+
+    StatusCode setValues(std::function<void(const std::vector<SetValueResult>&)>&&,
+                         const std::vector<SetValueRequest>&) override {
+        // TODO(b/200737967): mock this.
+        return StatusCode::OK;
+    }
+
+    StatusCode getValues(std::function<void(const std::vector<GetValueResult>&)>&&,
+                         const std::vector<GetValueRequest>&) const override {
+        // TODO(b/200737967): mock this.
+        return StatusCode::OK;
+    }
+
+    DumpResult dump(const std::vector<std::string>&) override {
+        // TODO(b/200737967): mock this.
+        return DumpResult{};
+    }
+
+    StatusCode checkHealth() override {
+        // TODO(b/200737967): mock this.
+        return StatusCode::OK;
+    }
+
+    void registerOnPropertyChangeEvent(
+            std::function<void(const std::vector<VehiclePropValue>&)>&&) override {
+        // TODO(b/200737967): mock this.
+    }
+
+    void registerOnPropertySetErrorEvent(
+            std::function<void(const std::vector<SetValueErrorEvent>&)>&&) override {
+        // TODO(b/200737967): mock this.
+    }
+
+    // Test functions.
+    void setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) {
+        mPropertyConfigs = configs;
+    }
+
+  private:
+    std::vector<VehiclePropConfig> mPropertyConfigs;
+};
+
+struct PropConfigCmp {
+    bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const {
+        return (a.prop < b.prop);
+    }
+} propConfigCmp;
+
+}  // namespace
+
+TEST(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
+    auto testConfigs = std::vector<VehiclePropConfig>({
+            VehiclePropConfig{
+                    .prop = 1,
+            },
+            VehiclePropConfig{
+                    .prop = 2,
+            },
+    });
+
+    auto hardware = std::make_unique<MockVehicleHardware>();
+    hardware->setPropertyConfigs(testConfigs);
+    auto vhal = ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+    VehiclePropConfigs output;
+    auto status = client->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(status.isOk());
+    ASSERT_THAT(output.payloads, WhenSortedBy(propConfigCmp, Eq(testConfigs)));
+}
+
+TEST(DefaultVehicleHalTest, testGetAllPropConfigsLarge) {
+    std::vector<VehiclePropConfig> testConfigs;
+    // 10000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
+    for (size_t i = 0; i < 10000; i++) {
+        testConfigs.push_back(VehiclePropConfig{
+                .prop = static_cast<int32_t>(i),
+        });
+    }
+
+    auto hardware = std::make_unique<MockVehicleHardware>();
+    hardware->setPropertyConfigs(testConfigs);
+    auto vhal = ::ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware));
+    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+    VehiclePropConfigs output;
+    auto status = client->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(output.payloads.empty());
+    Result<std::optional<std::vector<VehiclePropConfig>>> result =
+            LargeParcelableBase::stableLargeParcelableToParcelableVector<VehiclePropConfig>(
+                    output.sharedMemoryFd);
+    ASSERT_TRUE(result.ok());
+    ASSERT_TRUE(result.value().has_value());
+    ASSERT_EQ(result.value().value(), testConfigs);
+}
+
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android