Merge "Implement getPropConfigs in Default VHAL."

This commit is contained in:
TreeHugger Robot
2021-11-16 23:08:29 +00:00
committed by Android (Google) Code Review
10 changed files with 409 additions and 52 deletions

View File

@@ -20,6 +20,9 @@
},
{
"name": "FakeUserHalTest"
},
{
"name": "DefaultVehicleHalTest"
}
]
}

View File

@@ -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",

View File

@@ -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 <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) {

View File

@@ -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 @@ inline size_t getVehiclePropValueSize(
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

View File

@@ -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",

View File

@@ -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 @@ 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<IVehicleHardware> mVehicleHardware;
std::unordered_map<int32_t, ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
mConfigsByPropId;
std::unique_ptr<::ndk::ScopedFileDescriptor> mConfigFile;
};
} // namespace vehicle

View File

@@ -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 @@ 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<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 @@ ScopedAStatus DefaultVehicleHal::setValues(const std::shared_ptr<IVehicleCallbac
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 @@ ScopedAStatus DefaultVehicleHal::returnSharedMemory(const std::shared_ptr<IVehic
return ScopedAStatus::ok();
}
IVehicleHardware* DefaultVehicleHal::getHardware() {
return mVehicleHardware.get();
}
} // namespace vehicle
} // namespace automotive
} // namespace hardware

View File

@@ -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(),

View File

@@ -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"],
}

View File

@@ -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