1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * @file
19  * The daemon that hosts CHRE on a hexagon DSP via FastRPC. This is typically
20  * the SLPI but could be the ADSP or another DSP that supports FastRPC.
21  *
22  * Several threads are required for this functionality:
23  *   - Main thread: blocked waiting on SIGINT/SIGTERM, and requests graceful
24  *     shutdown of CHRE when caught
25  *   - Monitor thread: persistently blocked in a FastRPC call to the DSP that
26  *     only returns when CHRE exits or the DSP crashes
27  *     - TODO: see whether we can merge this with the RX thread
28  *   - Reverse monitor thread: after initializing the DSP-side monitor for this
29  *     process, blocks on a condition variable. If this thread exits, CHRE on
30  *     the DSP side will be notified and shut down (this is only possible if
31  *     this thread is not blocked in a FastRPC call).
32  *     - TODO: confirm this and see whether we can merge this responsibility
33  *       into the TX thread
34  *   - Message to host (RX) thread: blocks in FastRPC call, waiting on incoming
35  *     message from CHRE
36  *   - Message to CHRE (TX) thread: blocks waiting on outbound queue, delivers
37  *     messages to CHRE over FastRPC
38  *
39  * TODO: This file originated from an implementation for another device, and was
40  * written in C, but then it was converted to C++ when adding socket support. It
41  * should be fully converted to C++.
42  */
43 
44 // Disable verbose logging
45 // TODO: use property_get_bool to make verbose logging runtime configurable
46 // #define LOG_NDEBUG 0
47 
48 #include <ctype.h>
49 #include <inttypes.h>
50 #include <pthread.h>
51 #include <stdbool.h>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <unistd.h>
56 
57 #include <fstream>
58 #include <string>
59 #include <queue>
60 
61 #include "chre/platform/slpi/fastrpc.h"
62 #include "chre_host/log.h"
63 #include "chre_host/host_protocol_host.h"
64 #include "chre_host/socket_server.h"
65 #include "generated/chre_slpi.h"
66 
67 #include <json/json.h>
68 #include <utils/SystemClock.h>
69 
70 #ifdef CHRE_DAEMON_LOAD_INTO_SENSORSPD
71 #include "remote.h"
72 
73 #define ITRANSPORT_PREFIX "'\":;./\\"
74 #endif  // CHRE_DAEMON_LOAD_INTO_SENSORSPD
75 
76 //! The format string to use for logs from the CHRE implementation.
77 #define HUB_LOG_FORMAT_STR "Hub (t=%.6f): %s"
78 
79 #ifdef CHRE_DAEMON_LPMA_ENABLED
80 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
81 #include <hardware_legacy/power.h>
82 
83 using android::sp;
84 using android::wp;
85 using android::hardware::Return;
86 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
87 using android::hardware::soundtrigger::V2_0::SoundModelHandle;
88 using android::hardware::soundtrigger::V2_0::SoundModelType;
89 #endif  // CHRE_DAEMON_LPMA_ENABLED
90 
91 using android::chre::HostProtocolHost;
92 using android::chre::FragmentedLoadTransaction;
93 using android::elapsedRealtimeNano;
94 
95 // Aliased for consistency with the way these symbols are referenced in
96 // CHRE-side code
97 namespace fbs = ::chre::fbs;
98 
99 typedef void *(thread_entry_point_f)(void *);
100 
101 struct reverse_monitor_thread_data {
102   pthread_t       thread;
103   pthread_mutex_t mutex;
104   pthread_cond_t  cond;
105 };
106 
107 static void *chre_message_to_host_thread(void *arg);
108 static void *chre_monitor_thread(void *arg);
109 static void *chre_reverse_monitor_thread(void *arg);
110 static bool init_reverse_monitor(struct reverse_monitor_thread_data *data);
111 static bool start_thread(pthread_t *thread_handle,
112                          thread_entry_point_f *thread_entry,
113                          void *arg);
114 
115 #ifdef CHRE_DAEMON_LPMA_ENABLED
116 //! The name of the wakelock to use for the CHRE daemon.
117 static const char kWakeLockName[] = "chre_daemon";
118 
119 //! Forward declarations
120 static void onStHalServiceDeath();
121 
122 //! Class to handle when a connected ST HAL service dies.
123 class StHalDeathRecipient : public android::hardware::hidl_death_recipient {
serviceDied(uint64_t,const wp<::android::hidl::base::V1_0::IBase> &)124   virtual void serviceDied(
125       uint64_t /* cookie */,
126       const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
127     LOGE("ST HAL service died.");
128     onStHalServiceDeath();
129   }
130 };
131 
132 struct LpmaEnableThreadData {
133   pthread_t thread;
134   pthread_mutex_t mutex;
135   pthread_cond_t cond;
136   bool currentLpmaEnabled;
137   bool targetLpmaEnabled;
138   bool connectedToService;
139   sp<StHalDeathRecipient> deathRecipient = new StHalDeathRecipient();
140   sp<ISoundTriggerHw> stHalService;
141 };
142 
143 static LpmaEnableThreadData lpmaEnableThread;
144 
145 #endif  // CHRE_DAEMON_LPMA_ENABLED
146 
147 //! The host ID to use when preloading nanoapps. This is used before the server
148 //! is started and is sufficiently high enough so as to not collide with any
149 //! clients after the server starts.
150 static const uint16_t kHostClientIdDaemon = UINT16_MAX;
151 
152 //! Contains a set of transaction IDs used to load the preloaded nanoapps.
153 //! The IDs are stored in the order they are sent.
154 static std::queue<uint32_t> gPreloadedNanoappPendingTransactionIds;
155 
156 //! Set to true when we request a graceful shutdown of CHRE
157 static volatile bool chre_shutdown_requested = false;
158 
159 #if !defined(LOG_NDEBUG) || LOG_NDEBUG != 0
log_buffer(const uint8_t *,size_t)160 static void log_buffer(const uint8_t * /*buffer*/, size_t /*size*/) {}
161 #else
log_buffer(const uint8_t * buffer,size_t size)162 static void log_buffer(const uint8_t *buffer, size_t size) {
163   char line[32];
164   int offset = 0;
165   char line_chars[32];
166   int offset_chars = 0;
167 
168   size_t orig_size = size;
169   if (size > 128) {
170     size = 128;
171     LOGV("Dumping first 128 bytes of buffer of size %zu", orig_size);
172   } else {
173     LOGV("Dumping buffer of size %zu bytes", size);
174   }
175   for (size_t i = 1; i <= size; ++i) {
176     offset += snprintf(&line[offset], sizeof(line) - offset, "%02x ",
177                        buffer[i - 1]);
178     offset_chars += snprintf(
179         &line_chars[offset_chars], sizeof(line_chars) - offset_chars,
180         "%c", (isprint(buffer[i - 1])) ? buffer[i - 1] : '.');
181     if ((i % 8) == 0) {
182       LOGV("  %s\t%s", line, line_chars);
183       offset = 0;
184       offset_chars = 0;
185     } else if ((i % 4) == 0) {
186       offset += snprintf(&line[offset], sizeof(line) - offset, " ");
187     }
188   }
189 
190   if (offset > 0) {
191     char tabs[8];
192     char *pos = tabs;
193     while (offset < 28) {
194       *pos++ = '\t';
195       offset += 8;
196     }
197     *pos = '\0';
198     LOGV("  %s%s%s", line, tabs, line_chars);
199   }
200 }
201 #endif
202 
parseAndEmitLogMessages(unsigned char * message)203 static void parseAndEmitLogMessages(unsigned char *message) {
204   const fbs::MessageContainer *container = fbs::GetMessageContainer(message);
205   const auto *logMessage = static_cast<const fbs::LogMessage *>(
206       container->message());
207 
208   constexpr size_t kLogMessageHeaderSize = 2 + sizeof(uint64_t);
209   const flatbuffers::Vector<int8_t>& logData = *logMessage->buffer();
210   for (size_t i = 0; i <= (logData.size() - kLogMessageHeaderSize);) {
211     // Parse out the log level.
212     const char *log = reinterpret_cast<const char *>(&logData.data()[i]);
213     char logLevel = *log;
214     log++;
215 
216     // Parse out the timestampNanos.
217     uint64_t timestampNanos;
218     memcpy(&timestampNanos, log, sizeof(uint64_t));
219     timestampNanos = le64toh(timestampNanos);
220     log += sizeof(uint64_t);
221 
222     float timestampSeconds = timestampNanos / 1e9;
223 
224     // Log the message.
225     switch (logLevel) {
226       case 1:
227         LOGE(HUB_LOG_FORMAT_STR, timestampSeconds, log);
228         break;
229       case 2:
230         LOGW(HUB_LOG_FORMAT_STR, timestampSeconds, log);
231         break;
232       case 3:
233         LOGI(HUB_LOG_FORMAT_STR, timestampSeconds, log);
234         break;
235       case 4:
236         LOGD(HUB_LOG_FORMAT_STR, timestampSeconds, log);
237         break;
238       default:
239         LOGE("Invalid CHRE hub log level, omitting log");
240     }
241 
242     // Advance the log pointer.
243     size_t strLen = strlen(log);
244     i += kLogMessageHeaderSize + strLen;
245   }
246 }
247 
getTimeOffset(bool * success)248 static int64_t getTimeOffset(bool *success) {
249   int64_t timeOffset = 0;
250 
251 #if defined(__aarch64__)
252   // Reads the system time counter (CNTVCT) and its frequency (CNTFRQ)
253   // CNTVCT is used in the sensors HAL for time synchronization.
254   // More information can be found in the ARM reference manual
255   // (http://infocenter.arm.com/help/index.jsp?topic=
256   // /com.arm.doc.100048_0002_05_en/jfa1406793266982.html)
257   // Use uint64_t to store since the MRS instruction uses 64 bit (X) registers
258   // (http://infocenter.arm.com/help/topic/
259   // com.arm.doc.den0024a/ch06s05s02.html)
260   uint64_t qTimerCount = 0, qTimerFreq = 0;
261   uint64_t hostTimeNano = elapsedRealtimeNano();
262   asm volatile("mrs %0, cntvct_el0" : "=r"(qTimerCount));
263   asm volatile("mrs %0, cntfrq_el0" : "=r"(qTimerFreq));
264 
265   constexpr uint64_t kOneSecondInNanoseconds = 1000000000;
266   if (qTimerFreq != 0) {
267     // Get the seconds part first, then convert the remainder to prevent
268     // overflow
269     uint64_t qTimerNanos = (qTimerCount / qTimerFreq);
270     if (qTimerNanos > UINT64_MAX / kOneSecondInNanoseconds) {
271       LOGE("CNTVCT_EL0 conversion to nanoseconds overflowed during time sync."
272            " Aborting time sync.");
273       *success = false;
274     } else {
275       qTimerNanos *= kOneSecondInNanoseconds;
276 
277       // Round the remainder portion to the nearest nanosecond
278       uint64_t remainder = (qTimerCount % qTimerFreq);
279       qTimerNanos +=
280           (remainder * kOneSecondInNanoseconds + qTimerFreq / 2) / qTimerFreq;
281 
282       timeOffset = hostTimeNano - qTimerNanos;
283       *success = true;
284     }
285   } else {
286     LOGE("CNTFRQ_EL0 had 0 value. Aborting time sync.");
287     *success = false;
288   }
289 #else
290 #error "Unsupported CPU architecture type"
291 #endif
292 
293   return timeOffset;
294 }
295 
296 
297 /**
298  * @param logOnError If true, logs an error message on failure.
299  *
300  * @return true if the time sync message was successfully sent to CHRE.
301  */
sendTimeSyncMessage(bool logOnError)302 static bool sendTimeSyncMessage(bool logOnError) {
303   bool timeSyncSuccess = true;
304   int64_t timeOffset = getTimeOffset(&timeSyncSuccess);
305 
306   if (timeSyncSuccess) {
307     flatbuffers::FlatBufferBuilder builder(64);
308     HostProtocolHost::encodeTimeSyncMessage(builder, timeOffset);
309     int success = chre_slpi_deliver_message_from_host(
310         static_cast<const unsigned char *>(builder.GetBufferPointer()),
311         static_cast<int>(builder.GetSize()));
312 
313     if (success != 0) {
314       if (logOnError) {
315         LOGE("Failed to deliver time sync message from host to CHRE: %d",
316              success);
317       }
318       timeSyncSuccess = false;
319     }
320   }
321 
322   return timeSyncSuccess;
323 }
324 
325 /**
326  * Sends a time sync message to CHRE, retrying a specified time until success.
327  *
328  * @param maxNumRetries The number of times to retry sending the message
329  *
330  * @return true if the time sync message was successfully sent to CHRE.
331  */
sendTimeSyncMessageRetry(size_t maxNumRetries)332 static bool sendTimeSyncMessageRetry(size_t maxNumRetries) {
333   size_t numRetries = 0;
334   useconds_t retryDelayUs = 50000; // 50 ms initially
335   bool success = sendTimeSyncMessage(numRetries == maxNumRetries);
336   while (!success && numRetries < maxNumRetries) {
337     usleep(retryDelayUs);
338     numRetries++;
339     retryDelayUs *= 2;
340     success = sendTimeSyncMessage(numRetries == maxNumRetries);
341   }
342 
343   return success;
344 }
345 
346 #ifdef CHRE_DAEMON_LPMA_ENABLED
347 
acquireWakeLock()348 static void acquireWakeLock() {
349   if (acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) != 0) {
350     LOGE("Failed to acquire wakelock");
351   }
352 }
353 
releaseWakeLock()354 static void releaseWakeLock() {
355   static bool initialRelease = true;
356 
357   // It's expected to get an error when we first try to release the wakelock
358   // as it won't exist unless it was leaked previously - don't output a
359   // false warning for this case
360   if (release_wake_lock(kWakeLockName) != 0 && !initialRelease) {
361     LOGE("Failed to release wakelock");
362   }
363 
364   initialRelease = false;
365 }
366 
367 /**
368  * Sets the target state for LPMA to be enabled. This triggers another thread to
369  * perform the async operation of enabling or disabling the LPMA use case.
370  *
371  * @param enabled Whether LPMA is to be enabled or disabled.
372  */
setLpmaState(bool enabled)373 static void setLpmaState(bool enabled) {
374   pthread_mutex_lock(&lpmaEnableThread.mutex);
375   lpmaEnableThread.targetLpmaEnabled = enabled;
376   pthread_mutex_unlock(&lpmaEnableThread.mutex);
377   pthread_cond_signal(&lpmaEnableThread.cond);
378 }
379 
onStHalServiceDeath()380 static void onStHalServiceDeath() {
381   pthread_mutex_lock(&lpmaEnableThread.mutex);
382   lpmaEnableThread.connectedToService = false;
383   if (lpmaEnableThread.targetLpmaEnabled) {
384     // ST HAL has died, so assume that the sound model is no longer active,
385     // and trigger a reload of the sound model.
386     lpmaEnableThread.currentLpmaEnabled = false;
387     pthread_cond_signal(&lpmaEnableThread.cond);
388   }
389   pthread_mutex_unlock(&lpmaEnableThread.mutex);
390 }
391 
392 /**
393  * Connects to the ST HAL service, if not already. This method should only
394  * be invoked after acquiring the lpmaEnableThread.mutex lock.
395  *
396  * @return true if successfully connected to the HAL.
397  */
connectToStHalServiceLocked()398 static bool connectToStHalServiceLocked() {
399   if (!lpmaEnableThread.connectedToService) {
400     lpmaEnableThread.stHalService = ISoundTriggerHw::getService();
401     if (lpmaEnableThread.stHalService != nullptr) {
402       LOGI("Connected to ST HAL service");
403       lpmaEnableThread.connectedToService = true;
404       lpmaEnableThread.stHalService->linkToDeath(
405           lpmaEnableThread.deathRecipient, 0 /* flags */);
406     }
407   }
408 
409   return lpmaEnableThread.connectedToService;
410 }
411 
412 /**
413  * Loads the LPMA use case via the SoundTrigger HAL HIDL service.
414  *
415  * @param lpmaHandle The handle that was generated as a result of enabling
416  *        the LPMA use case successfully.
417  * @return true if LPMA was enabled successfully, false otherwise.
418  */
loadLpma(SoundModelHandle * lpmaHandle)419 static bool loadLpma(SoundModelHandle *lpmaHandle) {
420   LOGD("Loading LPMA");
421 
422   ISoundTriggerHw::SoundModel soundModel;
423   soundModel.type = SoundModelType::GENERIC;
424   soundModel.vendorUuid.timeLow = 0x57CADDB1;
425   soundModel.vendorUuid.timeMid = 0xACDB;
426   soundModel.vendorUuid.versionAndTimeHigh = 0x4DCE;
427   soundModel.vendorUuid.variantAndClockSeqHigh = 0x8CB0;
428 
429   const uint8_t uuidNode[6] = { 0x2E, 0x95, 0xA2, 0x31, 0x3A, 0xEE };
430   memcpy(&soundModel.vendorUuid.node[0], uuidNode, sizeof(uuidNode));
431   soundModel.data.resize(1);  // Insert a dummy byte to bypass HAL NULL checks.
432 
433   bool loaded = false;
434   if (!connectToStHalServiceLocked()) {
435     LOGE("Failed to get ST HAL service for LPMA load");
436   } else {
437     int32_t loadResult;
438     Return<void> hidlResult = lpmaEnableThread.stHalService->loadSoundModel(
439         soundModel, NULL /* callback */, 0 /* cookie */,
440         [&](int32_t retval, SoundModelHandle handle) {
441             loadResult = retval;
442             *lpmaHandle = handle;
443         });
444 
445     if (hidlResult.isOk()) {
446       if (loadResult == 0) {
447         LOGI("Loaded LPMA");
448         loaded = true;
449       } else {
450         LOGE("Failed to load LPMA with %" PRId32, loadResult);
451       }
452     } else {
453       LOGE("Failed to load LPMA due to hidl error %s",
454            hidlResult.description().c_str());
455     }
456   }
457 
458   return loaded;
459 }
460 
461 /**
462  * Unloads the LPMA use case via the SoundTrigger HAL HIDL service. This
463  * function does not indicate success/failure as it is expected that even in the
464  * event of a failure to unload, the use case will be unloaded. As long as the
465  * sound trigger HAL received the request we can be assured that the use case
466  * will be unloaded (even if it means reseting the codec or otherwise).
467  *
468  * @param lpmaHandle A handle that was previously produced by the setLpmaEnabled
469  *        function. This is the handle that is unloaded from the ST HAL to
470  *        disable LPMA.
471  */
unloadLpma(SoundModelHandle lpmaHandle)472 static void unloadLpma(SoundModelHandle lpmaHandle) {
473   LOGD("Unloading LPMA");
474 
475   if (!connectToStHalServiceLocked()) {
476     LOGE("Failed to get ST HAL service for LPMA unload");
477   } else {
478     Return<int32_t> hidlResult =
479         lpmaEnableThread.stHalService->unloadSoundModel(lpmaHandle);
480 
481     if (hidlResult.isOk()) {
482       if (hidlResult == 0) {
483         LOGI("Unloaded LPMA");
484       } else {
485         LOGE("Failed to unload LPMA with %" PRId32, int32_t(hidlResult));
486       }
487     } else {
488       LOGE("Failed to unload LPMA due to hidl error %s",
489            hidlResult.description().c_str());
490     }
491   }
492 }
493 
chreLpmaEnableThread(void * arg)494 static void *chreLpmaEnableThread(void *arg) {
495   auto *state = static_cast<LpmaEnableThreadData *>(arg);
496 
497   const useconds_t kInitialRetryDelayUs = 500000;
498   const int kRetryGrowthFactor = 2;
499   const int kRetryGrowthLimit = 5;  // Terminates at 8s retry interval.
500   const int kRetryWakeLockLimit = 10;  // Retry with a wakelock 10 times.
501 
502   int retryCount = 0;
503   useconds_t retryDelay = 0;
504   SoundModelHandle lpmaHandle;
505 
506   while (true) {
507     pthread_mutex_lock(&state->mutex);
508     if (state->currentLpmaEnabled == state->targetLpmaEnabled) {
509       retryCount = 0;
510       retryDelay = 0;
511       releaseWakeLock();  // Allow the system to suspend while waiting.
512       pthread_cond_wait(&state->cond, &state->mutex);
513       acquireWakeLock();  // Ensure the system stays up while retrying.
514     } else if (state->targetLpmaEnabled && loadLpma(&lpmaHandle)) {
515       state->currentLpmaEnabled = state->targetLpmaEnabled;
516     } else if (!state->targetLpmaEnabled) {
517       // Regardless of whether the use case fails to unload, set the
518       // currentLpmaEnabled to the targetLpmaEnabled. This will allow the next
519       // enable request to proceed. After a failure to unload occurs, the
520       // supplied handle is invalid and should not be unloaded again.
521       unloadLpma(lpmaHandle);
522       state->currentLpmaEnabled = state->targetLpmaEnabled;
523     } else {
524       // Unlock while delaying to avoid blocking the client thread. No shared
525       // state is modified here.
526       pthread_mutex_unlock(&state->mutex);
527 
528       if (retryDelay == 0) {
529         retryDelay = kInitialRetryDelayUs;
530       } else if (retryCount < kRetryGrowthLimit) {
531         retryDelay *= kRetryGrowthFactor;
532       }
533 
534       LOGD("Delaying retry %d for %uus", retryCount, retryDelay);
535       usleep(retryDelay);
536 
537       retryCount++;
538       if (retryCount > kRetryWakeLockLimit) {
539         releaseWakeLock();
540       }
541 
542       pthread_mutex_lock(&state->mutex);
543     }
544 
545     pthread_mutex_unlock(&state->mutex);
546   }
547 
548   LOGV("LPMA enable thread exited");
549   return NULL;
550 }
551 
552 /**
553  * Initializes the data shared with the LPMA enable thread and starts the
554  * thread.
555  *
556  * @param data Pointer to structure containing the (uninitialized) condition
557  *        variable and associated data passed to the LPMA enable thread.
558  * @return true on success, false otherwise.
559  */
initLpmaEnableThread(LpmaEnableThreadData * data)560 static bool initLpmaEnableThread(LpmaEnableThreadData *data) {
561   bool success = false;
562   int ret;
563 
564   if ((ret = pthread_mutex_init(&data->mutex, NULL)) != 0) {
565     LOG_ERROR("Failed to initialize lpma enable mutex", ret);
566   } else if ((ret = pthread_cond_init(&data->cond, NULL)) != 0) {
567     LOG_ERROR("Failed to initialize lpma enable condition variable", ret);
568   } else if (!start_thread(&data->thread, chreLpmaEnableThread, data)) {
569     LOGE("Couldn't start lpma enable thread");
570   } else {
571     data->currentLpmaEnabled = false;
572     data->targetLpmaEnabled = false;
573     success = true;
574   }
575 
576   return success;
577 }
578 
579 #endif  // CHRE_DAEMON_LPMA_ENABLED
580 
581 /**
582  * Sends a message to CHRE.
583  *
584  * @param clientId The client ID that this message originates from.
585  * @param data The data to pass down.
586  * @param length The size of the data to send.
587  * @return true if successful, false otherwise.
588  */
sendMessageToChre(uint16_t clientId,void * data,size_t length)589 static bool sendMessageToChre(uint16_t clientId, void *data, size_t length) {
590   constexpr size_t kMaxPayloadSize = 1024 * 1024;  // 1 MiB
591 
592   // This limitation is due to FastRPC, but there's no case where we should come
593   // close to this limit...
594   static_assert(kMaxPayloadSize <= INT32_MAX,
595                 "DSP uses 32-bit signed integers to represent message size");
596 
597   bool success = false;
598   if (length > kMaxPayloadSize) {
599     LOGE("Message too large (got %zu, max %zu bytes)", length, kMaxPayloadSize);
600   } else if (!HostProtocolHost::mutateHostClientId(data, length, clientId)) {
601     LOGE("Couldn't set host client ID in message container!");
602   } else {
603     LOGV("Delivering message from host (size %zu)", length);
604     log_buffer(static_cast<const uint8_t *>(data), length);
605     int ret = chre_slpi_deliver_message_from_host(
606         static_cast<const unsigned char *>(data), static_cast<int>(length));
607     if (ret != 0) {
608       LOGE("Failed to deliver message from host to CHRE: %d", ret);
609     } else {
610       success = true;
611     }
612   }
613 
614   return success;
615 }
616 
617 /**
618  * Loads a nanoapp by sending the nanoapp filename to the CHRE framework. This
619  * method will return after sending the request so no guarantee is made that
620  * the nanoapp is loaded until after the response is received.
621  *
622  * @param appId The ID of the nanoapp to load.
623  * @param appVersion The version of the nanoapp to load.
624  * @param appTargetApiVersion The version of the CHRE API that the app targets.
625  * @param appBinaryName The name of the binary as stored in the filesystem. This
626  *     will be used to load the nanoapp into CHRE.
627  * @param transactionId The transaction ID to use when loading.
628  * @return true if a request was successfully sent, false otherwise.
629  */
sendNanoappLoad(uint64_t appId,uint32_t appVersion,uint32_t appTargetApiVersion,const std::string & appBinaryName,uint32_t transactionId)630 static bool sendNanoappLoad(
631     uint64_t appId, uint32_t appVersion, uint32_t appTargetApiVersion,
632     const std::string& appBinaryName, uint32_t transactionId) {
633   flatbuffers::FlatBufferBuilder builder;
634   HostProtocolHost::encodeLoadNanoappRequestForFile(
635       builder, transactionId, appId, appVersion, appTargetApiVersion,
636       appBinaryName.c_str());
637 
638   bool success = sendMessageToChre(
639       kHostClientIdDaemon, builder.GetBufferPointer(), builder.GetSize());
640 
641   if (!success) {
642     LOGE("Failed to send nanoapp filename.");
643   } else {
644     gPreloadedNanoappPendingTransactionIds.push(transactionId);
645   }
646 
647   return success;
648 }
649 
650 /**
651  * Sends a preloaded nanoapp filename / metadata to CHRE.
652  *
653  * @param header The nanoapp header binary blob.
654  * @param nanoappName The filename of the nanoapp to be loaded.
655  * @param transactionId The transaction ID to use when loading the app.
656  * @return true if successful, false otherwise.
657  */
loadNanoapp(const std::vector<uint8_t> & header,const std::string & nanoappName,uint32_t transactionId)658 static bool loadNanoapp(const std::vector<uint8_t>& header,
659                         const std::string& nanoappName,
660                         uint32_t transactionId) {
661   // This struct comes from build/build_template.mk and must not be modified.
662   // Refer to that file for more details.
663   struct NanoAppBinaryHeader {
664     uint32_t headerVersion;
665     uint32_t magic;
666     uint64_t appId;
667     uint32_t appVersion;
668     uint32_t flags;
669     uint64_t hwHubType;
670     uint8_t targetChreApiMajorVersion;
671     uint8_t targetChreApiMinorVersion;
672     uint8_t reserved[6];
673   } __attribute__((packed));
674 
675   bool success = false;
676   if (header.size() != sizeof(NanoAppBinaryHeader)) {
677     LOGE("Header size mismatch");
678   } else {
679     // The header blob contains the struct above.
680     const auto *appHeader = reinterpret_cast<
681         const NanoAppBinaryHeader *>(header.data());
682 
683     // Build the target API version from major and minor.
684     uint32_t targetApiVersion = (appHeader->targetChreApiMajorVersion << 24)
685         | (appHeader->targetChreApiMinorVersion << 16);
686 
687     success = sendNanoappLoad(appHeader->appId, appHeader->appVersion,
688                               targetApiVersion, nanoappName, transactionId);
689   }
690 
691   return success;
692 }
693 
694 /**
695  * Loads the supplied file into the provided buffer.
696  *
697  * @param filename The name of the file to load.
698  * @param buffer The buffer to load into.
699  * @return true if successful, false otherwise.
700  */
readFileContents(const char * filename,std::vector<uint8_t> * buffer)701 static bool readFileContents(const char *filename,
702                              std::vector<uint8_t> *buffer) {
703   bool success = false;
704   std::ifstream file(filename, std::ios::binary | std::ios::ate);
705   if (!file) {
706     LOGE("Couldn't open file '%s': %d (%s)", filename, errno, strerror(errno));
707   } else {
708     ssize_t size = file.tellg();
709     file.seekg(0, std::ios::beg);
710 
711     buffer->resize(size);
712     if (!file.read(reinterpret_cast<char *>(buffer->data()), size)) {
713       LOGE("Couldn't read from file '%s': %d (%s)",
714            filename, errno, strerror(errno));
715     } else {
716       success = true;
717     }
718   }
719 
720   return success;
721 }
722 
723 /**
724  * Loads a preloaded nanoapp given a filename to load from. Allows the
725  * transaction to complete before the nanoapp starts so the server can start
726  * serving requests as soon as possible.
727  *
728  * @param name The filepath to load the nanoapp from.
729  * @param transactionId The transaction ID to use when loading the app.
730  */
loadPreloadedNanoapp(const std::string & name,uint32_t transactionId)731 static void loadPreloadedNanoapp(const std::string& name,
732                                  uint32_t transactionId) {
733   std::vector<uint8_t> headerBuffer;
734 
735   std::string headerFilename = std::string(name) + ".napp_header";
736   std::string nanoappFilename = std::string(name) + ".so";
737 
738   // Only send the filename itself e.g activity.so since CHRE will load from
739   // the same directory its own binary resides in.
740   nanoappFilename = nanoappFilename.substr(
741       nanoappFilename.find_last_of("/\\") + 1);
742   if (nanoappFilename.empty()) {
743     LOGE("Failed to get the name of the nanoapp %s", name.c_str());
744   } else if (readFileContents(headerFilename.c_str(), &headerBuffer)
745       && !loadNanoapp(headerBuffer, nanoappFilename, transactionId)) {
746     LOGE("Failed to load nanoapp: '%s'", name.c_str());
747   }
748 }
749 
750 /**
751  * Attempts to load all preloaded nanoapps from a config file. The config file
752  * is expected to be valid JSON with the following structure:
753  *
754  * { "nanoapps": [
755  *     "/path/to/nanoapp_1",
756  *     "/path/to/nanoapp_2"
757  * ]}
758  *
759  * The napp_header and so files will both be loaded. All errors are logged.
760  */
loadPreloadedNanoapps()761 static void loadPreloadedNanoapps() {
762   constexpr char kPreloadedNanoappsConfigPath[] =
763       "/vendor/etc/chre/preloaded_nanoapps.json";
764   std::ifstream configFileStream(kPreloadedNanoappsConfigPath);
765 
766   Json::Reader reader;
767   Json::Value config;
768   if (!configFileStream) {
769     LOGE("Failed to open config file '%s': %d (%s)",
770          kPreloadedNanoappsConfigPath, errno, strerror(errno));
771   } else if (!reader.parse(configFileStream, config)) {
772     LOGE("Failed to parse nanoapp config file");
773   } else if (!config.isMember("nanoapps")) {
774     LOGE("Malformed preloaded nanoapps config");
775   } else {
776     for (Json::ArrayIndex i = 0; i < config["nanoapps"].size(); i++) {
777       const Json::Value& nanoapp = config["nanoapps"][i];
778       loadPreloadedNanoapp(nanoapp.asString(), static_cast<uint32_t>(i));
779     }
780   }
781 }
782 
783 /**
784  * Handles a message that is directed towards the daemon.
785  *
786  * @param message The message sent to the daemon.
787  */
handleDaemonMessage(const uint8_t * message)788 static void handleDaemonMessage(const uint8_t *message) {
789   std::unique_ptr<fbs::MessageContainerT> container =
790       fbs::UnPackMessageContainer(message);
791   if (container->message.type
792           != fbs::ChreMessage::LoadNanoappResponse) {
793     LOGE("Invalid message from CHRE directed to daemon");
794   } else {
795     const auto *response = container->message.AsLoadNanoappResponse();
796     if (gPreloadedNanoappPendingTransactionIds.empty()) {
797       LOGE("Received nanoapp load response with no pending load");
798     } else if (gPreloadedNanoappPendingTransactionIds.front()
799                    != response->transaction_id) {
800       LOGE("Received nanoapp load response with ID %" PRIu32
801            " expected transaction id %" PRIu32, response->transaction_id,
802            gPreloadedNanoappPendingTransactionIds.front());
803     } else {
804       if (!response->success) {
805         LOGE("Received unsuccessful nanoapp load response with ID %" PRIu32,
806              gPreloadedNanoappPendingTransactionIds.front());
807       }
808       gPreloadedNanoappPendingTransactionIds.pop();
809     }
810   }
811 }
812 
813 /**
814  * Entry point for the thread that receives messages sent by CHRE.
815  *
816  * @return always returns NULL
817  */
chre_message_to_host_thread(void * arg)818 static void *chre_message_to_host_thread(void *arg) {
819   unsigned char messageBuffer[4096];
820   unsigned int messageLen;
821   int result = 0;
822   auto *server = static_cast<::android::chre::SocketServer *>(arg);
823 
824   while (true) {
825     messageLen = 0;
826     LOGV("Calling into chre_slpi_get_message_to_host");
827     result = chre_slpi_get_message_to_host(
828         messageBuffer, sizeof(messageBuffer), &messageLen);
829     LOGV("Got message from CHRE with size %u (result %d)", messageLen, result);
830 
831     if (result == CHRE_FASTRPC_ERROR_SHUTTING_DOWN) {
832       LOGD("CHRE shutting down, exiting CHRE->Host message thread");
833       break;
834     } else if (result == CHRE_FASTRPC_SUCCESS && messageLen > 0) {
835       log_buffer(messageBuffer, messageLen);
836       uint16_t hostClientId;
837       fbs::ChreMessage messageType;
838       if (!HostProtocolHost::extractHostClientIdAndType(
839           messageBuffer, messageLen, &hostClientId, &messageType)) {
840         LOGW("Failed to extract host client ID from message - sending "
841              "broadcast");
842         hostClientId = chre::kHostClientIdUnspecified;
843       }
844 
845       if (messageType == fbs::ChreMessage::LogMessage) {
846         parseAndEmitLogMessages(messageBuffer);
847       } else if (messageType == fbs::ChreMessage::TimeSyncRequest) {
848         sendTimeSyncMessage(true /* logOnError */);
849 #ifdef CHRE_DAEMON_LPMA_ENABLED
850       } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRequest) {
851         setLpmaState(true);
852       } else if (messageType == fbs::ChreMessage::LowPowerMicAccessRelease) {
853         setLpmaState(false);
854 #endif  // CHRE_DAEMON_LPMA_ENABLED
855       } else if (hostClientId == kHostClientIdDaemon) {
856         handleDaemonMessage(messageBuffer);
857       } else if (hostClientId == chre::kHostClientIdUnspecified) {
858         server->sendToAllClients(messageBuffer,
859                                  static_cast<size_t>(messageLen));
860       } else {
861         server->sendToClientById(messageBuffer,
862                                  static_cast<size_t>(messageLen), hostClientId);
863       }
864     } else if (!chre_shutdown_requested) {
865       LOGE("Received an unknown result and no shutdown was requested. Quitting");
866       exit(-1);
867     } else {
868       // Received an unknown result but a shutdown was requested. Break from the
869       // loop to allow the daemon to cleanup.
870       break;
871     }
872   }
873 
874   LOGV("Message to host thread exited");
875   return NULL;
876 }
877 
878 /**
879  * Entry point for the thread that blocks in a FastRPC call to monitor for
880  * abnormal exit of CHRE or reboot of the DSP.
881  *
882  * @return always returns NULL
883  */
chre_monitor_thread(void * arg)884 static void *chre_monitor_thread(void *arg) {
885   (void) arg;
886   int ret = chre_slpi_wait_on_thread_exit();
887   if (!chre_shutdown_requested) {
888     LOGE("Detected unexpected CHRE thread exit (%d)\n", ret);
889     exit(EXIT_FAILURE);
890   }
891 
892   LOGV("Monitor thread exited");
893   return NULL;
894 }
895 
896 /**
897  * Entry point for the "reverse" monitor thread, which invokes a FastRPC method
898  * to register a thread destructor, and blocks waiting on a condition variable.
899  * This allows for the code running in the DSP to detect abnormal shutdown of
900  * the host-side binary and perform graceful cleanup.
901  *
902  * @return always returns NULL
903  */
chre_reverse_monitor_thread(void * arg)904 static void *chre_reverse_monitor_thread(void *arg) {
905   struct reverse_monitor_thread_data *thread_data =
906       (struct reverse_monitor_thread_data *) arg;
907 
908   int ret = chre_slpi_initialize_reverse_monitor();
909   if (ret != CHRE_FASTRPC_SUCCESS) {
910     LOGE("Failed to initialize reverse monitor: %d", ret);
911   } else {
912     // Block here on the condition variable until the main thread notifies
913     // us to exit
914     pthread_mutex_lock(&thread_data->mutex);
915     pthread_cond_wait(&thread_data->cond, &thread_data->mutex);
916     pthread_mutex_unlock(&thread_data->mutex);
917   }
918 
919   LOGV("Reverse monitor thread exited");
920   return NULL;
921 }
922 
923 /**
924  * Initializes the data shared with the reverse monitor thread, and starts the
925  * thread.
926  *
927  * @param data Pointer to structure containing the (uninitialized) condition
928  *        variable and associated data passed to the reverse monitor thread
929  *
930  * @return true on success
931  */
init_reverse_monitor(struct reverse_monitor_thread_data * data)932 static bool init_reverse_monitor(struct reverse_monitor_thread_data *data) {
933   bool success = false;
934   int ret;
935 
936   if ((ret = pthread_mutex_init(&data->mutex, NULL)) != 0) {
937     LOG_ERROR("Failed to initialize mutex", ret);
938   } else if ((ret = pthread_cond_init(&data->cond, NULL)) != 0) {
939     LOG_ERROR("Failed to initialize condition variable", ret);
940   } else if (!start_thread(&data->thread, chre_reverse_monitor_thread, data)) {
941     LOGE("Couldn't start reverse monitor thread");
942   } else {
943     success = true;
944   }
945 
946   return success;
947 }
948 
949 /**
950  * Start a thread with default attributes, or log an error on failure
951  *
952  * @return bool true if the thread was successfully started
953  */
start_thread(pthread_t * thread_handle,thread_entry_point_f * thread_entry,void * arg)954 static bool start_thread(pthread_t *thread_handle,
955                          thread_entry_point_f *thread_entry,
956                          void *arg) {
957   int ret = pthread_create(thread_handle, NULL, thread_entry, arg);
958   if (ret != 0) {
959     LOG_ERROR("pthread_create failed", ret);
960   }
961   return (ret == 0);
962 }
963 
964 namespace {
965 
onMessageReceivedFromClient(uint16_t clientId,void * data,size_t length)966 void onMessageReceivedFromClient(uint16_t clientId, void *data, size_t length) {
967   sendMessageToChre(clientId, data, length);
968 }
969 
970 }  // anonymous namespace
971 
main()972 int main() {
973   int ret = -1;
974   pthread_t monitor_thread;
975   pthread_t msg_to_host_thread;
976 
977   struct reverse_monitor_thread_data reverse_monitor;
978   ::android::chre::SocketServer server;
979 
980 #ifdef CHRE_DAEMON_LOAD_INTO_SENSORSPD
981   remote_handle remote_handle_fd = 0xFFFFFFFF;
982   if (remote_handle_open(ITRANSPORT_PREFIX "createstaticpd:sensorspd",
983                          &remote_handle_fd)) {
984     LOGE("Failed to open remote handle for sensorspd");
985   } else {
986     LOGV("Successfully opened remote handle for sensorspd");
987   }
988 #endif  // CHRE_DAEMON_LOAD_INTO_SENSORSPD
989 
990   // Send time sync message before nanoapps start, retrying a few times
991   // in case the SLPI is not ready yet. This retry logic must be placed before
992   // any of the other FastRPC method invocations.
993   constexpr size_t kMaxNumRetries = 5;
994   if (!sendTimeSyncMessageRetry(kMaxNumRetries)) {
995     LOGE("Failed to send initial time sync message");
996   } else if (!init_reverse_monitor(&reverse_monitor)) {
997     LOGE("Couldn't initialize reverse monitor");
998 #ifdef CHRE_DAEMON_LPMA_ENABLED
999   } else if (!initLpmaEnableThread(&lpmaEnableThread)) {
1000     LOGE("Couldn't initialize LPMA enable thread");
1001 #endif  // CHRE_DAEMON_LPMA_ENABLED
1002   } else {
1003     if ((ret = chre_slpi_start_thread()) != CHRE_FASTRPC_SUCCESS) {
1004       LOGE("Failed to start CHRE: %d", ret);
1005     } else {
1006       if (!start_thread(&monitor_thread, chre_monitor_thread, NULL)) {
1007         LOGE("Couldn't start monitor thread");
1008       } else if (!start_thread(&msg_to_host_thread, chre_message_to_host_thread,
1009                                &server)) {
1010         LOGE("Couldn't start CHRE->Host message thread");
1011       } else {
1012         LOGI("CHRE started");
1013         loadPreloadedNanoapps();
1014 
1015         // TODO: take 2nd argument as command-line parameter
1016         server.run("chre", true, onMessageReceivedFromClient);
1017       }
1018 
1019       chre_shutdown_requested = true;
1020       ret = chre_slpi_stop_thread();
1021       if (ret != CHRE_FASTRPC_SUCCESS) {
1022         LOGE("Failed to stop CHRE: %d", ret);
1023       } else {
1024         // TODO: don't call pthread_join if the thread failed to start
1025         LOGV("Joining monitor thread");
1026         ret = pthread_join(monitor_thread, NULL);
1027         if (ret != 0) {
1028           LOG_ERROR("Join on monitor thread failed", ret);
1029         }
1030 
1031         LOGV("Joining reverse monitor thread");
1032         pthread_cond_signal(&reverse_monitor.cond);
1033         ret = pthread_join(reverse_monitor.thread, NULL);
1034         if (ret != 0) {
1035           LOG_ERROR("Join on reverse monitor thread failed", ret);
1036         }
1037 
1038         LOGV("Joining message to host thread");
1039         ret = pthread_join(msg_to_host_thread, NULL);
1040         if (ret != 0) {
1041           LOG_ERROR("Join on monitor thread failed", ret);
1042         }
1043 
1044         LOGI("Shutdown complete");
1045       }
1046     }
1047   }
1048 
1049   return ret;
1050 }
1051 
1052