Add CHRE daemon retry logic in initial time sync
We cannot perform a retry in the CHRE thread start method,
because there is a chance that the reverse monitor thread fails to
initialize. Intead, move the initial time sync message as the
first FastRPC method invocation and perform the retry there.
Bug: 138139617
Test: Push to device, verify reverse monitor initialization
does not fail after multiple reboots. Also verify that
the initial time sync message is successfully sent after
the CHRE thread starts.
Change-Id: I4ebf029e3a2fe777ac6c8d5037f05d413be4bd5f
diff --git a/host/msm/daemon/chre_daemon.cc b/host/msm/daemon/chre_daemon.cc
index 2dd253d..e6b8bc5 100644
--- a/host/msm/daemon/chre_daemon.cc
+++ b/host/msm/daemon/chre_daemon.cc
@@ -293,23 +293,13 @@
return timeOffset;
}
-static int startChreThread() {
- int ret;
- // Retry a few times in case the SLPI is not ready yet.
- constexpr size_t kMaxNumRetries = 5;
- size_t numRetries = 0;
- useconds_t retryDelayUs = 50000; // 50 ms initially
- while (((ret = chre_slpi_start_thread()) != CHRE_FASTRPC_SUCCESS)
- && numRetries < kMaxNumRetries) {
- usleep(retryDelayUs);
- numRetries++;
- retryDelayUs *= 2;
- }
- return ret;
-}
-
-static void sendTimeSyncMessage() {
+/**
+ * @param logOnError If true, logs an error message on failure.
+ *
+ * @return true if the time sync message was successfully sent to CHRE.
+ */
+static bool sendTimeSyncMessage(bool logOnError) {
bool timeSyncSuccess = true;
int64_t timeOffset = getTimeOffset(&timeSyncSuccess);
@@ -321,10 +311,36 @@
static_cast<int>(builder.GetSize()));
if (success != 0) {
- LOGE("Failed to deliver time sync message from host to CHRE: %d",
- success);
+ if (logOnError) {
+ LOGE("Failed to deliver time sync message from host to CHRE: %d",
+ success);
+ }
+ timeSyncSuccess = false;
}
}
+
+ return timeSyncSuccess;
+}
+
+/**
+ * Sends a time sync message to CHRE, retrying a specified time until success.
+ *
+ * @param maxNumRetries The number of times to retry sending the message
+ *
+ * @return true if the time sync message was successfully sent to CHRE.
+ */
+static bool sendTimeSyncMessageRetry(size_t maxNumRetries) {
+ size_t numRetries = 0;
+ useconds_t retryDelayUs = 50000; // 50 ms initially
+ bool success = sendTimeSyncMessage(numRetries == maxNumRetries);
+ while (!success && numRetries < maxNumRetries) {
+ usleep(retryDelayUs);
+ numRetries++;
+ retryDelayUs *= 2;
+ success = sendTimeSyncMessage(numRetries == maxNumRetries);
+ }
+
+ return success;
}
#ifdef CHRE_DAEMON_LPMA_ENABLED
@@ -829,7 +845,7 @@
if (messageType == fbs::ChreMessage::LogMessage) {
parseAndEmitLogMessages(messageBuffer);
} else if (messageType == fbs::ChreMessage::TimeSyncRequest) {
- sendTimeSyncMessage();
+ sendTimeSyncMessage(true /* logOnError */);
#ifdef CHRE_DAEMON_LPMA_ENABLED
} else if (messageType == fbs::ChreMessage::LowPowerMicAccessRequest) {
setLpmaState(true);
@@ -972,14 +988,20 @@
}
#endif // ADSPRPC
- if (!init_reverse_monitor(&reverse_monitor)) {
+ // Send time sync message before nanoapps start, retrying a few times
+ // in case the SLPI is not ready yet. This retry logic must be placed before
+ // any of the other FastRPC method invocations.
+ constexpr size_t kMaxNumRetries = 5;
+ if (!sendTimeSyncMessageRetry(kMaxNumRetries)) {
+ LOGE("Failed to send initial time sync message");
+ } else if (!init_reverse_monitor(&reverse_monitor)) {
LOGE("Couldn't initialize reverse monitor");
#ifdef CHRE_DAEMON_LPMA_ENABLED
} else if (!initLpmaEnableThread(&lpmaEnableThread)) {
LOGE("Couldn't initialize LPMA enable thread");
#endif // CHRE_DAEMON_LPMA_ENABLED
} else {
- if ((ret = startChreThread()) != CHRE_FASTRPC_SUCCESS) {
+ if ((ret = chre_slpi_start_thread()) != CHRE_FASTRPC_SUCCESS) {
LOGE("Failed to start CHRE: %d", ret);
} else {
if (!start_thread(&monitor_thread, chre_monitor_thread, NULL)) {
@@ -989,8 +1011,6 @@
LOGE("Couldn't start CHRE->Host message thread");
} else {
LOGI("CHRE started");
- // Send a time sync message before any of the nanoapps start.
- sendTimeSyncMessage();
loadPreloadedNanoapps();
// TODO: take 2nd argument as command-line parameter