1 /* 2 * Copyright (C) 2022 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 #ifndef CHRE_EXYNOS_DAEMON_H_ 18 #define CHRE_EXYNOS_DAEMON_H_ 19 20 #include <atomic> 21 #include <thread> 22 23 #include "chre_host/fbs_daemon_base.h" 24 #include "chre_host/st_hal_lpma_handler.h" 25 26 namespace android { 27 namespace chre { 28 29 class ExynosDaemon : public FbsDaemonBase { 30 public: 31 ExynosDaemon(); ~ExynosDaemon()32 ~ExynosDaemon() { 33 deinit(); 34 } 35 36 //! EXYNOS's shared memory size for CHRE <-> AP is 4KB. 37 static constexpr size_t kIpcMsgSizeMax = 4096; 38 39 /** 40 * Initializes the CHRE daemon. 41 * 42 * @return true on successful init 43 */ 44 bool init(); 45 46 /** 47 * Starts a socket server receive loop for inbound messages. 48 */ 49 void run(); 50 51 void processIncomingMsgs(); 52 53 int64_t getTimeOffset(bool *success) override; 54 55 protected: 56 void loadPreloadedNanoapp(const std::string &directory, 57 const std::string &name, 58 uint32_t transactionId) override; 59 void handleDaemonMessage(const uint8_t *message) override; 60 bool doSendMessage(void *data, size_t length) override; 61 configureLpma(bool enabled)62 void configureLpma(bool enabled) override { 63 mLpmaHandler.enable(enabled); 64 } 65 66 private: 67 static constexpr char kCommsDeviceFilename[] = "/dev/nanohub_comms"; 68 static constexpr int kInvalidFd = -1; 69 70 int mCommsReadFd = kInvalidFd; 71 int mCommsWriteFd = kInvalidFd; 72 std::thread mIncomingMsgProcessThread; 73 std::thread::native_handle_type mNativeThreadHandle; 74 std::atomic<bool> mProcessThreadRunning = false; 75 76 StHalLpmaHandler mLpmaHandler; 77 78 //! Set to the expected transaction, fragment, app ID for loading a nanoapp. 79 struct Transaction { 80 uint32_t transactionId; 81 uint32_t fragmentId; 82 uint64_t nanoappId; 83 }; 84 Transaction mPreloadedNanoappPendingTransaction; 85 86 //! The mutex used to guard state between the nanoapp messaging thread 87 //! and loading preloaded nanoapps. 88 std::mutex mPreloadedNanoappsMutex; 89 90 //! The condition variable used to wait for a nanoapp to finish loading. 91 std::condition_variable mPreloadedNanoappsCond; 92 93 //! Set to true when a preloaded nanoapp is pending load. 94 bool mPreloadedNanoappPending; 95 96 /** 97 * Perform a graceful shutdown of the daemon 98 */ 99 void deinit(); 100 101 /** 102 * Stops the inbound message processing thread (forcibly). 103 * Since the message read mechanism uses blocking system calls (poll, read), 104 * and since there's no timeout on the system calls (to avoid waking the AP 105 * up to handle timeouts), we forcibly terminate the thread on a daemon 106 * deinit. POSIX semantics are used since the C++20 threading interface does 107 * not provide an API to accomplish this. 108 */ 109 void stopMsgProcessingThread(); 110 111 /** 112 * Sends a preloaded nanoapp to CHRE. 113 * 114 * @param header The nanoapp header binary blob. 115 * @param nanoapp The nanoapp binary blob. 116 * @param transactionId The transaction ID to use when loading the app. 117 * @return true if successful, false otherwise. 118 */ 119 bool loadNanoapp(const std::vector<uint8_t> &header, 120 const std::vector<uint8_t> &nanoapp, uint32_t transactionId); 121 122 /** 123 * Loads a nanoapp using fragments. 124 * 125 * @param appId The ID of the nanoapp to load. 126 * @param appVersion The version of the nanoapp to load. 127 * @param appFlags The flags specified by the nanoapp to be loaded. 128 * @param appTargetApiVersion The version of the CHRE API that the app 129 * targets. 130 * @param appBinary The application binary code. 131 * @param appSize The size of the appBinary. 132 * @param transactionId The transaction ID to use when loading. 133 * @return true if successful, false otherwise. 134 */ 135 bool sendFragmentedNanoappLoad(uint64_t appId, uint32_t appVersion, 136 uint32_t appFlags, 137 uint32_t appTargetApiVersion, 138 const uint8_t *appBinary, size_t appSize, 139 uint32_t transactionId); 140 141 bool sendFragmentAndWaitOnResponse(uint32_t transactionId, 142 flatbuffers::FlatBufferBuilder &builder, 143 uint32_t fragmentId, uint64_t appId); 144 145 /** 146 * Empty signal handler to handle SIGINT 147 */ signalHandler(int)148 static void signalHandler(int /*signal*/) {} 149 }; 150 151 } // namespace chre 152 } // namespace android 153 154 #endif // CHRE_EXYNOS_DAEMON_H_ 155