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

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

Merge changes from topics "aae-watchdog-vhal-integration", "aae_new_vhal_healthcheck"

* changes:
  New health check in VHAL
  Add vehicle properties to integrate car watchdog
parents c9b507f7 81108e24
Loading
Loading
Loading
Loading
+2 −19
Original line number Diff line number Diff line
@@ -20,13 +20,10 @@

#include <iostream>

#include <android/binder_process.h>
#include <utils/Looper.h>
#include <vhal_v2_0/EmulatedUserHal.h>
#include <vhal_v2_0/EmulatedVehicleConnector.h>
#include <vhal_v2_0/EmulatedVehicleHal.h>
#include <vhal_v2_0/VehicleHalManager.h>
#include <vhal_v2_0/WatchdogClient.h>

using namespace android;
using namespace android::hardware;
@@ -41,7 +38,7 @@ int main(int /* argc */, char* /* argv */ []) {
    auto service = std::make_unique<VehicleHalManager>(hal.get());
    connector->setValuePool(hal->getValuePool());

    configureRpcThreadpool(4, false /* callerWillJoin */);
    configureRpcThreadpool(4, true /* callerWillJoin */);

    ALOGI("Registering as service...");
    status_t status = service->registerAsService();
@@ -51,22 +48,8 @@ int main(int /* argc */, char* /* argv */ []) {
        return 1;
    }

    // Setup a binder thread pool to be a car watchdog client.
    ABinderProcess_setThreadPoolMaxThreadCount(1);
    ABinderProcess_startThreadPool();
    sp<Looper> looper(Looper::prepare(0 /* opts */));
    std::shared_ptr<WatchdogClient> watchdogClient =
            ndk::SharedRefBase::make<WatchdogClient>(looper, service.get());
    // The current health check is done in the main thread, so it falls short of capturing the real
    // situation. Checking through HAL binder thread should be considered.
    if (!watchdogClient->initialize()) {
        ALOGE("Failed to initialize car watchdog client");
        return 1;
    }
    ALOGI("Ready");
    while (true) {
        looper->pollAll(-1 /* timeoutMillis */);
    }
    joinRpcThreadpool();

    return 1;
}
+24 −0
Original line number Diff line number Diff line
@@ -1074,6 +1074,30 @@ const ConfigDeclaration kVehicleProperties[]{
                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                        },
        },
        {
                .config =
                        {
                                .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
                                .access = VehiclePropertyAccess::WRITE,
                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                        },
        },
        {
                .config =
                        {
                                .prop = toInt(VehicleProperty::WATCHDOG_TERMINATED_PROCESS),
                                .access = VehiclePropertyAccess::WRITE,
                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                        },
        },
        {
                .config =
                        {
                                .prop = toInt(VehicleProperty::VHAL_HEARTBEAT),
                                .access = VehiclePropertyAccess::READ,
                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                        },
        },
};

}  // impl
+35 −0
Original line number Diff line number Diff line
@@ -15,11 +15,13 @@
 */
#define LOG_TAG "DefaultVehicleHal_v2_0"

#include <android-base/chrono_utils.h>
#include <android-base/macros.h>
#include <android-base/properties.h>
#include <android/log.h>
#include <dirent.h>
#include <sys/system_properties.h>
#include <utils/SystemClock.h>
#include <fstream>
#include <regex>

@@ -36,6 +38,8 @@ namespace V2_0 {

namespace impl {

static constexpr std::chrono::nanoseconds kHeartBeatIntervalNs = 3s;

static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
                                                             size_t numVendorFloatSensors) {
    std::unique_ptr<Obd2SensorStore> sensorStore(
@@ -342,6 +346,8 @@ void EmulatedVehicleHal::onCreate() {
    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
    mInEmulator = isInEmulator();
    ALOGD("mInEmulator=%s", mInEmulator ? "true" : "false");
    mRecurrentTimer.registerRecurrentEvent(kHeartBeatIntervalNs,
                                           static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT));
}

std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
@@ -359,6 +365,10 @@ void EmulatedVehicleHal::onContinuousPropertyTimer(const std::vector<int32_t>& p
            if (internalPropValue != nullptr) {
                v = pool.obtain(*internalPropValue);
            }
        } else if (property == static_cast<int32_t>(VehicleProperty::VHAL_HEARTBEAT)) {
            // VHAL_HEARTBEAT is not a continuous value, but it needs to be updated periodically.
            // So, the update is done through onContinuousPropertyTimer.
            v = doInternalHealthCheck();
        } else {
            ALOGE("Unexpected onContinuousPropertyTimer for property: 0x%x", property);
        }
@@ -512,6 +522,31 @@ StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) {
    return StatusCode::OK;
}

VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::doInternalHealthCheck() {
    VehicleHal::VehiclePropValuePtr v = nullptr;

    // This is an example of very simpe health checking. VHAL is considered healthy if we can read
    // PERF_VEHICLE_SPEED. The more comprehensive health checking is required.
    VehiclePropValue propValue = {
            .prop = static_cast<int32_t>(VehicleProperty::PERF_VEHICLE_SPEED),
    };
    auto internalPropValue = mPropStore->readValueOrNull(propValue);
    if (internalPropValue != nullptr) {
        v = createVhalHeartBeatProp();
    } else {
        ALOGW("VHAL health check failed");
    }
    return v;
}

VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::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;
}

}  // impl

}  // namespace V2_0
+2 −0
Original line number Diff line number Diff line
@@ -82,6 +82,8 @@ private:
                                   VehiclePropValue* outValue);
    StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
    StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
    VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
    VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();

    /* Private members */
    VehiclePropertyStore* mPropStore;
+66 −0
Original line number Diff line number Diff line
@@ -2892,6 +2892,52 @@ enum VehicleProperty : int32_t {
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:MIXED
        | VehicleArea:GLOBAL),

    /**
     * Defines an event that car watchdog updates to tell it's alive.
     *
     * Car watchdog sets this property to system uptime in milliseconds at every 3 second.
     * During the boot, the update may take longer time.
     *
     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
     * @access VehiclePropertyAccess:WRITE
     */
    WATCHDOG_ALIVE = (
        0xF31
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:INT64
        | VehicleArea:GLOBAL),

    /**
     * Defines a process terminated by car watchdog and the reason of termination.
     *
     * int32Values[0]: 1         // ProcessTerminationReason showing why a process is terminated.
     * string: "/system/bin/log" // Process execution command.
     *
     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
     * @access VehiclePropertyAccess:WRITE
     */
    WATCHDOG_TERMINATED_PROCESS = (
        0x0F32
        | VehiclePropertyGroup:SYSTEM
        | VehiclePropertyType:MIXED
        | VehicleArea:GLOBAL),

    /**
     * Defines an event that VHAL signals to the car watchdog as a heartbeat.
     *
     * VHAL is supposed to write system uptime to this property at every 3 second.
     * Car watchdog subscribes to this property and checks if the property is updated at every 3
     * second. If it isn’t, car watchdog considers VHAL unhealthy and terminates it.
     *
     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
     * @access VehiclePropertyAccess:READ
     */
     VHAL_HEARTBEAT = (
         0x0F33
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:INT64
         | VehicleArea:GLOBAL),
};

/**
@@ -4790,3 +4836,23 @@ enum RotaryInputType : int32_t {
    ROTARY_INPUT_TYPE_AUDIO_VOLUME = 1,
};

/**
 * The reason why a process is terminated by car watchdog.
 * This is used with WATCHDOG_TERMINATED_PROCESS property.
 */
enum ProcessTerminationReason : int32_t {
   /**
    * A process doesn't respond to car watchdog within the timeout.
    */
   NOT_RESPONDING = 1,

   /**
    * A process uses more IO operations than what is allowed.
    */
   IO_OVERUSE = 2,

   /**
    * A process uses more memory space than what is allowed.
    */
   MEMORY_OVERUSE = 3,
};