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

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

Merge changes from topic "default_vhal_emulated_user"

* changes:
  Move emulatedUserHal to default VHAL.
  Add fake OBD2 frame logic to default VHAL.
  Support vendor override in default VHAL.
parents 3884b0f2 56020bc1
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -92,10 +92,12 @@ cc_library_static {
        "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
        "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
        "impl/vhal_v2_0/GeneratorHub.cpp",
        "impl/vhal_v2_0/FakeObd2Frame.cpp",
    ],
    local_include_dirs: ["common/include/vhal_v2_0"],
    export_include_dirs: ["impl"],
    whole_static_libs: [
        "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
        "android.hardware.automotive.vehicle@2.0-manager-lib",
    ],
    shared_libs: [
@@ -141,10 +143,10 @@ cc_library_static {
        "impl/vhal_v2_0/JsonFakeValueGenerator.cpp",
        "impl/vhal_v2_0/LinearFakeValueGenerator.cpp",
        "impl/vhal_v2_0/DefaultVehicleHalServer.cpp",
        "impl/vhal_v2_0/FakeObd2Frame.cpp",
    ],
    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 +215,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_json",
        ":vhal_test_override_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());
+172 −14
Original line number Diff line number Diff line
@@ -17,10 +17,14 @@

#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 "FakeObd2Frame.h"
#include "PropertyUtils.h"
#include "VehicleUtils.h"

#include "DefaultVehicleHal.h"
@@ -52,8 +56,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();
@@ -63,12 +89,51 @@ DefaultVehicleHal::DefaultVehicleHal(VehiclePropertyStore* propStore, VehicleHal
            });
}

VehicleHal::VehiclePropValuePtr DefaultVehicleHal::getUserHalProp(
        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
    auto propId = requestedPropValue.prop;
    ALOGI("get(): getting value for prop %d from User HAL", propId);
    const auto& ret = mEmulatedUserHal.onGetProperty(requestedPropValue);
    VehicleHal::VehiclePropValuePtr v = nullptr;
    if (!ret.ok()) {
        ALOGE("get(): User HAL returned error: %s", ret.error().message().c_str());
        *outStatus = StatusCode(ret.error().code());
    } else {
        auto value = ret.value().get();
        if (value != nullptr) {
            ALOGI("get(): User HAL returned value: %s", toString(*value).c_str());
            v = getValuePool()->obtain(*value);
            *outStatus = StatusCode::OK;
        } else {
            ALOGE("get(): User HAL returned null value");
            *outStatus = StatusCode::INTERNAL_ERROR;
        }
    }
    return addTimestamp(std::move(v));
}

VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(const VehiclePropValue& requestedPropValue,
                                                       StatusCode* outStatus) {
    auto propId = requestedPropValue.prop;
    ALOGV("get(%d)", propId);

    if (mEmulatedUserHal.isSupported(propId)) {
        return getUserHalProp(requestedPropValue, outStatus);
    }

    VehiclePropValuePtr v = nullptr;
    if (propId == OBD2_FREEZE_FRAME) {
        v = getValuePool()->obtainComplex();
        *outStatus = fillObd2FreezeFrame(mPropStore, requestedPropValue, v.get());
        return addTimestamp(std::move(v));
    }

    if (propId == OBD2_FREEZE_FRAME_INFO) {
        v = getValuePool()->obtainComplex();
        *outStatus = fillObd2DtcInfo(mPropStore, v.get());
        return addTimestamp(std::move(v));
    }

    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
    if (internalPropValue != nullptr) {
        v = getValuePool()->obtain(*internalPropValue);
@@ -81,10 +146,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() {
@@ -92,6 +154,36 @@ std::vector<VehiclePropConfig> DefaultVehicleHal::listProperties() {
}

bool DefaultVehicleHal::dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
    int nativeFd = fd->data[0];
    if (nativeFd < 0) {
        ALOGW("Invalid fd from HIDL handle: %d", nativeFd);
        return false;
    }
    if (options.size() > 0) {
        if (options[0] == "--help") {
            std::string buffer;
            buffer += "Emulated user hal usage:\n";
            buffer += mEmulatedUserHal.showDumpHelp();
            buffer += "\n";
            buffer += "VHAL server debug usage:\n";
            buffer += "--debughal: send debug command to VHAL server, see '--debughal --help'\n";
            buffer += "\n";
            dprintf(nativeFd, "%s", buffer.c_str());
            return false;
        } else if (options[0] == kUserHalDumpOption) {
            dprintf(nativeFd, "%s", mEmulatedUserHal.dump("").c_str());
            return false;
        }
    } else {
        // No options, dump the emulated user hal state first and then send command to VHAL server
        // to dump its state.
        std::string buffer;
        buffer += "Emulator user hal state:\n";
        buffer += mEmulatedUserHal.dump("  ");
        buffer += "\n";
        dprintf(nativeFd, "%s", buffer.c_str());
    }

    return mVehicleClient->dump(fd, options);
}

@@ -250,6 +342,23 @@ StatusCode DefaultVehicleHal::checkValueRange(const VehiclePropValue& value,
    return StatusCode::OK;
}

StatusCode DefaultVehicleHal::setUserHalProp(const VehiclePropValue& propValue) {
    ALOGI("onSetProperty(): property %d will be handled by UserHal", propValue.prop);

    const auto& ret = mEmulatedUserHal.onSetProperty(propValue);
    if (!ret.ok()) {
        ALOGE("onSetProperty(): HAL returned error: %s", ret.error().message().c_str());
        return StatusCode(ret.error().code());
    }
    auto updatedValue = ret.value().get();
    if (updatedValue != nullptr) {
        ALOGI("onSetProperty(): updating property returned by HAL: %s",
              toString(*updatedValue).c_str());
        onPropertyValue(*updatedValue, true);
    }
    return StatusCode::OK;
}

StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
    if (propValue.status != VehiclePropertyStatus::AVAILABLE) {
        // Android side cannot set property status - this value is the
@@ -258,6 +367,39 @@ StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
        return StatusCode::INVALID_ARG;
    }

    if (mEmulatedUserHal.isSupported(propValue.prop)) {
        return setUserHalProp(propValue);
    }

    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 == OBD2_FREEZE_FRAME_CLEAR) {
        return clearObd2FreezeFrames(mPropStore, propValue);
    }
    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 +440,13 @@ void DefaultVehicleHal::onCreate() {
    auto configs = mVehicleClient->getAllPropertyConfig();

    for (const auto& cfg : configs) {
        int32_t numAreas = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs.size();
        if (isDiagnosticProperty(cfg)) {
            // do not write an initial empty value for the diagnostic properties
            // as we will initialize those separately.
            continue;
        }

        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 +463,10 @@ void DefaultVehicleHal::onCreate() {
    }

    mVehicleClient->triggerSendAllValues();

    initObd2LiveFrame(mPropStore, *mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
    initObd2FreezeFrame(mPropStore, *mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));

    registerHeartBeatEvent();
}

@@ -344,14 +496,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();

@@ -432,7 +576,21 @@ void DefaultVehicleHal::onPropertyValue(const VehiclePropValue& value, bool upda
void DefaultVehicleHal::initStaticConfig() {
    auto configs = mVehicleClient->getAllPropertyConfig();
    for (auto&& cfg : configs) {
        mPropStore->registerProperty(cfg, nullptr);
        VehiclePropertyStore::TokenFunction tokenFunction = nullptr;

        switch (cfg.prop) {
            case OBD2_FREEZE_FRAME: {
                // We use timestamp as token for OBD2_FREEZE_FRAME
                tokenFunction = [](const VehiclePropValue& propValue) {
                    return propValue.timestamp;
                };
                break;
            }
            default:
                break;
        }

        mPropStore->registerProperty(cfg, tokenFunction);
    }
}

+24 −6
Original line number Diff line number Diff line
@@ -19,8 +19,9 @@

#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 "EmulatedUserHal.h"
#include "VehicleHalClient.h"

namespace android {
@@ -55,10 +56,21 @@ 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);
    EmulatedUserHal mEmulatedUserHal;

    // 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 +81,12 @@ 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();
    // Get a user HAL property.
    VehiclePropValuePtr getUserHalProp(const VehiclePropValue& requestedPropValue,
                                       StatusCode* outStatus);
    // Set a user HAL property.
    StatusCode setUserHalProp(const VehiclePropValue& propValue);
    // Create a VHAL heart beat property.
    VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();

  private:
@@ -78,6 +94,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
+38 −0
Original line number Diff line number Diff line
@@ -17,14 +17,17 @@
#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"
#include "FakeObd2Frame.h"
#include "JsonFakeValueGenerator.h"
#include "LinearFakeValueGenerator.h"

@@ -38,6 +41,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;

@@ -72,8 +79,13 @@ DefaultVehicleHalServer::DefaultVehicleHalServer() {
    for (auto& it : kVehicleProperties) {
        VehiclePropConfig cfg = it.config;
        mServerSidePropStore.registerProperty(cfg);
        // Skip diagnostic properties since there is special logic to handle those.
        if (isDiagnosticProperty(cfg)) {
            continue;
        }
        storePropInitialValue(it);
    }
    maybeOverrideProperties(VENDOR_OVERRIDE_DIR);
}

void DefaultVehicleHalServer::sendAllValuesToClient() {
@@ -559,6 +571,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