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

Commit ccc1d2e7 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic 'vhal-def-refactor' into oc-dev

* changes:
  Extract logic of storing values to separate class
  Fix an issue where Vehicle HAL would crash when trying to update a continuous property without an initial floating-point value
  Refactor default values in VHAL
parents 163dc91b 33676528
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ LOCAL_SRC_FILES := \
    common/src/SubscriptionManager.cpp \
    common/src/VehicleHalManager.cpp \
    common/src/VehicleObjectPool.cpp \
    common/src/VehiclePropertyStore.cpp \
    common/src/VehicleUtils.cpp \

LOCAL_C_INCLUDES := \
@@ -72,9 +73,10 @@ include $(CLEAR_VARS)

LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
LOCAL_SRC_FILES:= \
    impl/vhal_v2_0/DefaultVehicleHal.cpp \
    impl/vhal_v2_0/EmulatedVehicleHal.cpp \
    impl/vhal_v2_0/VehicleEmulator.cpp \
    impl/vhal_v2_0/PipeComm.cpp \
    impl/vhal_v2_0/SocketComm.cpp
    impl/vhal_v2_0/SocketComm.cpp \

LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/impl/vhal_v2_0
+4 −2
Original line number Diff line number Diff line
@@ -21,14 +21,16 @@
#include <iostream>

#include <vhal_v2_0/VehicleHalManager.h>
#include <vhal_v2_0/DefaultVehicleHal.h>
#include <vhal_v2_0/EmulatedVehicleHal.h>

using namespace android;
using namespace android::hardware;
using namespace android::hardware::automotive::vehicle::V2_0;

int main(int /* argc */, char* /* argv */ []) {
    auto hal = std::make_unique<impl::DefaultVehicleHal>();
    auto store = std::make_unique<VehiclePropertyStore>();
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get());
    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
    auto service = std::make_unique<VehicleHalManager>(hal.get());

    configureRpcThreadpool(1, true /* callerWillJoin */);
+104 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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_V2_0_impl_PropertyDb_H_
#define android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_

#include <cstdint>
#include <unordered_map>
#include <memory>
#include <mutex>

#include <android/hardware/automotive/vehicle/2.0/IVehicle.h>

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

/**
 * Encapsulates work related to storing and accessing configuration, storing and modifying
 * vehicle property values.
 *
 * VehiclePropertyValues stored in a sorted map thus it makes easier to get range of values, e.g.
 * to get value for all areas for particular property.
 *
 * This class is thread-safe, however it uses blocking synchronization across all methods.
 */
class VehiclePropertyStore {
public:
    /* Function that used to calculate unique token for given VehiclePropValue */
    using TokenFunction = std::function<int64_t(const VehiclePropValue& value)>;

private:
    struct RecordConfig {
        VehiclePropConfig propConfig;
        TokenFunction tokenFunction;
    };

    struct RecordId {
        int32_t prop;
        int32_t area;
        int64_t token;

        bool operator==(const RecordId& other) const;
        bool operator<(const RecordId& other) const;
    };

    using PropertyMap = std::map<RecordId, VehiclePropValue>;
    using PropertyMapRange = std::pair<PropertyMap::const_iterator, PropertyMap::const_iterator>;

public:
    void registerProperty(const VehiclePropConfig& config, TokenFunction tokenFunc = nullptr);

    /* Stores provided value. Returns true if value was written returns false if config for
     * example wasn't registered. */
    bool writeValue(const VehiclePropValue& propValue);

    void removeValue(const VehiclePropValue& propValue);
    void removeValuesForProperty(int32_t propId);

    std::vector<VehiclePropValue> readAllValues() const;
    std::vector<VehiclePropValue> readValuesForProperty(int32_t propId) const;
    std::unique_ptr<VehiclePropValue> readValueOrNull(const VehiclePropValue& request) const;
    std::unique_ptr<VehiclePropValue> readValueOrNull(int32_t prop, int32_t area = 0,
                                                      int64_t token = 0) const;

    std::vector<VehiclePropConfig> getAllConfigs() const;
    const VehiclePropConfig* getConfigOrNull(int32_t propId) const;
    const VehiclePropConfig* getConfigOrDie(int32_t propId) const;

private:
    RecordId getRecordIdLocked(const VehiclePropValue& valuePrototype) const;
    const VehiclePropValue* getValueOrNullLocked(const RecordId& recId) const;
    PropertyMapRange findRangeLocked(int32_t propId) const;

private:
    using MuxGuard = std::lock_guard<std::mutex>;
    mutable std::mutex mLock;
    std::unordered_map<int32_t /* VehicleProperty */, RecordConfig> mConfigs;

    PropertyMap mPropertyValues;  // Sorted map of RecordId : VehiclePropValue.
};

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

#endif //android_hardware_automotive_vehicle_V2_0_impl_PropertyDb_H_
+172 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */
#define LOG_TAG "VehiclePropertyStore"
#include <android/log.h>

#include <common/include/vhal_v2_0/VehicleUtils.h>
#include "VehiclePropertyStore.h"

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

bool VehiclePropertyStore::RecordId::operator==(const VehiclePropertyStore::RecordId& other) const {
    return prop == other.prop && area == other.area && token == other.token;
}

bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const  {
    return prop < other.prop
           || (prop == other.prop && area < other.area)
           || (prop == other.prop && area == other.area && token < other.token);
}

void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
                                            VehiclePropertyStore::TokenFunction tokenFunc) {
    MuxGuard g(mLock);
    mConfigs.insert({ config.prop, RecordConfig { config, tokenFunc } });
}

bool VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
    MuxGuard g(mLock);
    if (!mConfigs.count(propValue.prop)) return false;

    RecordId recId = getRecordIdLocked(propValue);
    VehiclePropValue* valueToUpdate = const_cast<VehiclePropValue*>(getValueOrNullLocked(recId));
    if (valueToUpdate == nullptr) {
        mPropertyValues.insert({ recId, propValue });
    } else {
        valueToUpdate->timestamp = propValue.timestamp;
        valueToUpdate->value = propValue.value;
    }
    return true;
}

void VehiclePropertyStore::removeValue(const VehiclePropValue& propValue) {
    MuxGuard g(mLock);
    RecordId recId = getRecordIdLocked(propValue);
    auto it = mPropertyValues.find(recId);
    if (it != mPropertyValues.end()) {
        mPropertyValues.erase(it);
    }
}

void VehiclePropertyStore::removeValuesForProperty(int32_t propId) {
    MuxGuard g(mLock);
    auto range = findRangeLocked(propId);
    mPropertyValues.erase(range.first, range.second);
}

std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
    MuxGuard g(mLock);
    std::vector<VehiclePropValue> allValues;
    allValues.reserve(mPropertyValues.size());
    for (auto&& it : mPropertyValues) {
        allValues.push_back(it.second);
    }
    return allValues;
}

std::vector<VehiclePropValue> VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
    std::vector<VehiclePropValue> values;
    MuxGuard g(mLock);
    auto range = findRangeLocked(propId);
    for (auto it = range.first; it != range.second; ++it) {
        values.push_back(it->second);
    }

    return values;
}

std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
        const VehiclePropValue& request) const {
    MuxGuard g(mLock);
    RecordId recId = getRecordIdLocked(request);
    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
}

std::unique_ptr<VehiclePropValue> VehiclePropertyStore::readValueOrNull(
        int32_t prop, int32_t area, int64_t token) const {
    RecordId recId = {prop, isGlobalProp(prop) ? 0 : area, token };
    MuxGuard g(mLock);
    const VehiclePropValue* internalValue = getValueOrNullLocked(recId);
    return internalValue ? std::make_unique<VehiclePropValue>(*internalValue) : nullptr;
}


std::vector<VehiclePropConfig> VehiclePropertyStore::getAllConfigs() const {
    MuxGuard g(mLock);
    std::vector<VehiclePropConfig> configs;
    configs.reserve(mConfigs.size());
    for (auto&& recordConfigIt: mConfigs) {
        configs.push_back(recordConfigIt.second.propConfig);
    }
    return configs;
}

const VehiclePropConfig* VehiclePropertyStore::getConfigOrNull(int32_t propId) const {
    MuxGuard g(mLock);
    auto recordConfigIt = mConfigs.find(propId);
    return recordConfigIt != mConfigs.end() ? &recordConfigIt->second.propConfig : nullptr;
}

const VehiclePropConfig* VehiclePropertyStore::getConfigOrDie(int32_t propId) const {
    auto cfg = getConfigOrNull(propId);
    if (!cfg) {
        ALOGW("%s: config not found for property: 0x%x", __func__, propId);
        abort();
    }
    return cfg;
}

VehiclePropertyStore::RecordId VehiclePropertyStore::getRecordIdLocked(
        const VehiclePropValue& valuePrototype) const {
    RecordId recId = {
        .prop = valuePrototype.prop,
        .area = isGlobalProp(valuePrototype.prop) ? 0 : valuePrototype.areaId,
        .token = 0
    };

    auto it = mConfigs.find(recId.prop);
    if (it == mConfigs.end()) return {};

    if (it->second.tokenFunction != nullptr) {
        recId.token = it->second.tokenFunction(valuePrototype);
    }
    return recId;
}

const VehiclePropValue* VehiclePropertyStore::getValueOrNullLocked(
        const VehiclePropertyStore::RecordId& recId) const  {
    auto it = mPropertyValues.find(recId);
    return it == mPropertyValues.end() ? nullptr : &it->second;
}

VehiclePropertyStore::PropertyMapRange VehiclePropertyStore::findRangeLocked(int32_t propId) const {
    // Based on the fact that mPropertyValues is a sorted map by RecordId.
    auto beginIt = mPropertyValues.lower_bound( RecordId { propId, INT32_MIN, 0 });
    auto endIt = mPropertyValues.lower_bound( RecordId { propId + 1, INT32_MIN, 0 });

    return  PropertyMapRange { beginIt, endIt };
}

}  // namespace V2_0
}  // namespace vehicle
}  // namespace automotive
}  // namespace hardware
}  // namespace android
+187 −106
Original line number Diff line number Diff line
@@ -33,38 +33,64 @@ const int32_t kHvacPowerProperties[] = {
    toInt(VehicleProperty::HVAC_FAN_DIRECTION),
};

const VehiclePropConfig kVehicleProperties[] = {
struct ConfigDeclaration {
    VehiclePropConfig config;

    /* This value will be used as an initial value for the property. If this field is specified for
     * property that supports multiple areas then it will be used for all areas unless particular
     * area is overridden in initialAreaValue field. */
    VehiclePropValue::RawValue initialValue;
    /* Use initialAreaValues if it is necessary to specify different values per each area. */
    std::map<int32_t, VehiclePropValue::RawValue> initialAreaValues;
};

const ConfigDeclaration kVehicleProperties[] {
    {
        .config = {
            .prop = toInt(VehicleProperty::INFO_MAKE),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::STATIC,
        },

        .initialValue = { .stringValue = "Toy Vehicle" }
    },
    {
        .config = {
            .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .floatValues = {0.0f} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::CURRENT_GEAR),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = { toInt(VehicleGear::GEAR_PARK) } }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::PARKING_BRAKE_ON),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = {1} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::FUEL_LEVEL_LOW),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = {0} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_POWER_ON),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -73,8 +99,11 @@ const VehiclePropConfig kVehicleProperties[] = {
            // kHvacPowerProperties.
            .configString = "0x12400500,0x12400501"  // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
        },
        .initialValue = { .int32Values = {1} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_DEFROSTER),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -82,29 +111,41 @@ const VehiclePropConfig kVehicleProperties[] = {
            VehicleAreaWindow::FRONT_WINDSHIELD
            | VehicleAreaWindow::REAR_WINDSHIELD
        },
        .initialValue = { .int32Values = {0} }  // Will be used for all areas.
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
            .supportedAreas = toInt(VehicleAreaZone::ROW_1)
        },
        .initialValue = { .int32Values = {1} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_AC_ON),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
            .supportedAreas = toInt(VehicleAreaZone::ROW_1)
        },
        .initialValue = { .int32Values = {1} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_AUTO_ON),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
            .supportedAreas = toInt(VehicleAreaZone::ROW_1)
        },
        .initialValue = { .int32Values = {1} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -117,15 +158,21 @@ const VehiclePropConfig kVehicleProperties[] = {
                }
            }
        },
        .initialValue = { .int32Values = {3} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
            .supportedAreas = toInt(VehicleAreaZone::ROW_1),
        },
        .initialValue = { .int32Values = { toInt(VehicleHvacFanDirection::FACE) } }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -145,8 +192,19 @@ const VehiclePropConfig kVehicleProperties[] = {
                }
            }
        },
        .initialAreaValues = {
            {
                toInt(VehicleAreaZone::ROW_1_LEFT),
                { .floatValues = {16} }
            }, {
                toInt(VehicleAreaZone::ROW_1_RIGHT),
                { .floatValues = {20} }
            }
        }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::ENV_OUTSIDE_TEMPERATURE),
            .access = VehiclePropertyAccess::READ,
            // TODO(bryaneyler): Support ON_CHANGE as well.
@@ -154,32 +212,47 @@ const VehiclePropConfig kVehicleProperties[] = {
            .minSampleRate = 1.0f,
            .maxSampleRate = 2.0f,
        },
        .initialValue = { .floatValues = {25.0f} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::NIGHT_MODE),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = {0} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::DRIVING_STATUS),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = { toInt(VehicleDrivingStatus::UNRESTRICTED) } }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::GEAR_SELECTION),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = { toInt(VehicleGear::GEAR_PARK) } }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::STATIC,
        },
        .initialValue = { .floatValues = { 123000.0f } }  // In Milliliters
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
            .access = VehiclePropertyAccess::READ_WRITE,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -190,19 +263,27 @@ const VehiclePropConfig kVehicleProperties[] = {
                }
            }
        },
        .initialValue = { .int32Values = {7} }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::IGNITION_STATE),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
        },
        .initialValue = { .int32Values = { toInt(VehicleIgnitionState::ON) } }
    },

    {
        .config = {
            .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
            .access = VehiclePropertyAccess::READ,
            .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
            .minSampleRate = 0.1, // 0.1 Hz, every 10 seconds
            .maxSampleRate = 10,  // 10 Hz, every 100 ms
        },
        .initialValue = { .floatValues = {101.0f} }
    }
};

Loading