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

Commit 4a23901e authored by Yu Shan's avatar Yu Shan
Browse files

Support vendor override in default VHAL.

Move vendor override property logic from emulated VHAL to
default VHAL. If system property
"persist.vendor.vhal_init_value_override" is set, then we would
try to parse JSON files in "/vendor/etc/vhaloverride/" and use the
values there to override the default initial values.

Test: unit test
Bug: 193831021
Change-Id: I6823aab3de284d5b1d96186bc9f1325d868fd8d6
parent 656882ac
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -144,7 +144,6 @@ cc_library_static {
    ],
    whole_static_libs: [
        "android.hardware.automotive.vehicle@2.0-server-common-lib",
        "android.hardware.automotive.vehicle@2.0-user-hal-helper-lib",
    ],
    static_libs: [
        "android.hardware.automotive.vehicle@2.0-libproto-native",
@@ -213,7 +212,10 @@ cc_test {
        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
        "android.hardware.automotive.vehicle@2.0-libproto-native",
    ],
    data: [":vhal_test_json"],
    data: [
        ":vhal_test_override_json",
        ":vhal_test_json",
    ],
    test_suites: ["general-tests"],
}

+1 −3
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@

#include <iostream>

#include <EmulatedUserHal.h>
#include <EmulatedVehicleConnector.h>
#include <EmulatedVehicleHal.h>
#include <vhal_v2_0/VehicleHalManager.h>
@@ -32,8 +31,7 @@ using namespace android::hardware::automotive::vehicle::V2_0;
int main(int /* argc */, char* /* argv */ []) {
    auto store = std::make_unique<VehiclePropertyStore>();
    auto connector = std::make_unique<impl::EmulatedVehicleConnector>();
    auto userHal = connector->getEmulatedUserHal();
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get(), userHal);
    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
    auto emulator = connector->getEmulator();
    auto service = std::make_unique<VehicleHalManager>(hal.get());
    connector->setValuePool(hal->getValuePool());
+55 −13
Original line number Diff line number Diff line
@@ -17,10 +17,13 @@

#include <android-base/chrono_utils.h>
#include <assert.h>
#include <stdio.h>
#include <utils/Log.h>
#include <utils/SystemClock.h>
#include <vhal_v2_0/RecurrentTimer.h>
#include <unordered_set>

#include "PropertyUtils.h"
#include "VehicleUtils.h"

#include "DefaultVehicleHal.h"
@@ -52,8 +55,30 @@ const VehicleAreaConfig* getAreaConfig(const VehiclePropValue& propValue,
    }
    return nullptr;
}

VehicleHal::VehiclePropValuePtr addTimestamp(VehicleHal::VehiclePropValuePtr v) {
    if (v.get()) {
        v->timestamp = elapsedRealtimeNano();
    }
    return v;
}

bool isDebugProperty(int propId) {
    return (propId == kGenerateFakeDataControllingProperty ||
            propId == kSetIntPropertyFromVehicleForTest ||
            propId == kSetFloatPropertyFromVehicleForTest ||
            propId == kSetBooleanPropertyFromVehicleForTest);
}
}  // namespace

VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
    v->areaId = 0;
    v->status = VehiclePropertyStatus::AVAILABLE;
    return v;
}

DefaultVehicleHal::DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
    : mPropStore(propStore), mRecurrentTimer(getTimerAction()), mVehicleClient(client) {
    initStaticConfig();
@@ -69,6 +94,7 @@ VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(const VehiclePropValue& r
    ALOGV("get(%d)", propId);

    VehiclePropValuePtr v = nullptr;

    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
    if (internalPropValue != nullptr) {
        v = getValuePool()->obtain(*internalPropValue);
@@ -81,10 +107,7 @@ VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(const VehiclePropValue& r
    } else {
        *outStatus = StatusCode::TRY_AGAIN;
    }
    if (v.get()) {
        v->timestamp = elapsedRealtimeNano();
    }
    return v;
    return addTimestamp(std::move(v));
}

std::vector<VehiclePropConfig> DefaultVehicleHal::listProperties() {
@@ -258,6 +281,32 @@ StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
        return StatusCode::INVALID_ARG;
    }

    std::unordered_set<int32_t> powerProps(std::begin(kHvacPowerProperties),
                                           std::end(kHvacPowerProperties));
    if (powerProps.count(propValue.prop)) {
        auto hvacPowerOn = mPropStore->readValueOrNull(
                toInt(VehicleProperty::HVAC_POWER_ON),
                (VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_1_RIGHT |
                 VehicleAreaSeat::ROW_2_LEFT | VehicleAreaSeat::ROW_2_CENTER |
                 VehicleAreaSeat::ROW_2_RIGHT));

        if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1 &&
            hvacPowerOn->value.int32Values[0] == 0) {
            return StatusCode::NOT_AVAILABLE;
        }
    }

    if (propValue.prop == VEHICLE_MAP_SERVICE) {
        // Placeholder for future implementation of VMS property in the default hal. For
        // now, just returns OK; otherwise, hal clients crash with property not supported.
        return StatusCode::OK;
    }
    if (isDebugProperty(propValue.prop)) {
        // These are special debug properties and do not need a config or check.
        // TODO(shanyu): Remove this after we remove debug properties.
        return mVehicleClient->setProperty(propValue, /*updateStatus=*/false);
    }

    int32_t property = propValue.prop;
    const VehiclePropConfig* config = mPropStore->getConfigOrNull(property);
    if (config == nullptr) {
@@ -298,7 +347,7 @@ void DefaultVehicleHal::onCreate() {
    auto configs = mVehicleClient->getAllPropertyConfig();

    for (const auto& cfg : configs) {
        int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size();
        int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();

        for (int i = 0; i < numAreas; i++) {
            int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
@@ -315,6 +364,7 @@ void DefaultVehicleHal::onCreate() {
    }

    mVehicleClient->triggerSendAllValues();

    registerHeartBeatEvent();
}

@@ -344,14 +394,6 @@ VehicleHal::VehiclePropValuePtr DefaultVehicleHal::doInternalHealthCheck() {
    return v;
}

VehicleHal::VehiclePropValuePtr DefaultVehicleHal::createVhalHeartBeatProp() {
    VehicleHal::VehiclePropValuePtr v = getValuePool()->obtainInt64(uptimeMillis());
    v->prop = static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT);
    v->areaId = 0;
    v->status = VehiclePropertyStatus::AVAILABLE;
    return v;
}

void DefaultVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& properties) {
    auto& pool = *getValuePool();

+17 −6
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@

#include <vhal_v2_0/RecurrentTimer.h>
#include <vhal_v2_0/VehicleHal.h>
#include "vhal_v2_0/VehiclePropertyStore.h"
#include <vhal_v2_0/VehiclePropertyStore.h>

#include "VehicleHalClient.h"

@@ -55,10 +55,20 @@ class DefaultVehicleHal : public VehicleHal {
    VehiclePropertyStore* mPropStore;
    RecurrentTimer mRecurrentTimer;
    VehicleHalClient* mVehicleClient;
    virtual bool isContinuousProperty(int32_t propId) const;
    virtual void initStaticConfig();
    virtual void onContinuousPropertyTimer(const std::vector<int32_t>& properties);

    // The callback that would be called when a property value is updated. This function could
    // be extended to handle specific property update event.
    virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus);
    // Do an internal health check, vendor should add health check logic in this function.
    virtual VehicleHal::VehiclePropValuePtr doInternalHealthCheck();

    // The callback that would be called for every event generated by 'subscribe' or heartbeat.
    // Properties contains a list of properties that need to be handled.
    void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
    // Initiate config for all properties, would be called during onCreate().
    void initStaticConfig();
    // Whether the property is a continuous property.
    bool isContinuousProperty(int32_t propId) const;
    // Returns a lambda that could be used in mRecurrentTimer.
    RecurrentTimer::Action getTimerAction();
    // Check whether a propValue is valid according to its type.
@@ -69,8 +79,7 @@ class DefaultVehicleHal : public VehicleHal {
    // Register the heart beat event to be sent every 3s. This is required to inform watch dog that
    // VHAL is alive. Subclasses should always calls this function during onCreate.
    void registerHeartBeatEvent();

    VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
    // Create a VHAL heart beat property.
    VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();

  private:
@@ -78,6 +87,8 @@ class DefaultVehicleHal : public VehicleHal {
    // See 'VehiclePropertyType' documentation in 'types.hal' for detail.
    StatusCode checkVendorMixedPropValue(const VehiclePropValue& value,
                                         const VehiclePropConfig* config);
    // Read the override properties from a config file.
    void getAllPropertiesOverride();
};

}  // namespace impl
+33 −0
Original line number Diff line number Diff line
@@ -17,11 +17,13 @@
#define LOG_TAG "DefaultVehicleHalServer"

#include <fstream>
#include <regex>

#include <android-base/format.h>
#include <android-base/logging.h>
#include <android-base/parsedouble.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <utils/SystemClock.h>

#include "DefaultConfig.h"
@@ -38,6 +40,10 @@ namespace V2_0 {

namespace impl {

namespace {
const char* VENDOR_OVERRIDE_DIR = "/vendor/etc/vhaloverride/";
}  // namespace

void DefaultVehicleHalServer::storePropInitialValue(const ConfigDeclaration& config) {
    VehiclePropConfig cfg = config.config;

@@ -74,6 +80,7 @@ DefaultVehicleHalServer::DefaultVehicleHalServer() {
        mServerSidePropStore.registerProperty(cfg);
        storePropInitialValue(it);
    }
    maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
}

void DefaultVehicleHalServer::sendAllValuesToClient() {
@@ -559,6 +566,32 @@ IVehicleServer::DumpResult DefaultVehicleHalServer::genFakeData(
    return result;
}

void DefaultVehicleHalServer::maybeOverrideProperties(const char* overrideDir) {
    if (android::base::GetBoolProperty("persist.vendor.vhal_init_value_override", false)) {
        overrideProperties(overrideDir);
    }
}

void DefaultVehicleHalServer::overrideProperties(const char* overrideDir) {
    LOG(INFO) << "loading vendor override properties from " << overrideDir;
    if (auto dir = opendir(overrideDir)) {
        std::regex reg_json(".*[.]json", std::regex::icase);
        while (auto f = readdir(dir)) {
            if (!regex_match(f->d_name, reg_json)) {
                continue;
            }
            std::string file = overrideDir + std::string(f->d_name);
            JsonFakeValueGenerator tmpGenerator(file);

            std::vector<VehiclePropValue> propValues = tmpGenerator.getAllEvents();
            for (const VehiclePropValue& prop : propValues) {
                mServerSidePropStore.writeValue(prop, true);
            }
        }
        closedir(dir);
    }
}

}  // namespace impl

}  // namespace V2_0
Loading