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
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 47133fd..62a4f20 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -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 @@
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 @@
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;
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 16e1bf7..fc83078 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -1074,6 +1074,30 @@
.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
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index a0b566d..c83e2de 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -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 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 @@
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 @@
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 @@
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
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index eb38d7d..5c67641 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -82,6 +82,8 @@
VehiclePropValue* outValue);
StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
+ VehicleHal::VehiclePropValuePtr doInternalHealthCheck();
+ VehicleHal::VehiclePropValuePtr createVhalHeartBeatProp();
/* Private members */
VehiclePropertyStore* mPropStore;
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f7a42e9..b7c72e4 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2892,6 +2892,52 @@
| 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 @@
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,
+};