Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e7f7804 authored by Yu Shan's avatar Yu Shan
Browse files

Add fake vehicle hardware implementation.

Add a fake vehicle hardware implementation that uses default config.
This would be used in emulator.

Test: atest FakeVehicleHardwareTest
Bug: 201830716
Change-Id: If93bdebb5c82b947a327688db80978fc4cb46d3c
parent 74bf81da
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
/*
 * 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_library {
    name: "FakeVehicleHardware",
    vendor: true,
    srcs: ["src/*.cpp"],
    local_include_dirs: ["include"],
    export_include_dirs: ["include"],
    defaults: ["VehicleHalDefaults"],
    header_libs: [
        "IVehicleHardware",
        "VehicleHalDefaultConfig",
    ],
    export_header_lib_headers: ["IVehicleHardware"],
    static_libs: ["VehicleHalUtils"],
    export_static_lib_headers: ["VehicleHalUtils"],
}
+102 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#ifndef android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
#define android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_

#include <DefaultConfig.h>
#include <IVehicleHardware.h>
#include <VehicleHalTypes.h>
#include <VehiclePropertyStore.h>
#include <android-base/thread_annotations.h>

#include <map>
#include <memory>
#include <mutex>
#include <vector>

namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {

class FakeVehicleHardware final : public IVehicleHardware {
  public:
    using SetValuesCallback = std::function<void(
            const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>&)>;
    using GetValuesCallback = std::function<void(
            const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>&)>;
    using OnPropertyChangeCallback = std::function<void(
            const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>&)>;
    using OnPropertySetErrorCallback = std::function<void(const std::vector<SetValueErrorEvent>&)>;

    FakeVehicleHardware();

    explicit FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool);

    // Get all the property configs.
    std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>
    getAllPropertyConfigs() const override;

    // Set property values asynchronously. Server could return before the property set requests
    // are sent to vehicle bus or before property set confirmation is received. The callback is
    // safe to be called after the function returns and is safe to be called in a different thread.
    ::aidl::android::hardware::automotive::vehicle::StatusCode setValues(
            SetValuesCallback&& callback,
            const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>&
                    requests) override;

    // Get property values asynchronously. Server could return before the property values are ready.
    // The callback is safe to be called after the function returns and is safe to be called in a
    // different thread.
    ::aidl::android::hardware::automotive::vehicle::StatusCode getValues(
            GetValuesCallback&& callback,
            const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>&
                    requests) const override;

    // Dump debug information in the server.
    DumpResult dump(const std::vector<std::string>& options) override;

    // Check whether the system is healthy, return {@code StatusCode::OK} for healthy.
    ::aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override;

    // Register a callback that would be called when there is a property change event from vehicle.
    void registerOnPropertyChangeEvent(OnPropertyChangeCallback&& callback) override;

    // Register a callback that would be called when there is a property set error event from
    // vehicle.
    void registerOnPropertySetErrorEvent(OnPropertySetErrorCallback&& callback) override;

  private:
    void storePropInitialValue(const defaultconfig::ConfigDeclaration& config);
    void init(std::shared_ptr<VehiclePropValuePool> valuePool);
    void onValueChangeCallback(
            const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);

    std::unique_ptr<VehiclePropertyStore> mServerSidePropStore;
    // mValuePool is also used in mServerSidePropStore.
    std::shared_ptr<VehiclePropValuePool> mValuePool;
    std::mutex mCallbackLock;
    OnPropertyChangeCallback mOnPropertyChangeCallback GUARDED_BY(mCallbackLock);
    OnPropertySetErrorCallback mOnPropertySetErrorCallback GUARDED_BY(mCallbackLock);
};

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
}  // namespace android

#endif  // android_hardware_automotive_vehicle_aidl_impl_fake_impl_hardware_include_FakeVehicleHardware_H_
+154 −0
Original line number Diff line number Diff line
/*
 * 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 "FakeVehicleHardware.h"

#include <DefaultConfig.h>
#include <VehicleHalTypes.h>
#include <VehicleUtils.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>

#include <vector>

namespace android {
namespace hardware {
namespace automotive {
namespace vehicle {

using ::aidl::android::hardware::automotive::vehicle::GetValueRequest;
using ::aidl::android::hardware::automotive::vehicle::GetValueResult;
using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
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::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;

void FakeVehicleHardware::storePropInitialValue(const defaultconfig::ConfigDeclaration& config) {
    const VehiclePropConfig& vehiclePropConfig = config.config;
    int propId = vehiclePropConfig.prop;

    // A global property will have only a single area
    bool globalProp = isGlobalProp(propId);
    size_t numAreas = globalProp ? 1 : vehiclePropConfig.areaConfigs.size();

    for (size_t i = 0; i < numAreas; i++) {
        int32_t curArea = globalProp ? 0 : vehiclePropConfig.areaConfigs[i].areaId;

        // Create a separate instance for each individual zone
        VehiclePropValue prop = {
                .areaId = curArea,
                .prop = propId,
                .timestamp = elapsedRealtimeNano(),
        };

        if (config.initialAreaValues.empty()) {
            if (config.initialValue == RawPropValues{}) {
                // Skip empty initial values.
                continue;
            }
            prop.value = config.initialValue;
        } else if (auto valueForAreaIt = config.initialAreaValues.find(curArea);
                   valueForAreaIt != config.initialAreaValues.end()) {
            prop.value = valueForAreaIt->second;
        } else {
            ALOGW("failed to get default value for prop 0x%x area 0x%x", propId, curArea);
            continue;
        }

        auto result =
                mServerSidePropStore->writeValue(mValuePool->obtain(prop), /*updateStatus=*/true);
        if (!result.ok()) {
            ALOGE("failed to write default config value, error: %s",
                  result.error().message().c_str());
        }
    }
}

FakeVehicleHardware::FakeVehicleHardware() {
    mValuePool = std::make_shared<VehiclePropValuePool>();
    init(mValuePool);
}

FakeVehicleHardware::FakeVehicleHardware(std::unique_ptr<VehiclePropValuePool> valuePool)
    : mValuePool(std::move(valuePool)) {
    init(mValuePool);
}

void FakeVehicleHardware::init(std::shared_ptr<VehiclePropValuePool> valuePool) {
    mServerSidePropStore.reset(new VehiclePropertyStore(valuePool));
    for (auto& it : defaultconfig::getDefaultConfigs()) {
        VehiclePropConfig cfg = it.config;
        mServerSidePropStore->registerProperty(cfg);
        storePropInitialValue(it);
    }

    mServerSidePropStore->setOnValueChangeCallback(
            [this](const VehiclePropValue& value) { return onValueChangeCallback(value); });
}

std::vector<VehiclePropConfig> FakeVehicleHardware::getAllPropertyConfigs() const {
    return mServerSidePropStore->getAllConfigs();
}

StatusCode FakeVehicleHardware::setValues(FakeVehicleHardware::SetValuesCallback&&,
                                          const std::vector<SetValueRequest>&) {
    // TODO(b/201830716): Implement this.
    return StatusCode::OK;
}

StatusCode FakeVehicleHardware::getValues(FakeVehicleHardware::GetValuesCallback&&,
                                          const std::vector<GetValueRequest>&) const {
    // TODO(b/201830716): Implement this.
    return StatusCode::OK;
}

DumpResult FakeVehicleHardware::dump(const std::vector<std::string>&) {
    DumpResult result;
    // TODO(b/201830716): Implement this.
    return result;
}

StatusCode FakeVehicleHardware::checkHealth() {
    // TODO(b/201830716): Implement this.
    return StatusCode::OK;
}

void FakeVehicleHardware::registerOnPropertyChangeEvent(OnPropertyChangeCallback&& callback) {
    std::lock_guard<std::mutex> lockGuard(mCallbackLock);
    mOnPropertyChangeCallback = std::move(callback);
}

void FakeVehicleHardware::registerOnPropertySetErrorEvent(OnPropertySetErrorCallback&& callback) {
    std::lock_guard<std::mutex> lockGuard(mCallbackLock);
    mOnPropertySetErrorCallback = std::move(callback);
}

void FakeVehicleHardware::onValueChangeCallback(const VehiclePropValue& value) {
    std::lock_guard<std::mutex> lockGuard(mCallbackLock);
    if (mOnPropertyChangeCallback != nullptr) {
        std::vector<VehiclePropValue> updatedValues;
        updatedValues.push_back(value);
        mOnPropertyChangeCallback(std::move(updatedValues));
    }
}

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
}  // namespace android
+37 −0
Original line number Diff line number Diff line
/*
 * 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: "FakeVehicleHardwareTest",
    vendor: true,
    srcs: ["*.cpp"],
    header_libs: [
        "IVehicleHardware",
        "VehicleHalDefaultConfig",
    ],
    static_libs: [
        "VehicleHalUtils",
        "FakeVehicleHardware",
        "libgtest",
        "libgmock",
    ],
    defaults: ["VehicleHalDefaults"],
    test_suites: ["device-tests"],
}
+165 −0
Original line number Diff line number Diff line
/*
 * 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 <DefaultConfig.h>
#include <FakeVehicleHardware.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <utils/SystemClock.h>

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::RawPropValues;
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::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::testing::ContainerEq;
using ::testing::Eq;
using ::testing::WhenSortedBy;

}  // namespace

class FakeVehicleHardwareTest : public ::testing::Test {
  protected:
    void SetUp() override {}

    FakeVehicleHardware* getHardware() { return &mHardware; }

    StatusCode setValues(const std::vector<SetValueRequest>& requests) {
        return getHardware()->setValues(
                [this](const std::vector<SetValueResult> results) { return onSetValues(results); },
                requests);
    }

    StatusCode getValues(const std::vector<GetValueRequest>& requests) {
        return getHardware()->getValues(
                [this](const std::vector<GetValueResult> results) { return onGetValues(results); },
                requests);
    }

    void onSetValues(const std::vector<SetValueResult> results) {
        for (auto& result : results) {
            mSetValueResults.push_back(result);
        }
    }

    const std::vector<SetValueResult>& getSetValueResults() { return mSetValueResults; }

    void onGetValues(const std::vector<GetValueResult> results) {
        for (auto& result : results) {
            mGetValueResults.push_back(result);
        }
    }

    const std::vector<GetValueResult>& getGetValueResults() { return mGetValueResults; }

    void onPropertyChangeEvent(const std::vector<VehiclePropValue>& values) {
        for (auto& value : values) {
            mChangedProperties.push_back(value);
        }
    }

    const std::vector<VehiclePropValue>& getChangedProperties() { return mChangedProperties; }

    static void addSetValueRequest(std::vector<SetValueRequest>& requests,
                                   std::vector<SetValueResult>& expectedResults, int64_t requestId,
                                   const VehiclePropValue& value, StatusCode expectedStatus) {
        SetValueRequest request;
        request.requestId = requestId;
        request.value = value;
        request.value.timestamp = elapsedRealtimeNano();
        requests.push_back(std::move(request));

        SetValueResult result;
        result.requestId = requestId;
        result.status = expectedStatus;
        expectedResults.push_back(std::move(result));
    }

    static void addGetValueRequest(std::vector<GetValueRequest>& requests,
                                   std::vector<GetValueResult>& expectedResults, int64_t requestId,
                                   const VehiclePropValue& value, StatusCode expectedStatus) {
        GetValueRequest request;
        request.requestId = requestId;
        request.prop.prop = value.prop;
        request.prop.areaId = value.areaId;
        requests.push_back(std::move(request));

        GetValueResult result;
        result.requestId = requestId;
        result.status = expectedStatus;
        if (expectedStatus == StatusCode::OK) {
            result.prop = value;
        }
        expectedResults.push_back(std::move(result));
    }

    std::vector<VehiclePropValue> getTestPropValues() {
        VehiclePropValue fuelCapacity = {
                .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
                .value = {.floatValues = {1.0}},
        };

        VehiclePropValue leftTirePressure = {
                .prop = toInt(VehicleProperty::TIRE_PRESSURE),
                .value = {.floatValues = {170.0}},
                .areaId = WHEEL_FRONT_LEFT,
        };

        VehiclePropValue rightTirePressure = {
                .prop = toInt(VehicleProperty::TIRE_PRESSURE),
                .value = {.floatValues = {180.0}},
                .areaId = WHEEL_FRONT_RIGHT,
        };

        return {fuelCapacity, leftTirePressure, rightTirePressure};
    }

    struct PropValueCmp {
        bool operator()(const VehiclePropValue& a, const VehiclePropValue& b) const {
            return (a.prop < b.prop) || ((a.prop == b.prop) && (a.value < b.value)) ||
                   ((a.prop == b.prop) && (a.value == b.value) && (a.areaId < b.areaId));
        }
    } mPropValueCmp;

  private:
    FakeVehicleHardware mHardware;
    std::vector<SetValueResult> mSetValueResults;
    std::vector<GetValueResult> mGetValueResults;
    std::vector<VehiclePropValue> mChangedProperties;
};

TEST_F(FakeVehicleHardwareTest, testGetAllPropertyConfigs) {
    std::vector<VehiclePropConfig> configs = getHardware()->getAllPropertyConfigs();

    ASSERT_EQ(configs.size(), defaultconfig::getDefaultConfigs().size());
}

}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
}  // namespace android
Loading