aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Ishiguro <arthuri@google.com>2019-02-21 13:38:52 -0800
committerArthur Ishiguro <arthuri@google.com>2019-03-21 18:20:32 -0700
commitacd0cb60e1f439a57bd20ff63931036178e74af7 (patch)
treeeaeb8e5b0bd2da7945ac7573eee92a1dcada0467
parent401e7d19a62a553f9f77b01372a5940141121052 (diff)
downloadchre-acd0cb60e1f439a57bd20ff63931036178e74af7.tar.gz
Implements SensorRequestManager::flushAsync
Bug: 119269104 Test: Compile only Change-Id: I2c7e02dd0b0d1afe147aa0f28efb1f9164bce0ce
-rw-r--r--chre_api/include/chre_api/chre/sensor.h1
-rw-r--r--core/include/chre/core/event_loop_common.h2
-rw-r--r--core/include/chre/core/sensor_request_manager.h102
-rw-r--r--core/include/chre/core/sensor_type.h2
-rw-r--r--core/sensor_request_manager.cc157
-rw-r--r--platform/include/chre/platform/platform_sensor.h10
-rw-r--r--platform/linux/platform_sensor.cc5
-rw-r--r--platform/slpi/see/platform_sensor.cc5
-rw-r--r--platform/slpi/smgr/platform_sensor.cc5
9 files changed, 284 insertions, 5 deletions
diff --git a/chre_api/include/chre_api/chre/sensor.h b/chre_api/include/chre_api/chre/sensor.h
index e9667848..6e418d2d 100644
--- a/chre_api/include/chre_api/chre/sensor.h
+++ b/chre_api/include/chre_api/chre/sensor.h
@@ -29,6 +29,7 @@
#include <stdbool.h>
#include <stdint.h>
+#include <chre/common.h>
#include <chre/event.h>
#include <chre/sensor_types.h>
diff --git a/core/include/chre/core/event_loop_common.h b/core/include/chre/core/event_loop_common.h
index abb9ce57..df989775 100644
--- a/core/include/chre/core/event_loop_common.h
+++ b/core/include/chre/core/event_loop_common.h
@@ -42,6 +42,8 @@ enum class SystemCallbackType : uint16_t {
WifiHandleRangingEvent,
AudioAvailabilityChange,
AudioHandleHostAwake,
+ SensorFlushComplete,
+ SensorFlushTimeout,
};
//! The function signature of a system callback mirrors the CHRE event free
diff --git a/core/include/chre/core/sensor_request_manager.h b/core/include/chre/core/sensor_request_manager.h
index e4046131..621421a4 100644
--- a/core/include/chre/core/sensor_request_manager.h
+++ b/core/include/chre/core/sensor_request_manager.h
@@ -20,6 +20,9 @@
#include "chre/core/request_multiplexer.h"
#include "chre/core/sensor.h"
#include "chre/core/sensor_request.h"
+#include "chre/core/timer_pool.h"
+#include "chre/platform/system_time.h"
+#include "chre/platform/system_timer.h"
#include "chre/util/fixed_size_vector.h"
#include "chre/util/non_copyable.h"
#include "chre/util/optional.h"
@@ -129,6 +132,17 @@ class SensorRequestManager : public NonCopyable {
bool flushAsync(Nanoapp *nanoapp, uint32_t sensorHandle, const void *cookie);
/**
+ * Invoked by the PlatformSensor when a flush complete event is received for a
+ * given sensor for a request done through flushAsync(). This method can be
+ * invoked from any thread, and defers processing the event to the main CHRE
+ * event loop.
+ *
+ * @param errorCode An error code from enum chreError
+ * @param sensorType The SensorType of sensor that has completed the flush.
+ */
+ void handleFlushCompleteEvent(uint8_t errorCode, SensorType sensorType);
+
+ /**
* Prints state in a string buffer. Must only be called from the context of
* the main CHRE thread.
*
@@ -140,6 +154,25 @@ class SensorRequestManager : public NonCopyable {
size_t bufferSize) const;
private:
+ //! An internal structure to store incoming sensor flush requests
+ struct FlushRequest {
+ FlushRequest(SensorType type, uint32_t id, const void *cookiePtr) {
+ sensorType = type;
+ nanoappInstanceId = id;
+ cookie = cookiePtr;
+ }
+
+ //! The sensor type the flush request is for.
+ SensorType sensorType;
+ //! The ID of the nanoapp that requested the flush.
+ uint32_t nanoappInstanceId;
+ //! The opaque pointer provided in flushAsync().
+ const void *cookie;
+ //! The timestamp at which this request should complete.
+ Nanoseconds deadlineTimestamp = SystemTime::getMonotonicTime() +
+ Nanoseconds(CHRE_SENSOR_FLUSH_COMPLETE_TIMEOUT_NS);
+ };
+
/**
* This allows tracking the state of a sensor with the various requests for it
* and can trigger a change in mode/rate/latency when required.
@@ -261,6 +294,22 @@ class SensorRequestManager : public NonCopyable {
*/
bool removeAll();
+ /**
+ * Makes a specified flush request for this sensor, and sets the timeout
+ * timer appropriately. If there already is a pending flush request, then
+ * this method does nothing.
+ *
+ * @param request the request to make
+ *
+ * @return An error code from enum chreError
+ */
+ uint8_t makeFlushRequest(const FlushRequest& request);
+
+ /**
+ * Cancels a timeout timer for a pending flush request.
+ */
+ void cancelFlushTimer();
+
private:
//! The sensor associated with this request multiplexer. If this Optional
//! container does not have a value, then the platform does not support this
@@ -269,10 +318,61 @@ class SensorRequestManager : public NonCopyable {
//! The request multiplexer for this sensor.
RequestMultiplexer<SensorRequest> mMultiplexer;
+
+ //! The timeout timer handle for the current flush request.
+ TimerHandle mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
+
+ /**
+ * @return true if a flush through makeFlushRequest is pending.
+ */
+ inline bool isFlushRequestPending() const {
+ return mFlushRequestTimerHandle != CHRE_TIMER_INVALID;
+ }
};
- //! The list of sensor requests
+ //! The list of sensor requests.
FixedSizeVector<SensorRequests, getSensorTypeCount()> mSensorRequests;
+
+ //! A queue of flush requests made by nanoapps.
+ static constexpr size_t kMaxFlushRequests = 16;
+ FixedSizeVector<FlushRequest, kMaxFlushRequests> mFlushRequestQueue;
+
+ /**
+ * Helper function to convert SensorType to SensorRequests.
+ */
+ SensorRequests& getSensorRequests(SensorType sensorType) {
+ size_t index = getSensorTypeArrayIndex(sensorType);
+ return mSensorRequests[index];
+ }
+
+ /**
+ * Posts an event to a nanoapp indicating the completion of a flush request.
+ *
+ * @param sensorHandle The handle of the sensor for this event.
+ * @param errorCode An error code from enum chreError
+ * @param request The corresponding FlushRequest.
+ */
+ void postFlushCompleteEvent(
+ uint32_t sensorHandle, uint8_t errorCode, const FlushRequest& request);
+
+ /**
+ * Dispatches the next flush request for the given sensor. If there are no
+ * more pending flush requests, this method does nothing.
+ *
+ * @param sensorHandle The handle of the sensor to apply a request for.
+ * @param sensorType The corresponding sensor type.
+ */
+ void dispatchNextFlushRequest(uint32_t sensorHandle, SensorType sensorType);
+
+ /**
+ * Handles a complete event for a sensor flush requested through flushAsync.
+ * See handleFlushCompleteEvent which may be called from any thread. This
+ * method is intended to be invoked on the CHRE event loop thread.
+ *
+ * @param errorCode An error code from enum chreError
+ * @param sensorType The SensorType of sensor that has completed the flush.
+ */
+ void handleFlushCompleteEventSync(uint8_t errorCode, SensorType sensorType);
};
} // namespace chre
diff --git a/core/include/chre/core/sensor_type.h b/core/include/chre/core/sensor_type.h
index ed8112f3..30b9f96a 100644
--- a/core/include/chre/core/sensor_type.h
+++ b/core/include/chre/core/sensor_type.h
@@ -38,7 +38,7 @@ union ChreSensorData {
* specification. The details of these sensors are left to the CHRE API
* sensor definitions.
*/
-enum class SensorType {
+enum class SensorType : uint8_t {
Unknown,
Accelerometer,
InstantMotion,
diff --git a/core/sensor_request_manager.cc b/core/sensor_request_manager.cc
index dcd5dcc8..3f9e1115 100644
--- a/core/sensor_request_manager.cc
+++ b/core/sensor_request_manager.cc
@@ -16,9 +16,9 @@
#include "chre/core/sensor_request_manager.h"
+#include "chre_api/chre/version.h"
#include "chre/core/event_loop_manager.h"
#include "chre/platform/fatal_error.h"
-#include "chre_api/chre/version.h"
#include "chre/util/system/debug_dump.h"
namespace chre {
@@ -51,6 +51,13 @@ bool isSensorRequestValid(const Sensor& sensor,
return success;
}
+void flushTimerCallback(uint16_t /* eventType */, void * /* data */) {
+ // TODO: Fatal error here since some platforms may not be able to handle
+ // timeouts gracefully. Modify this implementation to drop flush
+ // requests and handle stale responses in the future appropriately.
+ FATAL_ERROR("Flush request timed out");
+}
+
} // namespace
SensorRequestManager::SensorRequestManager() {
@@ -296,8 +303,58 @@ const DynamicVector<SensorRequest>& SensorRequestManager::getRequests(
bool SensorRequestManager::flushAsync(
Nanoapp *nanoapp, uint32_t sensorHandle, const void *cookie) {
- // TODO: Implement this
- return false;
+ bool success = false;
+
+ uint32_t nanoappInstanceId = nanoapp->getInstanceId();
+ SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
+ // NOTE: One-shot sensors do not support flush per API
+ if (sensorType == SensorType::Unknown || sensorTypeIsOneShot(sensorType)) {
+ LOGE("Cannot flush for sensor type %" PRIu32,
+ static_cast<uint32_t>(sensorType));
+ } else if (mFlushRequestQueue.full()) {
+ LOG_OOM();
+ } else {
+ mFlushRequestQueue.emplace_back(sensorType, nanoappInstanceId, cookie);
+ size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
+ success = (mSensorRequests[sensorIndex].makeFlushRequest(
+ mFlushRequestQueue.back()) == CHRE_ERROR_NONE);
+ if (!success) {
+ mFlushRequestQueue.pop_back();
+ }
+ }
+
+ return success;
+}
+
+void SensorRequestManager::handleFlushCompleteEvent(
+ uint8_t errorCode, SensorType sensorType) {
+ struct CallbackState {
+ uint8_t errorCode;
+ SensorType sensorType;
+ };
+
+ // Enables passing data through void pointer to avoid allocation.
+ union NestedCallbackState {
+ void *eventData;
+ CallbackState callbackState;
+ };
+ static_assert(sizeof(NestedCallbackState) == sizeof(void *),
+ "Size of NestedCallbackState must equal that of void *");
+
+ NestedCallbackState state = {};
+ state.callbackState.errorCode = errorCode;
+ state.callbackState.sensorType = sensorType;
+
+ auto callback = [](uint16_t /* eventType */, void *eventData) {
+ NestedCallbackState state;
+ state.eventData = eventData;
+ EventLoopManagerSingleton::get()->getSensorRequestManager()
+ .handleFlushCompleteEventSync(state.callbackState.errorCode,
+ state.callbackState.sensorType);
+ };
+
+ EventLoopManagerSingleton::get()->deferCallback(
+ SystemCallbackType::SensorFlushComplete, state.eventData, callback);
}
void SensorRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
@@ -320,6 +377,61 @@ void SensorRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
}
}
+void SensorRequestManager::postFlushCompleteEvent(
+ uint32_t sensorHandle, uint8_t errorCode, const FlushRequest& request) {
+ auto *event = memoryAlloc<chreSensorFlushCompleteEvent>();
+ if (event == nullptr) {
+ LOG_OOM();
+ } else {
+ event->sensorHandle = sensorHandle;
+ event->errorCode = errorCode;
+ event->cookie = request.cookie;
+ memset(event->reserved, 0, sizeof(event->reserved));
+
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
+ CHRE_EVENT_SENSOR_FLUSH_COMPLETE, event, freeEventDataCallback,
+ kSystemInstanceId, request.nanoappInstanceId);
+ }
+}
+
+void SensorRequestManager::dispatchNextFlushRequest(
+ uint32_t sensorHandle, SensorType sensorType) {
+ SensorRequests& requests = getSensorRequests(sensorType);
+
+ for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
+ const FlushRequest& request = mFlushRequestQueue[i];
+ if (request.sensorType == sensorType) {
+ uint8_t newRequestErrorCode = requests.makeFlushRequest(request);
+ if (newRequestErrorCode == CHRE_ERROR_NONE) {
+ break;
+ } else {
+ postFlushCompleteEvent(sensorHandle, newRequestErrorCode, request);
+ mFlushRequestQueue.erase(i);
+ i--;
+ }
+ }
+ }
+}
+
+void SensorRequestManager::handleFlushCompleteEventSync(
+ uint8_t errorCode, SensorType sensorType) {
+ for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
+ const FlushRequest& request = mFlushRequestQueue[i];
+ if (request.sensorType == sensorType) {
+ uint32_t sensorHandle;
+ if (getSensorHandle(sensorType, &sensorHandle)) {
+ SensorRequests& requests = getSensorRequests(sensorType);
+ requests.cancelFlushTimer();
+
+ postFlushCompleteEvent(sensorHandle, errorCode, request);
+ mFlushRequestQueue.erase(i);
+ dispatchNextFlushRequest(sensorHandle, sensorType);
+ }
+ break;
+ }
+ }
+}
+
const SensorRequest *SensorRequestManager::SensorRequests::find(
uint32_t instanceId, size_t *index) const {
CHRE_ASSERT(index);
@@ -441,4 +553,43 @@ bool SensorRequestManager::SensorRequests::removeAll() {
return success;
}
+uint8_t SensorRequestManager::SensorRequests::makeFlushRequest(
+ const FlushRequest& request) {
+ uint8_t errorCode = CHRE_ERROR;
+ if (!isSensorSupported()) {
+ LOGE("Cannot flush on unsupported sensor");
+ } else if (mMultiplexer.getRequests().size() == 0) {
+ LOGE("Cannot flush on disabled sensor");
+ } else if (!isFlushRequestPending()) {
+ Nanoseconds now = SystemTime::getMonotonicTime();
+ Nanoseconds deadline = request.deadlineTimestamp;
+ if (now >= deadline) {
+ LOGE("Flush sensor %" PRIu32 " failed for nanoapp ID %" PRIu32
+ ": deadline exceeded", static_cast<uint32_t>(request.sensorType),
+ request.nanoappInstanceId);
+ errorCode = CHRE_ERROR_TIMEOUT;
+ } else if (mSensor->flushAsync()) {
+ errorCode = CHRE_ERROR_NONE;
+ Nanoseconds delay = deadline - now;
+ mFlushRequestTimerHandle =
+ EventLoopManagerSingleton::get()->setDelayedCallback(
+ SystemCallbackType::SensorFlushTimeout, nullptr /* data */,
+ flushTimerCallback, delay);
+ }
+ } else {
+ // Flush request will be made once the pending request is completed.
+ // Return true so that the nanoapp can wait for a result through the
+ // CHRE_EVENT_SENSOR_FLUSH_COMPLETE event.
+ errorCode = CHRE_ERROR_NONE;
+ }
+
+ return errorCode;
+}
+
+void SensorRequestManager::SensorRequests::cancelFlushTimer() {
+ EventLoopManagerSingleton::get()->cancelDelayedCallback(
+ mFlushRequestTimerHandle);
+ mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
+}
+
} // namespace chre
diff --git a/platform/include/chre/platform/platform_sensor.h b/platform/include/chre/platform/platform_sensor.h
index 87d37ed4..a430b376 100644
--- a/platform/include/chre/platform/platform_sensor.h
+++ b/platform/include/chre/platform/platform_sensor.h
@@ -95,6 +95,16 @@ class PlatformSensor : public PlatformSensorBase,
*/
bool getSamplingStatus(struct chreSensorSamplingStatus *status) const;
+ /**
+ * Makes a sensor flush request for a nanoapp asynchronously. When a flush
+ * request made by this method is completed (i.e. all pending samples are
+ * posted to the CHRE event queue), PlatformSensor should invoke
+ * SensorRequestManager::handleFlushCompleteEvent().
+ *
+ * @return true if the request was accepted.
+ */
+ bool flushAsync();
+
protected:
/**
* Default constructor that puts this instance in an unspecified state.
diff --git a/platform/linux/platform_sensor.cc b/platform/linux/platform_sensor.cc
index 83589a32..83bfd303 100644
--- a/platform/linux/platform_sensor.cc
+++ b/platform/linux/platform_sensor.cc
@@ -50,6 +50,11 @@ bool PlatformSensor::applyRequest(const SensorRequest& request) {
return false;
}
+bool PlatformSensor::flushAsync() {
+ // TODO: Implement this
+ return false;
+}
+
SensorType PlatformSensor::getSensorType() const {
// TODO: Implement this.
return SensorType::Unknown;
diff --git a/platform/slpi/see/platform_sensor.cc b/platform/slpi/see/platform_sensor.cc
index 5898fe66..3ebeb9af 100644
--- a/platform/slpi/see/platform_sensor.cc
+++ b/platform/slpi/see/platform_sensor.cc
@@ -700,6 +700,11 @@ bool PlatformSensor::applyRequest(const SensorRequest& request) {
return success;
}
+bool PlatformSensor::flushAsync() {
+ // TODO: Implement this
+ return false;
+}
+
SensorType PlatformSensor::getSensorType() const {
return mSensorType;
}
diff --git a/platform/slpi/smgr/platform_sensor.cc b/platform/slpi/smgr/platform_sensor.cc
index c8847e13..944301af 100644
--- a/platform/slpi/smgr/platform_sensor.cc
+++ b/platform/slpi/smgr/platform_sensor.cc
@@ -1451,6 +1451,11 @@ bool PlatformSensor::applyRequest(const SensorRequest& request) {
return success;
}
+bool PlatformSensor::flushAsync() {
+ // TODO: Implement this
+ return false;
+}
+
SensorType PlatformSensor::getSensorType() const {
return getSensorTypeFromSensorId(this->sensorId, this->dataType,
this->calType);