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,
+};