Implement getPropConfigs in Default VHAL.
Test: atest DefaultVehicleHalTest
Bug: 200737967
Change-Id: Id0152cb2dbf489f5d709845108b87961f6d9a019
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