blob: 00418324ce6684b1c7951b7f9dc489f2550c4e4b [file] [log] [blame] [edit]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CHRE_EXYNOS_DAEMON_H_
#define CHRE_EXYNOS_DAEMON_H_
#include <atomic>
#include <thread>
#include "chre_host/fbs_daemon_base.h"
#include "chre_host/st_hal_lpma_handler.h"
namespace android {
namespace chre {
class ExynosDaemon : public FbsDaemonBase {
public:
ExynosDaemon();
~ExynosDaemon() {
deinit();
}
//! EXYNOS's shared memory size for CHRE <-> AP is 4KB.
static constexpr size_t kIpcMsgSizeMax = 4096;
/**
* Initializes the CHRE daemon.
*
* @return true on successful init
*/
bool init();
/**
* Starts a socket server receive loop for inbound messages.
*/
void run();
void processIncomingMsgs();
int64_t getTimeOffset(bool *success) override;
protected:
void loadPreloadedNanoapp(const std::string &directory,
const std::string &name,
uint32_t transactionId) override;
void handleDaemonMessage(const uint8_t *message) override;
bool doSendMessage(void *data, size_t length) override;
void configureLpma(bool enabled) override {
mLpmaHandler.enable(enabled);
}
private:
static constexpr char kCommsDeviceFilename[] = "/dev/nanohub_comms";
static constexpr int kInvalidFd = -1;
int mCommsReadFd = kInvalidFd;
int mCommsWriteFd = kInvalidFd;
std::thread mIncomingMsgProcessThread;
std::thread::native_handle_type mNativeThreadHandle;
std::atomic<bool> mProcessThreadRunning = false;
StHalLpmaHandler mLpmaHandler;
//! Set to the expected transaction, fragment, app ID for loading a nanoapp.
struct Transaction {
uint32_t transactionId;
uint32_t fragmentId;
uint64_t nanoappId;
};
Transaction mPreloadedNanoappPendingTransaction;
//! The mutex used to guard state between the nanoapp messaging thread
//! and loading preloaded nanoapps.
std::mutex mPreloadedNanoappsMutex;
//! The condition variable used to wait for a nanoapp to finish loading.
std::condition_variable mPreloadedNanoappsCond;
//! Set to true when a preloaded nanoapp is pending load.
bool mPreloadedNanoappPending;
/**
* Perform a graceful shutdown of the daemon
*/
void deinit();
/**
* Stops the inbound message processing thread (forcibly).
* Since the message read mechanism uses blocking system calls (poll, read),
* and since there's no timeout on the system calls (to avoid waking the AP
* up to handle timeouts), we forcibly terminate the thread on a daemon
* deinit. POSIX semantics are used since the C++20 threading interface does
* not provide an API to accomplish this.
*/
void stopMsgProcessingThread();
/**
* Sends a preloaded nanoapp to CHRE.
*
* @param header The nanoapp header binary blob.
* @param nanoapp The nanoapp binary blob.
* @param transactionId The transaction ID to use when loading the app.
* @return true if successful, false otherwise.
*/
bool loadNanoapp(const std::vector<uint8_t> &header,
const std::vector<uint8_t> &nanoapp, uint32_t transactionId);
/**
* Loads a nanoapp using fragments.
*
* @param appId The ID of the nanoapp to load.
* @param appVersion The version of the nanoapp to load.
* @param appFlags The flags specified by the nanoapp to be loaded.
* @param appTargetApiVersion The version of the CHRE API that the app
* targets.
* @param appBinary The application binary code.
* @param appSize The size of the appBinary.
* @param transactionId The transaction ID to use when loading.
* @return true if successful, false otherwise.
*/
bool sendFragmentedNanoappLoad(uint64_t appId, uint32_t appVersion,
uint32_t appFlags,
uint32_t appTargetApiVersion,
const uint8_t *appBinary, size_t appSize,
uint32_t transactionId);
bool sendFragmentAndWaitOnResponse(uint32_t transactionId,
flatbuffers::FlatBufferBuilder &builder,
uint32_t fragmentId, uint64_t appId);
/**
* Empty signal handler to handle SIGINT
*/
static void signalHandler(int /*signal*/) {}
};
} // namespace chre
} // namespace android
#endif // CHRE_EXYNOS_DAEMON_H_