Enlengthen VHAL health check if a device is slow

- Car watchdog uses the given interval to check VHAL health, if
ro.carwatchdog.vhal_healthcheck.interval is set.
- If it is not set or shoter than 3s, car watchdog uses the default
interval, 3s.

Bug: 193742550
Test: VHAL on AA emulator should not be killed by car watchdog
Change-Id: I39e4b886ca22c02409475ba170f666b85bffadf0
diff --git a/cpp/watchdog/server/src/WatchdogProcessService.cpp b/cpp/watchdog/server/src/WatchdogProcessService.cpp
index fca1174..891c6e2 100644
--- a/cpp/watchdog/server/src/WatchdogProcessService.cpp
+++ b/cpp/watchdog/server/src/WatchdogProcessService.cpp
@@ -21,7 +21,6 @@
 
 #include "WatchdogServiceHelper.h"
 
-#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/properties.h>
@@ -50,6 +49,7 @@
 using ::android::sp;
 using ::android::String16;
 using ::android::base::Error;
+using ::android::base::GetIntProperty;
 using ::android::base::GetProperty;
 using ::android::base::ReadFileToString;
 using ::android::base::Result;
@@ -83,12 +83,14 @@
 const int32_t MSG_VHAL_WATCHDOG_ALIVE = static_cast<int>(TimeoutLength::TIMEOUT_NORMAL) + 1;
 const int32_t MSG_VHAL_HEALTH_CHECK = MSG_VHAL_WATCHDOG_ALIVE + 1;
 
-// TODO(b/193742550): Restore the timeout to 3s after configuration by vendors is added.
-// VHAL sends heart beat every 6s. Car watchdog checks if there is the latest heart beat from VHAL
-// with 1s marginal time.
-constexpr std::chrono::milliseconds kVhalHeartBeatIntervalMs = 6s;
-constexpr std::chrono::nanoseconds kVhalHealthCheckDelayNs = kVhalHeartBeatIntervalMs + 1s;
+// VHAL is supposed to send heart beat every 3s. Car watchdog checks if there is the latest heart
+// beat from VHAL within 3s, allowing 1s marginal time.
+// If {@code ro.carwatchdog.vhal_healthcheck.interval} is set, car watchdog checks VHAL health at
+// the given interval. The lower bound of the interval is 3s.
+constexpr int32_t kDefaultVhalCheckIntervalSec = 3;
+constexpr std::chrono::milliseconds kHealthCheckDelayMs = 1s;
 
+constexpr const char kPropertyVhalCheckInterval[] = "ro.carwatchdog.vhal_healthcheck.interval";
 constexpr const char kServiceName[] = "WatchdogProcessService";
 constexpr const char kVhalInterfaceName[] = "android.hardware.automotive.vehicle@2.0::IVehicle";
 
@@ -140,6 +142,10 @@
         mClients.insert(std::make_pair(timeout, std::vector<ClientInfo>()));
         mPingedClients.insert(std::make_pair(timeout, PingedClientMap()));
     }
+    int32_t vhalHealthCheckIntervalSec =
+            GetIntProperty(kPropertyVhalCheckInterval, kDefaultVhalCheckIntervalSec);
+    vhalHealthCheckIntervalSec = std::max(vhalHealthCheckIntervalSec, kDefaultVhalCheckIntervalSec);
+    mVhalHealthCheckWindowMs = std::chrono::seconds(vhalHealthCheckIntervalSec);
 }
 Result<void> WatchdogProcessService::registerWatchdogServiceHelper(
         const sp<IWatchdogServiceHelper>& helper) {
@@ -339,6 +345,9 @@
         }
     }
     WriteStringToFd(StringPrintf("%sStopped users: %s\n", indent, buffer.c_str()), fd);
+    WriteStringToFd(StringPrintf("%sVHAL health check interval: %lldms\n", indent,
+                                 mVhalHealthCheckWindowMs.count()),
+                    fd);
     return {};
 }
 
@@ -764,7 +773,8 @@
         ALOGW("Failed to subscribe to VHAL_HEARTBEAT. Checking VHAL health is disabled.");
         return;
     }
-    mHandlerLooper->sendMessageDelayed(kVhalHealthCheckDelayNs.count(), mMessageHandler,
+    std::chrono::nanoseconds intervalNs = mVhalHealthCheckWindowMs + kHealthCheckDelayMs;
+    mHandlerLooper->sendMessageDelayed(intervalNs.count(), mMessageHandler,
                                        Message(MSG_VHAL_HEALTH_CHECK));
 }
 
@@ -789,7 +799,8 @@
         terminateVhal();
         return;
     }
-    mHandlerLooper->sendMessageDelayed(kVhalHealthCheckDelayNs.count(), mMessageHandler,
+    std::chrono::nanoseconds intervalNs = mVhalHealthCheckWindowMs + kHealthCheckDelayMs;
+    mHandlerLooper->sendMessageDelayed(intervalNs.count(), mMessageHandler,
                                        Message(MSG_VHAL_HEALTH_CHECK));
 }
 
@@ -800,7 +811,7 @@
         Mutex::Autolock lock(mMutex);
         lastEventTime = mVhalHeartBeat.eventTime;
     }
-    if (currentUptime > lastEventTime + kVhalHeartBeatIntervalMs.count()) {
+    if (currentUptime > lastEventTime + mVhalHealthCheckWindowMs.count()) {
         ALOGW("VHAL failed to update heart beat within timeout. Terminating VHAL...");
         terminateVhal();
     }
diff --git a/cpp/watchdog/server/src/WatchdogProcessService.h b/cpp/watchdog/server/src/WatchdogProcessService.h
index 7fab6cb..46d3ef4 100644
--- a/cpp/watchdog/server/src/WatchdogProcessService.h
+++ b/cpp/watchdog/server/src/WatchdogProcessService.h
@@ -17,6 +17,7 @@
 #ifndef CPP_WATCHDOG_SERVER_SRC_WATCHDOGPROCESSSERVICE_H_
 #define CPP_WATCHDOG_SERVER_SRC_WATCHDOGPROCESSSERVICE_H_
 
+#include <android-base/chrono_utils.h>
 #include <android-base/result.h>
 #include <android/automotive/watchdog/ICarWatchdogClient.h>
 #include <android/automotive/watchdog/internal/ICarWatchdogMonitor.h>
@@ -244,6 +245,7 @@
             mNotSupportedVhalProperties;
     android::sp<PropertyChangeListener> mPropertyChangeListener;
     HeartBeat mVhalHeartBeat GUARDED_BY(mMutex);
+    std::chrono::milliseconds mVhalHealthCheckWindowMs;
     android::sp<IWatchdogServiceHelper> mWatchdogServiceHelper GUARDED_BY(mMutex);
 };