diff --git a/automotive/vehicle/TEST_MAPPING b/automotive/vehicle/TEST_MAPPING index 3696351109..ff6f3be52b 100644 --- a/automotive/vehicle/TEST_MAPPING +++ b/automotive/vehicle/TEST_MAPPING @@ -20,6 +20,9 @@ }, { "name": "FakeUserHalTest" + }, + { + "name": "DefaultVehicleHalTest" } ] } diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp b/automotive/vehicle/aidl/impl/fake_impl/hardware/Android.bp index dfc2efc5f2..dcd9208cab 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 @@ cc_library { 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 104147a543..5b2003ec19 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 @@ using ::android::base::Result; const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/automotive/vhaloverride/"; const char* OVERRIDE_PROPERTY = "persist.vendor.vhal_init_value_override"; -template -StatusCode getErrorCode(const Result& result) { - if (result.ok()) { - return StatusCode::OK; - } - return static_cast(result.error().code()); -} - -template -int getIntErrorCode(const Result& result) { - return toInt(getErrorCode(result)); -} - -template -std::string getErrorMsg(const Result& 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 95e58c6118..dfc7cbf748 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 + +#include #include namespace android { @@ -183,6 +185,29 @@ inline size_t getVehiclePropValueSize( return size; } +template +::aidl::android::hardware::automotive::vehicle::StatusCode getErrorCode( + const ::android::base::Result& 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 +int getIntErrorCode(const ::android::base::Result& result) { + return toInt(getErrorCode(result)); +} + +template +std::string getErrorMsg(const ::android::base::Result& 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 0704107bfc..ef1d0f18ef 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 49c501e4b2..43bdca2314 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 +#include +#include #include +#include + +#include +#include +#include namespace android { namespace hardware { namespace automotive { namespace vehicle { +// private namespace +namespace defaultvehiclehal_impl { + +constexpr int INVALID_MEMORY_FD = -1; + +template +::ndk::ScopedAStatus toScopedAStatus( + const ::android::base::Result& 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 +::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result& result) { + return toScopedAStatus(result, getErrorCode(result)); +} + +template +::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector& 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 hardware); + ::ndk::ScopedAStatus getAllPropConfigs( ::aidl::android::hardware::automotive::vehicle::VehiclePropConfigs* returnConfigs) override; @@ -56,6 +110,14 @@ class DefaultVehicleHal final : public ::aidl::android::hardware::automotive::ve const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback>& callback, int64_t sharedMemoryId) override; + + IVehicleHardware* getHardware(); + + private: + const std::unique_ptr mVehicleHardware; + std::unordered_map + 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 5a31643ba6..fd9e331c0d 100644 --- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp +++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp @@ -18,7 +18,11 @@ #include +#include #include +#include +#include +#include namespace android { namespace hardware { @@ -28,12 +32,41 @@ namespace vehicle { 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 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 @@ ScopedAStatus DefaultVehicleHal::setValues(const std::shared_ptr&, VehiclePropConfigs*) { - // TODO(b/200737967): implement this. - return ScopedAStatus::ok(); +ScopedAStatus DefaultVehicleHal::getPropConfigs(const std::vector& props, + VehiclePropConfigs* output) { + std::vector 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&, @@ -72,6 +111,10 @@ ScopedAStatus DefaultVehicleHal::returnSharedMemory(const std::shared_ptr +#include #include #include #include using ::android::hardware::automotive::vehicle::DefaultVehicleHal; +using ::android::hardware::automotive::vehicle::fake::FakeVehicleHardware; int main(int /* argc */, char* /* argv */[]) { - std::shared_ptr vhal = ndk::SharedRefBase::make(); + std::unique_ptr hardware = std::make_unique(); + std::shared_ptr vhal = + ::ndk::SharedRefBase::make(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 0000000000..bf16475ab0 --- /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 0000000000..62a7098585 --- /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 +#include +#include + +#include +#include + +#include +#include +#include + +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 getAllPropertyConfigs() const override { + return mPropertyConfigs; + } + + StatusCode setValues(std::function&)>&&, + const std::vector&) override { + // TODO(b/200737967): mock this. + return StatusCode::OK; + } + + StatusCode getValues(std::function&)>&&, + const std::vector&) const override { + // TODO(b/200737967): mock this. + return StatusCode::OK; + } + + DumpResult dump(const std::vector&) override { + // TODO(b/200737967): mock this. + return DumpResult{}; + } + + StatusCode checkHealth() override { + // TODO(b/200737967): mock this. + return StatusCode::OK; + } + + void registerOnPropertyChangeEvent( + std::function&)>&&) override { + // TODO(b/200737967): mock this. + } + + void registerOnPropertySetErrorEvent( + std::function&)>&&) override { + // TODO(b/200737967): mock this. + } + + // Test functions. + void setPropertyConfigs(const std::vector& configs) { + mPropertyConfigs = configs; + } + + private: + std::vector 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{ + .prop = 1, + }, + VehiclePropConfig{ + .prop = 2, + }, + }); + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + auto vhal = ::ndk::SharedRefBase::make(std::move(hardware)); + std::shared_ptr 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 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(i), + }); + } + + auto hardware = std::make_unique(); + hardware->setPropertyConfigs(testConfigs); + auto vhal = ::ndk::SharedRefBase::make(std::move(hardware)); + std::shared_ptr client = IVehicle::fromBinder(vhal->asBinder()); + + VehiclePropConfigs output; + auto status = client->getAllPropConfigs(&output); + + ASSERT_TRUE(status.isOk()); + ASSERT_TRUE(output.payloads.empty()); + Result>> result = + LargeParcelableBase::stableLargeParcelableToParcelableVector( + 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