Snap for 10338099 from dd44e1b38af3a21ec7e245033deece4e0d2cfd2b to udc-release
Change-Id: I50af16df5516d7c779a8159b04c6f0b94946b6ac
diff --git a/host/tinysys/hal/tinysys_chre_connection.cc b/host/tinysys/hal/tinysys_chre_connection.cc
index 0a02164..22ef714 100644
--- a/host/tinysys/hal/tinysys_chre_connection.cc
+++ b/host/tinysys/hal/tinysys_chre_connection.cc
@@ -80,8 +80,9 @@
return false;
}
mLogger.init();
- // launch the listener tasks
+ // launch the tasks
mMessageListener = std::thread(messageListenerTask, this);
+ mMessageSender = std::thread(messageSenderTask, this);
mStateListener = std::thread(chreStateMonitorTask, this);
mLpmaHandler.init();
return true;
@@ -138,25 +139,35 @@
}
}
+[[noreturn]] void TinysysChreConnection::messageSenderTask(
+ TinysysChreConnection *chreConnection) {
+ LOGI("Message sender task is launched.");
+ int chreFd = chreConnection->getChreFileDescriptor();
+ while (true) {
+ chreConnection->mQueue.waitForMessage();
+ ChreConnectionMessage &message = chreConnection->mQueue.front();
+ auto size =
+ TEMP_FAILURE_RETRY(write(chreFd, &message, message.getMessageSize()));
+ if (size < 0) {
+ LOGE("Failed to write to chre file descriptor. errno=%d\n", errno);
+ }
+ chreConnection->mQueue.pop();
+ }
+}
+
bool TinysysChreConnection::sendMessage(void *data, size_t length) {
if (length <= 0 || length > kMaxPayloadBytes) {
LOGE("length %zu is not within the accepted range.", length);
return false;
}
- mChreMessage->setData(data, length);
- auto size = TEMP_FAILURE_RETRY(write(mChreFileDescriptor, mChreMessage.get(),
- mChreMessage->getMessageSize()));
- if (size < 0) {
- LOGE("Failed to write to chre file descriptor. errno=%d\n", errno);
- return false;
- }
- return true;
+ return mQueue.emplace(data, length);
}
void TinysysChreConnection::handleMessageFromChre(
TinysysChreConnection *chreConnection, const unsigned char *messageBuffer,
size_t messageLen) {
- // TODO(b/267188769): Move the wake lock acquisition/release to RAII pattern.
+ // TODO(b/267188769): Move the wake lock acquisition/release to RAII
+ // pattern.
bool isWakelockAcquired =
acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock) == 0;
if (!isWakelockAcquired) {
diff --git a/host/tinysys/hal/tinysys_chre_connection.h b/host/tinysys/hal/tinysys_chre_connection.h
index 7b3dbae..e42b0c4 100644
--- a/host/tinysys/hal/tinysys_chre_connection.h
+++ b/host/tinysys/hal/tinysys_chre_connection.h
@@ -26,6 +26,8 @@
#include <unistd.h>
#include <cassert>
+#include <future>
+#include <queue>
#include <thread>
using ::android::chre::StHalLpmaHandler;
@@ -41,7 +43,6 @@
TinysysChreConnection(ChreConnectionCallback *callback)
: mCallback(callback), mLpmaHandler(/* allowed= */ true) {
mPayload = std::make_unique<uint8_t[]>(kMaxPayloadBytes);
- mChreMessage = std::make_unique<ChreConnectionMessage>();
};
~TinysysChreConnection() override {
@@ -50,6 +51,9 @@
if (mMessageListener.joinable()) {
mMessageListener.join();
}
+ if (mMessageSender.joinable()) {
+ mMessageSender.join();
+ }
if (mStateListener.joinable()) {
mStateListener.join();
}
@@ -89,6 +93,9 @@
// The path to CHRE file descriptor
static constexpr char kChreFileDescriptorPath[] = "/dev/scp_chre_manager";
+ // Max queue size for sending messages to CHRE
+ static constexpr size_t kMaxSynchronousMessageQueueSize = 64;
+
// Wrapper for a message sent to CHRE
struct ChreConnectionMessage {
// This magic number is the SCP_CHRE_MAGIC constant defined by kernel
@@ -98,7 +105,7 @@
uint32_t payloadSize = 0;
uint8_t payload[kMaxPayloadBytes];
- void setData(void *data, size_t length) {
+ ChreConnectionMessage(void *data, size_t length) {
assert(length <= kMaxPayloadBytes);
memcpy(payload, data, length);
payloadSize = static_cast<uint32_t>(length);
@@ -109,10 +116,49 @@
}
};
+ // A queue suitable for multiple producers and a single consumer.
+ class SynchronousMessageQueue {
+ public:
+ bool emplace(void *data, size_t length) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (mQueue.size() >= kMaxSynchronousMessageQueueSize) {
+ LOGE("Message queue from HAL to CHRE is full!");
+ return false;
+ }
+ mQueue.emplace(data, length);
+ mCv.notify_all();
+ return true;
+ }
+
+ void pop() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mQueue.pop();
+ }
+
+ ChreConnectionMessage &front() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ return mQueue.front();
+ }
+
+ void waitForMessage() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mCv.wait(lock, [&]() { return !mQueue.empty(); });
+ }
+
+ private:
+ std::mutex mMutex;
+ std::condition_variable mCv;
+ std::queue<ChreConnectionMessage> mQueue;
+ };
+
// The task receiving message from CHRE
[[noreturn]] static void messageListenerTask(
TinysysChreConnection *chreConnection);
+ // The task sending message to CHRE
+ [[noreturn]] static void messageSenderTask(
+ TinysysChreConnection *chreConnection);
+
// The task receiving CHRE state update
[[noreturn]] static void chreStateMonitorTask(
TinysysChreConnection *chreConnection);
@@ -130,19 +176,21 @@
// The calback function that should be implemented by HAL
ChreConnectionCallback *mCallback;
- // the message listener thread that hosts messageListenerTask
+ // the message listener thread that receives messages from CHRE
std::thread mMessageListener;
+ // the message sender thread that sends messages to CHRE
+ std::thread mMessageSender;
// the status listener thread that hosts chreStateMonitorTask
std::thread mStateListener;
// Payload received from CHRE
std::unique_ptr<uint8_t[]> mPayload;
- // message to be sent to CHRE
- std::unique_ptr<ChreConnectionMessage> mChreMessage;
-
- //! The LPMA handler to talk to the ST HAL
+ // The LPMA handler to talk to the ST HAL
StHalLpmaHandler mLpmaHandler;
+
+ // For messages sent to CHRE
+ SynchronousMessageQueue mQueue;
};
} // namespace aidl::android::hardware::contexthub