Merge tag 'android-security-10.0.0_r53' into int/10/fp2
Android security 10.0.0 release 53
* tag 'android-security-10.0.0_r53':
Revert "Add wakelocks to audio retries"
Change-Id: Id8c0113f178eb64d149e8e450e89dbb7acd8f046
diff --git a/Makefile b/Makefile
index 5943409..0675834 100644
--- a/Makefile
+++ b/Makefile
@@ -102,6 +102,8 @@
include $(CHRE_PREFIX)/build/variant/google_hexagonv65_adsp-see-uimg.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv65_slpi-see.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv65_slpi-see-uimg.mk
+include $(CHRE_PREFIX)/build/variant/google_hexagonv66_adsp-see.mk
+include $(CHRE_PREFIX)/build/variant/google_hexagonv66_adsp-see-uimg.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv66_slpi-see.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv66_slpi-see-uimg.mk
include $(CHRE_PREFIX)/build/variant/google_x86_linux.mk
diff --git a/build/nanoapp/app.mk b/build/nanoapp/app.mk
index 1452d7e..25f7791 100644
--- a/build/nanoapp/app.mk
+++ b/build/nanoapp/app.mk
@@ -107,6 +107,8 @@
GOOGLE_HEXAGONV65_ADSP-SEE-UIMG_SRCS += $(DSO_SUPPORT_LIB_SRCS)
GOOGLE_HEXAGONV65_SLPI-SEE_SRCS += $(DSO_SUPPORT_LIB_SRCS)
GOOGLE_HEXAGONV65_SLPI-SEE-UIMG_SRCS += $(DSO_SUPPORT_LIB_SRCS)
+GOOGLE_HEXAGONV66_ADSP-SEE_SRCS += $(DSO_SUPPORT_LIB_SRCS)
+GOOGLE_HEXAGONV66_ADSP-SEE-UIMG_SRCS += $(DSO_SUPPORT_LIB_SRCS)
GOOGLE_HEXAGONV66_SLPI-SEE_SRCS += $(DSO_SUPPORT_LIB_SRCS)
GOOGLE_HEXAGONV66_SLPI-SEE-UIMG_SRCS += $(DSO_SUPPORT_LIB_SRCS)
GOOGLE_ARM64_ANDROID_SRCS += $(DSO_SUPPORT_LIB_SRCS)
@@ -134,6 +136,8 @@
include $(CHRE_PREFIX)/build/variant/google_hexagonv65_adsp-see-uimg.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv65_slpi-see.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv65_slpi-see-uimg.mk
+include $(CHRE_PREFIX)/build/variant/google_hexagonv66_adsp-see.mk
+include $(CHRE_PREFIX)/build/variant/google_hexagonv66_adsp-see-uimg.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv66_slpi-see.mk
include $(CHRE_PREFIX)/build/variant/google_hexagonv66_slpi-see-uimg.mk
include $(CHRE_PREFIX)/build/variant/google_x86_linux.mk
diff --git a/build/variant/google_hexagonv66_adsp-see-uimg.mk b/build/variant/google_hexagonv66_adsp-see-uimg.mk
new file mode 100644
index 0000000..5777cb3
--- /dev/null
+++ b/build/variant/google_hexagonv66_adsp-see-uimg.mk
@@ -0,0 +1,42 @@
+#
+# Google CHRE Reference Implementation for Hexagon v66 Architecture on ADSP
+#
+
+include $(CHRE_PREFIX)/build/clean_build_template_args.mk
+
+TARGET_NAME = google_hexagonv66_adsp-see-uimg
+# Sized based on the buffer allocated in the host daemon (4096 bytes), minus
+# FlatBuffer overhead (max 80 bytes), minus some extra space to make a nice
+# round number and allow for addition of new fields to the FlatBuffer
+TARGET_CFLAGS = -DCHRE_MESSAGE_TO_HOST_MAX_SIZE=4000
+TARGET_CFLAGS += -DUIMG_DL_VER_MAJOR=2
+TARGET_CFLAGS += -DCHRE_SLPI_UIMG_ENABLED
+TARGET_CFLAGS += -DCHRE_THREAD_UTIL_ENABLED
+TARGET_CFLAGS += $(GOOGLE_HEXAGONV66_ADSP-SEE-UIMG_CFLAGS)
+TARGET_VARIANT_SRCS = $(GOOGLE_HEXAGONV66_ADSP-SEE-UIMG_SRCS)
+TARGET_SO_LATE_LIBS = $(GOOGLE_HEXAGONV66_ADSP-SEE-UIMG_LATE_LIBS)
+TARGET_PLATFORM_ID = 0x476f6f676c000007
+HEXAGON_ARCH = v66
+
+TARGET_CFLAGS += $(SLPI_CFLAGS)
+TARGET_VARIANT_SRCS += $(SLPI_SRCS)
+
+# Add SLPI/SEE-specific compiler flags and source files
+TARGET_CFLAGS += $(SLPI_SEE_CFLAGS)
+TARGET_CFLAGS += $(SLPI_SEE_QSK_CFLAGS)
+TARGET_VARIANT_SRCS += $(SLPI_SEE_SRCS)
+TARGET_VARIANT_SRCS += $(SLPI_SEE_QSK_SRCS)
+
+# Enable uImage support.
+TARGET_VARIANT_SRCS += $(SYS_SUPPORT_PATH)/qcom/uimg_dl_ver.c
+TARGET_SO_LDFLAGS += --script=$(SYS_SUPPORT_PATH)/qcom/uimage_v2.lcs
+
+ifneq ($(filter $(TARGET_NAME)% all, $(MAKECMDGOALS)),)
+ifneq ($(IS_NANOAPP_BUILD),)
+TARGET_SO_LATE_LIBS += $(CHRE_PREFIX)/build/app_support/google_slpi/libchre_slpi_skel.so
+include $(CHRE_PREFIX)/build/nanoapp/google_slpi.mk
+endif
+
+include $(CHRE_PREFIX)/build/arch/hexagon.mk
+include $(CHRE_PREFIX)/build/build_template.mk
+endif
diff --git a/build/variant/google_hexagonv66_adsp-see.mk b/build/variant/google_hexagonv66_adsp-see.mk
new file mode 100644
index 0000000..b1d0c6d
--- /dev/null
+++ b/build/variant/google_hexagonv66_adsp-see.mk
@@ -0,0 +1,36 @@
+#
+# Google CHRE Reference Implementation for Hexagon v66 Architecture on ADSP
+#
+
+include $(CHRE_PREFIX)/build/clean_build_template_args.mk
+
+TARGET_NAME = google_hexagonv66_adsp-see
+# Sized based on the buffer allocated in the host daemon (4096 bytes), minus
+# FlatBuffer overhead (max 80 bytes), minus some extra space to make a nice
+# round number and allow for addition of new fields to the FlatBuffer
+TARGET_CFLAGS = -DCHRE_MESSAGE_TO_HOST_MAX_SIZE=4000
+TARGET_CFLAGS += -DCHRE_THREAD_UTIL_ENABLED
+TARGET_CFLAGS += $(GOOGLE_HEXAGONV66_ADSP-SEE_CFLAGS)
+TARGET_VARIANT_SRCS = $(GOOGLE_HEXAGONV66_ADSP-SEE_SRCS)
+TARGET_SO_LATE_LIBS = $(GOOGLE_HEXAGONV66_ADSP-SEE_LATE_LIBS)
+TARGET_PLATFORM_ID = 0x476f6f676c000007
+HEXAGON_ARCH = v66
+
+TARGET_CFLAGS += $(SLPI_CFLAGS)
+TARGET_VARIANT_SRCS += $(SLPI_SRCS)
+
+# Add SLPI/SEE-specific compiler flags and source files
+TARGET_CFLAGS += $(SLPI_SEE_CFLAGS)
+TARGET_CFLAGS += $(SLPI_SEE_QMI_CFLAGS)
+TARGET_VARIANT_SRCS += $(SLPI_SEE_SRCS)
+TARGET_VARIANT_SRCS += $(SLPI_SEE_QMI_SRCS)
+
+ifneq ($(filter $(TARGET_NAME)% all, $(MAKECMDGOALS)),)
+ifneq ($(IS_NANOAPP_BUILD),)
+TARGET_SO_LATE_LIBS += $(CHRE_PREFIX)/build/app_support/google_slpi/libchre_slpi_skel.so
+include $(CHRE_PREFIX)/build/nanoapp/google_slpi.mk
+endif
+
+include $(CHRE_PREFIX)/build/arch/hexagon.mk
+include $(CHRE_PREFIX)/build/build_template.mk
+endif
diff --git a/chre_api/include/chre_api/chre/sensor.h b/chre_api/include/chre_api/chre/sensor.h
index 7985e9a..3a1f99e 100644
--- a/chre_api/include/chre_api/chre/sensor.h
+++ b/chre_api/include/chre_api/chre/sensor.h
@@ -972,6 +972,11 @@
* CHRE_EVENT_SENSOR_FLUSH_COMPLETE events received must equal the number of
* flush requests made.
*
+ * If a sensor request is disabled after a flush request is made through this
+ * method but before the flush operation is completed, the nanoapp will receive
+ * a CHRE_EVENT_SENSOR_FLUSH_COMPLETE with the error code
+ * CHRE_ERROR_FUNCTION_DISABLED for any pending flush requests.
+ *
* Starting with CHRE API v1.3, implementations must support this capability
* across all exposed sensor types.
*
diff --git a/core/audio_request_manager.cc b/core/audio_request_manager.cc
index a4a4f2e..7e162e7 100644
--- a/core/audio_request_manager.cc
+++ b/core/audio_request_manager.cc
@@ -66,6 +66,14 @@
void AudioRequestManager::handleAudioDataEvent(
const struct chreAudioDataEvent *audioDataEvent) {
+ uint32_t handle = audioDataEvent->handle;
+ if (handle >= mAudioRequestLists.size()) {
+ LOGE("Received audio event for unknown handle %" PRIu32, handle);
+ } else {
+ mAudioRequestLists[handle].lastEventTimestamp
+ = SystemTime::getMonotonicTime();
+ }
+
auto callback = [](uint16_t /* eventType */, void *eventData) {
auto *event = static_cast<struct chreAudioDataEvent *>(eventData);
EventLoopManagerSingleton::get()->getAudioRequestManager()
@@ -112,13 +120,17 @@
uint32_t handle = static_cast<uint32_t>(i);
struct chreAudioSource source;
mPlatformAudio.getAudioSource(handle, &source);
+
+ Nanoseconds timeSinceLastAudioEvent = SystemTime::getMonotonicTime()
+ - mAudioRequestLists[i].lastEventTimestamp;
debugDumpPrint(buffer, bufferPos, bufferSize,
- " handle=%" PRIu32 ", name=\"%s\", sampleRate=%" PRIu32
- ", buffer(ms)=[%" PRIu64 ",%" PRIu64 "], format=%" PRIu8 "\n",
- handle, source.name, source.sampleRate,
+ " handle=%" PRIu32 ", name=\"%s\", available=%d, sampleRate=%" PRIu32
+ ", buffer(ms)=[%" PRIu64 ",%" PRIu64 "], format=%" PRIu8
+ ", timeSinceLastAudioEvent(ms)=%" PRIu64 "\n",
+ handle, source.name, mAudioRequestLists[i].available, source.sampleRate,
Milliseconds(Nanoseconds(source.minBufferDuration)).getMilliseconds(),
Milliseconds(Nanoseconds(source.maxBufferDuration)).getMilliseconds(),
- source.format);
+ source.format, Milliseconds(timeSinceLastAudioEvent).getMilliseconds());
for (const auto& request : mAudioRequestLists[i].requests) {
for (const auto& instanceId : request.instanceIds) {
@@ -380,9 +392,9 @@
event->status.enabled = true;
event->status.suspended = !available;
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_AUDIO_SAMPLING_CHANGE, event,
- freeEventDataCallback, kSystemInstanceId, instanceId);
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_AUDIO_SAMPLING_CHANGE, event, freeEventDataCallback,
+ instanceId);
}
void AudioRequestManager::postAudioDataEventFatal(
@@ -392,11 +404,9 @@
LOGW("Received audio data event for no clients");
mPlatformAudio.releaseAudioDataEvent(event);
} else {
- for (const auto& instanceId : instanceIds) {
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_AUDIO_DATA, event,
- freeAudioDataEventCallback,
- kSystemInstanceId, instanceId);
+ for (const auto &instanceId : instanceIds) {
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_AUDIO_DATA, event, freeAudioDataEventCallback, instanceId);
}
mAudioDataEventRefCounts.emplace_back(
diff --git a/core/event.cc b/core/event.cc
index ef87b66..298463b 100644
--- a/core/event.cc
+++ b/core/event.cc
@@ -19,10 +19,11 @@
namespace chre {
-Event::Event(uint16_t eventType_, void *eventData_,
- chreEventCompleteFunction *freeCallback_,
+Event::Event(uint16_t eventType_, uint16_t receivedTimeMillis_,
+ void *eventData_, chreEventCompleteFunction *freeCallback_,
uint32_t senderInstanceId_, uint32_t targetInstanceId_)
- : eventType(eventType_), eventData(eventData_), freeCallback(freeCallback_),
+ : eventType(eventType_), receivedTimeMillis(receivedTimeMillis_),
+ eventData(eventData_), freeCallback(freeCallback_),
senderInstanceId(senderInstanceId_),
targetInstanceId(targetInstanceId_) {}
diff --git a/core/event_loop.cc b/core/event_loop.cc
index a634298..5fdfd4b 100644
--- a/core/event_loop.cc
+++ b/core/event_loop.cc
@@ -22,9 +22,11 @@
#include "chre/platform/context.h"
#include "chre/platform/fatal_error.h"
#include "chre/platform/log.h"
+#include "chre/platform/system_time.h"
#include "chre/util/conditional_lock_guard.h"
#include "chre/util/lock_guard.h"
#include "chre/util/system/debug_dump.h"
+#include "chre/util/time.h"
#include "chre_api/chre/version.h"
namespace chre {
@@ -242,15 +244,14 @@
return unloaded;
}
-bool EventLoop::postEvent(uint16_t eventType, void *eventData,
- chreEventCompleteFunction *freeCallback, uint32_t senderInstanceId,
- uint32_t targetInstanceId) {
+bool EventLoop::postEventOrDie(uint16_t eventType, void *eventData,
+ chreEventCompleteFunction *freeCallback,
+ uint32_t targetInstanceId) {
bool success = false;
- if (mRunning && (senderInstanceId == kSystemInstanceId ||
- mEventPool.getFreeBlockCount() > kMinReservedSystemEventCount)) {
+ if (mRunning) {
success = allocateAndPostEvent(eventType, eventData, freeCallback,
- senderInstanceId,targetInstanceId);
+ kSystemInstanceId, targetInstanceId);
if (!success) {
// This can only happen if the event is a system event type. This
// postEvent method will fail if a non-system event is posted when the
@@ -262,16 +263,21 @@
return success;
}
-bool EventLoop::postEventOrFree(uint16_t eventType, void *eventData,
+bool EventLoop::postLowPriorityEventOrFree(
+ uint16_t eventType, void *eventData,
chreEventCompleteFunction *freeCallback, uint32_t senderInstanceId,
uint32_t targetInstanceId) {
bool success = false;
if (mRunning) {
- success = allocateAndPostEvent(eventType, eventData, freeCallback,
- senderInstanceId,targetInstanceId);
+ if (mEventPool.getFreeBlockCount() > kMinReservedHighPriorityEventCount) {
+ success = allocateAndPostEvent(eventType, eventData, freeCallback,
+ senderInstanceId, targetInstanceId);
+ }
if (!success) {
- freeCallback(eventType, eventData);
+ if (freeCallback != nullptr) {
+ freeCallback(eventType, eventData);
+ }
LOGE("Failed to allocate event 0x%" PRIx16 " to instanceId %" PRIu32,
eventType, targetInstanceId);
}
@@ -286,7 +292,7 @@
};
// Stop accepting new events and tell the main loop to finish.
- postEvent(0, nullptr, callback, kSystemInstanceId, kSystemInstanceId);
+ postEventOrDie(0, nullptr, callback, kSystemInstanceId);
}
void EventLoop::onStopComplete() {
@@ -334,8 +340,15 @@
uint32_t targetInstanceId) {
bool success = false;
- Event *event = mEventPool.allocate(eventType, eventData, freeCallback,
- senderInstanceId, targetInstanceId);
+ Milliseconds receivedTime = Nanoseconds(SystemTime::getMonotonicTime());
+ // The event loop should never contain more than 65 seconds worth of data
+ // unless something has gone terribly wrong so use uint16_t to save space.
+ uint16_t receivedTimeMillis = receivedTime.getMilliseconds();
+
+ Event *event = mEventPool.allocate(eventType, receivedTimeMillis, eventData,
+ freeCallback, senderInstanceId,
+ targetInstanceId);
+
if (event != nullptr) {
success = mEvents.push(event);
}
@@ -444,7 +457,7 @@
info->version = nanoapp.getAppVersion();
info->instanceId = nanoapp.getInstanceId();
- postEvent(eventType, info, freeEventDataCallback);
+ postEventOrDie(eventType, info, freeEventDataCallback);
}
}
diff --git a/core/event_loop_manager.cc b/core/event_loop_manager.cc
index 76983e4..86b3e41 100644
--- a/core/event_loop_manager.cc
+++ b/core/event_loop_manager.cc
@@ -83,6 +83,8 @@
}
void EventLoopManager::lateInit() {
+ mSensorRequestManager.init();
+
#ifdef CHRE_GNSS_SUPPORT_ENABLED
mGnssManager.init();
#endif // CHRE_GNSS_SUPPORT_ENABLED
diff --git a/core/gnss_manager.cc b/core/gnss_manager.cc
index a04c657..b80a478 100644
--- a/core/gnss_manager.cc
+++ b/core/gnss_manager.cc
@@ -107,8 +107,8 @@
}
void GnssSession::handleReportEvent(void *event) {
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(mReportEventType, event, freeReportEventCallback);
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ mReportEventType, event, freeReportEventCallback);
}
void GnssSession::logStateToBuffer(
@@ -293,9 +293,10 @@
event->reserved = 0;
event->cookie = cookie;
- eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_GNSS_ASYNC_RESULT, event, freeEventDataCallback,
- kSystemInstanceId, instanceId);
+ eventPosted =
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_GNSS_ASYNC_RESULT, event, freeEventDataCallback,
+ instanceId);
if (!eventPosted) {
memoryFree(event);
diff --git a/core/host_comms_manager.cc b/core/host_comms_manager.cc
index 1019628..eb58af5 100644
--- a/core/host_comms_manager.cc
+++ b/core/host_comms_manager.cc
@@ -89,9 +89,9 @@
msgFromHost->fromHostData.message = msgFromHost->message.data();
msgFromHost->fromHostData.hostEndpoint = hostEndpoint;
- success = EventLoopManagerSingleton::get()->getEventLoop().postEvent(
+ success = EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
CHRE_EVENT_MESSAGE_FROM_HOST, &msgFromHost->fromHostData,
- freeMessageFromHostCallback, kSystemInstanceId, targetInstanceId);
+ freeMessageFromHostCallback, targetInstanceId);
}
if (!success && msgFromHost != nullptr) {
diff --git a/core/include/chre/core/audio_request_manager.h b/core/include/chre/core/audio_request_manager.h
index 0732168..90f85f6 100644
--- a/core/include/chre/core/audio_request_manager.h
+++ b/core/include/chre/core/audio_request_manager.h
@@ -183,6 +183,9 @@
//! Whether or not the source is available. It is unavailable by default.
bool available = false;
+ //! The timestamp when the last audio data event was received.
+ Nanoseconds lastEventTimestamp;
+
//! The request to post the next event to.
AudioRequest *nextAudioRequest = nullptr;
diff --git a/core/include/chre/core/event.h b/core/include/chre/core/event.h
index cc35386..9a7dd39 100644
--- a/core/include/chre/core/event.h
+++ b/core/include/chre/core/event.h
@@ -38,8 +38,8 @@
class Event : public NonCopyable {
public:
- Event(uint16_t eventType, void *eventData,
- chreEventCompleteFunction *freeCallback,
+ Event(uint16_t eventType_, uint16_t receivedTimeMillis_, void *eventData_,
+ chreEventCompleteFunction *freeCallback_,
uint32_t senderInstanceId = kSystemInstanceId,
uint32_t targetInstanceId = kBroadcastInstanceId);
@@ -58,6 +58,9 @@
}
const uint16_t eventType;
+ //! This value can serve as a proxy for how fast CHRE is processing events
+ //! in its queue by substracting the newest event timestamp by the oldest one.
+ const uint16_t receivedTimeMillis;
void * const eventData;
chreEventCompleteFunction * const freeCallback;
const uint32_t senderInstanceId;
diff --git a/core/include/chre/core/event_loop.h b/core/include/chre/core/event_loop.h
index aa27d00..3fd7e3b 100644
--- a/core/include/chre/core/event_loop.h
+++ b/core/include/chre/core/event_loop.h
@@ -139,10 +139,22 @@
/**
* Posts an event to a nanoapp that is currently running (or all nanoapps if
- * the target instance ID is kBroadcastInstanceId). If the senderInstanceId is
- * kSystemInstanceId and the event fails to post, this is considered a fatal
+ * the target instance ID is kBroadcastInstanceId). A senderInstanceId cannot
+ * be provided to this method because it should only be used to post events
+ * sent by the system. If the event fails to post, this is considered a fatal
* error.
*
+ * @see postLowPriorityEventOrFree
+ */
+ bool postEventOrDie(uint16_t eventType, void *eventData,
+ chreEventCompleteFunction *freeCallback,
+ uint32_t targetInstanceId = kBroadcastInstanceId);
+
+ /**
+ * Posts an event to a nanoapp that is currently running (or all nanoapps if
+ * the target instance ID is kBroadcastInstanceId). If the event fails to
+ * post, it is freed with freeCallback.
+ *
* This function is safe to call from any thread.
*
* @param eventType The type of data being posted.
@@ -152,26 +164,15 @@
* @param senderInstanceId The instance ID of the sender of this event.
* @param targetInstanceId The instance ID of the destination of this event.
*
- * @return true if the event was successfully added to the queue. Note that
- * unlike chreSendEvent, this does *not* invoke the free callback if
- * it failed to post the event.
+ * @return true if the event was successfully added to the queue.
*
* @see chreSendEvent
*/
- bool postEvent(uint16_t eventType, void *eventData,
- chreEventCompleteFunction *freeCallback,
- uint32_t senderInstanceId = kSystemInstanceId,
- uint32_t targetInstanceId = kBroadcastInstanceId);
-
- /**
- * Post an event to a nanoapp. If it fails, free the event with freeCallback.
- *
- * @see postEvent
- */
- bool postEventOrFree(uint16_t eventType, void *eventData,
- chreEventCompleteFunction *freeCallback,
- uint32_t senderInstanceId = kSystemInstanceId,
- uint32_t targetInstanceId = kBroadcastInstanceId);
+ bool postLowPriorityEventOrFree(
+ uint16_t eventType, void *eventData,
+ chreEventCompleteFunction *freeCallback,
+ uint32_t senderInstanceId = kSystemInstanceId,
+ uint32_t targetInstanceId = kBroadcastInstanceId);
/**
* Returns a pointer to the currently executing Nanoapp, or nullptr if none is
@@ -262,9 +263,9 @@
//! The maximum number of events that can be active in the system.
static constexpr size_t kMaxEventCount = CHRE_MAX_EVENT_COUNT;
- //! The minimum number of events to reserve in the event pool for system
- //! events.
- static constexpr size_t kMinReservedSystemEventCount = 16;
+ //! The minimum number of events to reserve in the event pool for high
+ //! priority events.
+ static constexpr size_t kMinReservedHighPriorityEventCount = 16;
//! The maximum number of events that are awaiting to be scheduled. These
//! events are in a queue to be distributed to apps.
@@ -320,7 +321,7 @@
*
* @return true if the event has been successfully allocated and posted.
*
- * @see postEvent and postEventOrFree
+ * @see postEventOrDie and postLowPriorityEventOrFree
*/
bool allocateAndPostEvent(uint16_t eventType, void *eventData,
chreEventCompleteFunction *freeCallback, uint32_t senderInstanceId,
diff --git a/core/include/chre/core/event_loop_manager.h b/core/include/chre/core/event_loop_manager.h
index 4242d2d..fb72fbf 100644
--- a/core/include/chre/core/event_loop_manager.h
+++ b/core/include/chre/core/event_loop_manager.h
@@ -87,8 +87,8 @@
*/
void deferCallback(SystemCallbackType type, void *data,
SystemCallbackFunction *callback) {
- mEventLoop.postEvent(static_cast<uint16_t>(type), data, callback,
- kSystemInstanceId, kSystemInstanceId);
+ mEventLoop.postEventOrDie(static_cast<uint16_t>(type), data, callback,
+ kSystemInstanceId);
}
/**
diff --git a/core/include/chre/core/sensor_request_manager.h b/core/include/chre/core/sensor_request_manager.h
index 1d36b61..2e48938 100644
--- a/core/include/chre/core/sensor_request_manager.h
+++ b/core/include/chre/core/sensor_request_manager.h
@@ -21,6 +21,7 @@
#include "chre/core/sensor.h"
#include "chre/core/sensor_request.h"
#include "chre/core/timer_pool.h"
+#include "chre/platform/atomic.h"
#include "chre/platform/system_time.h"
#include "chre/platform/system_timer.h"
#include "chre/util/fixed_size_vector.h"
@@ -44,6 +45,12 @@
~SensorRequestManager();
/**
+ * Initializes the underlying platform-specific sensors. Must be called
+ * prior to invoking any other methods in this class.
+ */
+ void init();
+
+ /**
* Determines whether the runtime is aware of a given sensor type. The
* supplied sensorHandle is only populated if the sensor type is known.
*
@@ -172,6 +179,16 @@
void handleFlushCompleteEvent(uint8_t errorCode, SensorType sensorType);
/**
+ * Invoked by the PlatformSensor when a sensor event is received for a given
+ * sensor. This method should be invoked from the same thread.
+ *
+ * @param sensorType the type of sensor the sensor data corresponds to
+ * @param event the event data formatted as one of the chreSensorXXXData
+ * defined in the CHRE API, implicitly specified by sensorType.
+ */
+ void handleSensorEvent(SensorType sensorType, void *event);
+
+ /**
* Prints state in a string buffer. Must only be called from the context of
* the main CHRE thread.
*
@@ -200,6 +217,8 @@
//! The timestamp at which this request should complete.
Nanoseconds deadlineTimestamp = SystemTime::getMonotonicTime() +
Nanoseconds(CHRE_SENSOR_FLUSH_COMPLETE_TIMEOUT_NS);
+ //! True if this flush request is active and is pending completion.
+ bool isActive = false;
};
/**
@@ -208,6 +227,8 @@
*/
class SensorRequests {
public:
+ SensorRequests() : mFlushRequestPending(false) {}
+
/**
* Initializes the sensor object. This method must only be invoked once
* when the SensorRequestManager initializes.
@@ -234,6 +255,13 @@
}
/**
+ * @return true if the sensor is currently enabled.
+ */
+ bool isSensorEnabled() const {
+ return !mMultiplexer.getRequests().empty();
+ }
+
+ /**
* @return A constant reference to the sensor object. This method has an
* undefined behavior if isSensorSupported() is false.
*/
@@ -347,12 +375,25 @@
*
* @return An error code from enum chreError
*/
- uint8_t makeFlushRequest(const FlushRequest& request);
+ uint8_t makeFlushRequest(FlushRequest& request);
/**
- * Cancels a timeout timer for a pending flush request.
+ * Clears any states (e.g. timeout timer and relevant flags) associated
+ * with a pending flush request.
*/
- void cancelFlushTimer();
+ void clearPendingFlushRequest();
+
+ /**
+ * Cancels the pending timeout timer associated with a flush request.
+ */
+ void cancelPendingFlushRequestTimer();
+
+ /**
+ * @return true if a flush through makeFlushRequest is pending.
+ */
+ inline bool isFlushRequestPending() const {
+ return mFlushRequestPending;
+ }
private:
//! The sensor associated with this request multiplexer. If this Optional
@@ -366,12 +407,15 @@
//! The timeout timer handle for the current flush request.
TimerHandle mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
+ //! True if a flush request is pending for this sensor.
+ AtomicBool mFlushRequestPending;
+
/**
- * @return true if a flush through makeFlushRequest is pending.
+ * Make a flush request through PlatformSensor.
+ *
+ * @return true if the flush request was successfully made.
*/
- inline bool isFlushRequestPending() const {
- return mFlushRequestTimerHandle != CHRE_TIMER_INVALID;
- }
+ bool doMakeFlushRequest();
};
//! The list of sensor requests.
@@ -400,13 +444,22 @@
uint32_t sensorHandle, uint8_t errorCode, const FlushRequest& request);
/**
+ * Completes a flush request at the specified index by posting a
+ * CHRE_EVENT_SENSOR_FLUSH_COMPLETE event with the specified errorCode,
+ * removing the request from the queue, cleaning up states as necessary.
+ *
+ * @param index The index of the flush request.
+ * @param errorCode The error code to send the completion event with.
+ */
+ void completeFlushRequestAtIndex(size_t index, uint8_t errorCode);
+
+ /**
* 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);
+ void dispatchNextFlushRequest(SensorType sensorType);
/**
* Handles a complete event for a sensor flush requested through flushAsync.
@@ -417,6 +470,16 @@
* @param sensorType The SensorType of sensor that has completed the flush.
*/
void handleFlushCompleteEventSync(uint8_t errorCode, SensorType sensorType);
+
+ /**
+ * Cancels all pending flush requests for a given sensor and nanoapp.
+ *
+ * @param sensorType The type of sensor to cancel requests for.
+ * @param nanoappInstanceId The ID of the nanoapp to cancel requests for,
+ * kSystemInstanceId to remove requests for all nanoapps.
+ */
+ void cancelFlushRequests(
+ SensorType sensorType, uint32_t nanoappInstanceId = kSystemInstanceId);
};
} // namespace chre
diff --git a/core/include/chre/core/sensor_type.h b/core/include/chre/core/sensor_type.h
index 1fb0492..ebb5e52 100644
--- a/core/include/chre/core/sensor_type.h
+++ b/core/include/chre/core/sensor_type.h
@@ -326,6 +326,18 @@
*/
SensorType toUncalibratedSensorType(SensorType sensorType);
+/**
+ * @param sensorType The sensor type.
+ *
+ * @return true if the sensor type is for a valid sensor.
+ */
+inline bool isValidSensorType(SensorType sensorType) {
+ // TODO: Consider asserting that sensorType < SensorType::SENSOR_TYPE_COUNT
+ // once assertion can be enabled without costing extra memory overhead.
+ return sensorType > SensorType::Unknown
+ && sensorType < SensorType::SENSOR_TYPE_COUNT;
+}
+
} // namespace chre
#endif // CHRE_CORE_SENSOR_TYPE_H_
diff --git a/core/init.cc b/core/init.cc
index 401c95a..01991df 100644
--- a/core/init.cc
+++ b/core/init.cc
@@ -17,7 +17,6 @@
#include "chre/core/init.h"
#include "chre/core/event_loop_manager.h"
-#include "chre/platform/platform_sensor.h"
#include "chre/platform/system_time.h"
#include "chre/util/singleton.h"
@@ -35,15 +34,10 @@
LOGI("CHRE init, version: %s", kChreVersionString);
SystemTime::init();
- PlatformSensor::init();
EventLoopManagerSingleton::init();
}
void deinit() {
- PlatformSensor::deinit();
-
- // EventLoopManager has to be the last one to deinit to handle callback
- // functions in PlatformSensor potentially from a different thread.
EventLoopManagerSingleton::deinit();
LOGD("CHRE deinit");
diff --git a/core/sensor_request_manager.cc b/core/sensor_request_manager.cc
index ca3730c..4053569 100644
--- a/core/sensor_request_manager.cc
+++ b/core/sensor_request_manager.cc
@@ -19,8 +19,14 @@
#include "chre_api/chre/version.h"
#include "chre/core/event_loop_manager.h"
#include "chre/platform/fatal_error.h"
+#include "chre/platform/shared/platform_sensor_util.h"
+#include "chre/util/nested_data_ptr.h"
#include "chre/util/system/debug_dump.h"
+#define LOG_INVALID_SENSOR(x) \
+ LOGE("Invalid sensor type %" PRIu8 ": line %d", \
+ static_cast<uint8_t>(x), __LINE__)
+
namespace chre {
namespace {
@@ -51,17 +57,27 @@
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() {
mSensorRequests.resize(mSensorRequests.capacity());
+}
+
+SensorRequestManager::~SensorRequestManager() {
+ for (size_t i = 0; i < mSensorRequests.size(); i++) {
+ // Disable sensors that have been enabled previously.
+ if (mSensorRequests[i].isSensorSupported()) {
+ mSensorRequests[i].removeAll();
+ }
+ }
+
+ PlatformSensor::deinit();
+}
+
+void SensorRequestManager::init() {
+ // The Platform sensor must be initialized prior to interacting with any
+ // sensors.
+ PlatformSensor::init();
DynamicVector<Sensor> sensors;
sensors.reserve(8); // Avoid some initial reallocation churn
@@ -74,8 +90,8 @@
SensorType sensorType = sensors[i].getSensorType();
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
- if (sensorType == SensorType::Unknown) {
- LOGE("Invalid sensor type");
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else if (sensors[i].getMinInterval() == 0) {
LOGE("Invalid sensor minInterval: %s", getSensorTypeName(sensorType));
} else {
@@ -86,22 +102,13 @@
}
}
-SensorRequestManager::~SensorRequestManager() {
- for (size_t i = 0; i < mSensorRequests.size(); i++) {
- // Disable sensors that have been enabled previously.
- if (mSensorRequests[i].isSensorSupported()) {
- mSensorRequests[i].removeAll();
- }
- }
-}
-
bool SensorRequestManager::getSensorHandle(SensorType sensorType,
uint32_t *sensorHandle) const {
CHRE_ASSERT(sensorHandle);
bool sensorHandleIsValid = false;
- if (sensorType == SensorType::Unknown) {
- LOGW("Querying for unknown sensor type");
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
sensorHandleIsValid = mSensorRequests[sensorIndex].isSensorSupported();
@@ -119,8 +126,8 @@
// Validate the input to ensure that a valid handle has been provided.
SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
- if (sensorType == SensorType::Unknown) {
- LOGW("Attempting to configure an invalid sensor handle");
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
return false;
}
@@ -151,6 +158,8 @@
// unregistered from events of this type if this request was successful.
success = requests.remove(requestIndex, &requestChanged);
if (success) {
+ cancelFlushRequests(sensorType, nanoapp->getInstanceId());
+
nanoapp->unregisterForBroadcastEvent(eventType);
uint16_t biasEventType;
@@ -185,12 +194,11 @@
}
// Deliver last valid event to new clients of on-change sensors
- if (sensorTypeIsOnChange(sensor.getSensorType())
- && sensor.getLastEvent() != nullptr) {
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(getSampleEventTypeForSensorType(sensorType),
- sensor.getLastEvent(), nullptr, kSystemInstanceId,
- nanoapp->getInstanceId());
+ if (sensorTypeIsOnChange(sensor.getSensorType()) &&
+ sensor.getLastEvent() != nullptr) {
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ getSampleEventTypeForSensorType(sensorType), sensor.getLastEvent(),
+ nullptr, nanoapp->getInstanceId());
}
}
} else {
@@ -215,9 +223,8 @@
// Validate the input to ensure that a valid handle has been provided.
SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
- if (sensorType == SensorType::Unknown) {
- LOGW("Attempting to access sensor with an invalid handle %" PRIu32,
- sensorHandle);
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
if (!mSensorRequests[sensorIndex].isSensorSupported()) {
@@ -250,8 +257,8 @@
bool SensorRequestManager::removeAllRequests(SensorType sensorType) {
bool success = false;
- if (sensorType == SensorType::Unknown) {
- LOGW("Attempting to remove all requests of an invalid sensor type");
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
SensorRequests& requests = mSensorRequests[sensorIndex];
@@ -265,6 +272,7 @@
}
}
+ cancelFlushRequests(sensorType);
success = requests.removeAll();
}
return success;
@@ -272,10 +280,8 @@
Sensor *SensorRequestManager::getSensor(SensorType sensorType) {
Sensor *sensorPtr = nullptr;
- if (sensorType == SensorType::Unknown
- || sensorType >= SensorType::SENSOR_TYPE_COUNT) {
- LOGW("Attempting to get Sensor of an invalid SensorType %d",
- static_cast<int>(sensorType));
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
if (mSensorRequests[sensorIndex].isSensorSupported()) {
@@ -291,9 +297,8 @@
bool success = false;
SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
- if (sensorType == SensorType::Unknown) {
- LOGW("Attempting to access sensor with an invalid handle %" PRIu32,
- sensorHandle);
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
if (mSensorRequests[sensorIndex].isSensorSupported()) {
@@ -306,9 +311,8 @@
const DynamicVector<SensorRequest>& SensorRequestManager::getRequests(
SensorType sensorType) const {
size_t sensorIndex = 0;
- if (sensorType == SensorType::Unknown
- || sensorType >= SensorType::SENSOR_TYPE_COUNT) {
- LOGW("Attempting to get requests of an invalid SensorType");
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
sensorIndex = getSensorTypeArrayIndex(sensorType);
}
@@ -340,9 +344,8 @@
bool success = false;
if (bias != nullptr) {
SensorType sensorType = getSensorTypeFromSensorHandle(sensorHandle);
- if (sensorType == SensorType::Unknown) {
- LOGW("Attempting to access sensor with an invalid handle %" PRIu32,
- sensorHandle);
+ if (!isValidSensorType(sensorType)) {
+ LOG_INVALID_SENSOR(sensorType);
} else {
size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
if (mSensorRequests[sensorIndex].isSensorSupported()) {
@@ -361,7 +364,7 @@
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)) {
+ if (!isValidSensorType(sensorType) || sensorTypeIsOneShot(sensorType)) {
LOGE("Cannot flush for sensor type %" PRIu32,
static_cast<uint32_t>(sensorType));
} else if (mFlushRequestQueue.full()) {
@@ -381,33 +384,49 @@
void SensorRequestManager::handleFlushCompleteEvent(
uint8_t errorCode, SensorType sensorType) {
- struct CallbackState {
- uint8_t errorCode;
- SensorType sensorType;
- };
+ size_t sensorIndex = getSensorTypeArrayIndex(sensorType);
+ if (isValidSensorType(sensorType)
+ && mSensorRequests[sensorIndex].isFlushRequestPending()) {
- // 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 *");
+ // Cancel flush request timer before posting to the event queue to ensure
+ // a timeout event isn't processed by CHRE now that the complete event
+ // has been received.
+ mSensorRequests[sensorIndex].cancelPendingFlushRequestTimer();
- NestedCallbackState state = {};
- state.callbackState.errorCode = errorCode;
- state.callbackState.sensorType = sensorType;
+ struct CallbackState {
+ uint8_t errorCode;
+ SensorType sensorType;
+ };
- auto callback = [](uint16_t /* eventType */, void *eventData) {
- NestedCallbackState nestedState;
- nestedState.eventData = eventData;
- EventLoopManagerSingleton::get()->getSensorRequestManager()
- .handleFlushCompleteEventSync(nestedState.callbackState.errorCode,
- nestedState.callbackState.sensorType);
- };
+ NestedDataPtr<CallbackState> state = {};
+ state.data.errorCode = errorCode;
+ state.data.sensorType = sensorType;
- EventLoopManagerSingleton::get()->deferCallback(
- SystemCallbackType::SensorFlushComplete, state.eventData, callback);
+ auto callback = [](uint16_t /* eventType */, void *eventData) {
+ NestedDataPtr<CallbackState> nestedState;
+ nestedState.dataPtr = eventData;
+ EventLoopManagerSingleton::get()->getSensorRequestManager()
+ .handleFlushCompleteEventSync(nestedState.data.errorCode,
+ nestedState.data.sensorType);
+ };
+
+ EventLoopManagerSingleton::get()->deferCallback(
+ SystemCallbackType::SensorFlushComplete, state.dataPtr, callback);
+ }
+}
+
+void SensorRequestManager::handleSensorEvent(SensorType sensorType,
+ void *event) {
+ uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
+ // Only allow dropping continuous sensor events since losing one-shot or
+ // on-change events could result in nanoapps stuck in a bad state.
+ if (sensorTypeIsContinuous(sensorType)) {
+ EventLoopManagerSingleton::get()->getEventLoop().postLowPriorityEventOrFree(
+ eventType, event, sensorDataEventFree);
+ } else {
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ eventType, event, sensorDataEventFree);
+ }
}
void SensorRequestManager::logStateToBuffer(char *buffer, size_t *bufferPos,
@@ -416,7 +435,7 @@
for (uint8_t i = 0; i < static_cast<uint8_t>(SensorType::SENSOR_TYPE_COUNT);
i++) {
SensorType sensor = static_cast<SensorType>(i);
- if (sensor != SensorType::Unknown) {
+ if (isValidSensorType(sensor)) {
for (const auto& request : getRequests(sensor)) {
debugDumpPrint(buffer, bufferPos, bufferSize, " %s: mode=%d"
" interval(ns)=%" PRIu64 " latency(ns)=%"
@@ -441,25 +460,41 @@
event->cookie = request.cookie;
memset(event->reserved, 0, sizeof(event->reserved));
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
CHRE_EVENT_SENSOR_FLUSH_COMPLETE, event, freeEventDataCallback,
- kSystemInstanceId, request.nanoappInstanceId);
+ request.nanoappInstanceId);
}
}
-void SensorRequestManager::dispatchNextFlushRequest(
- uint32_t sensorHandle, SensorType sensorType) {
+void SensorRequestManager::completeFlushRequestAtIndex(
+ size_t index, uint8_t errorCode) {
+ if (index < mFlushRequestQueue.size()) {
+ const FlushRequest& request = mFlushRequestQueue[index];
+ SensorType sensorType = request.sensorType;
+ if (request.isActive) {
+ SensorRequests& requests = getSensorRequests(sensorType);
+ requests.clearPendingFlushRequest();
+ }
+
+ uint32_t sensorHandle;
+ if (getSensorHandle(sensorType, &sensorHandle)) {
+ postFlushCompleteEvent(sensorHandle, errorCode, request);
+ }
+ mFlushRequestQueue.erase(index);
+ }
+}
+
+void SensorRequestManager::dispatchNextFlushRequest(SensorType sensorType) {
SensorRequests& requests = getSensorRequests(sensorType);
for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
- const FlushRequest& request = mFlushRequestQueue[i];
+ 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);
+ completeFlushRequestAtIndex(i, newRequestErrorCode);
i--;
}
}
@@ -469,22 +504,33 @@
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);
- }
+ if (mFlushRequestQueue[i].sensorType == sensorType) {
+ completeFlushRequestAtIndex(i, errorCode);
+ dispatchNextFlushRequest(sensorType);
break;
}
}
}
+void SensorRequestManager::cancelFlushRequests(
+ SensorType sensorType, uint32_t nanoappInstanceId) {
+ bool removeAll = (nanoappInstanceId == kSystemInstanceId);
+ for (size_t i = 0; i < mFlushRequestQueue.size(); i++) {
+ const FlushRequest& request = mFlushRequestQueue[i];
+ if (request.sensorType == sensorType &&
+ (request.nanoappInstanceId == nanoappInstanceId || removeAll)) {
+ completeFlushRequestAtIndex(
+ i, CHRE_ERROR_FUNCTION_DISABLED /* errorCode */);
+ i--;
+ }
+ }
+
+ SensorRequests& requests = getSensorRequests(sensorType);
+ if (!requests.isFlushRequestPending()) {
+ dispatchNextFlushRequest(sensorType);
+ }
+}
+
const SensorRequest *SensorRequestManager::SensorRequests::find(
uint32_t instanceId, size_t *index) const {
CHRE_ASSERT(index);
@@ -607,7 +653,7 @@
}
uint8_t SensorRequestManager::SensorRequests::makeFlushRequest(
- const FlushRequest& request) {
+ FlushRequest& request) {
uint8_t errorCode = CHRE_ERROR;
if (!isSensorSupported()) {
LOGE("Cannot flush on unsupported sensor");
@@ -621,13 +667,33 @@
": deadline exceeded", static_cast<uint32_t>(request.sensorType),
request.nanoappInstanceId);
errorCode = CHRE_ERROR_TIMEOUT;
- } else if (mSensor->flushAsync()) {
+ } else if (doMakeFlushRequest()) {
errorCode = CHRE_ERROR_NONE;
Nanoseconds delay = deadline - now;
+ request.isActive = true;
+
+ NestedDataPtr<SensorType> nestedType = {};
+ nestedType.data = request.sensorType;
+
+ auto callback = [](uint16_t /* eventType */, void * eventData) {
+ LOGE("Flush request timed out.");
+ NestedDataPtr<SensorType> nestedType;
+ nestedType.dataPtr = eventData;
+ // Send a complete event, thus closing out this flush request. If the
+ // request that has just timed out receives a response later, this may
+ // inadvertently close out a new request before it has actually
+ // completed.
+ // TODO: Attach an ID to all flush requests / responses so stale
+ // responses can be properly dropped.
+ EventLoopManagerSingleton::get()->getSensorRequestManager()
+ .handleFlushCompleteEventSync(CHRE_ERROR_TIMEOUT,
+ nestedType.data);
+ };
+
mFlushRequestTimerHandle =
EventLoopManagerSingleton::get()->setDelayedCallback(
- SystemCallbackType::SensorFlushTimeout, nullptr /* data */,
- flushTimerCallback, delay);
+ SystemCallbackType::SensorFlushTimeout, nestedType.dataPtr,
+ callback, delay);
}
} else {
// Flush request will be made once the pending request is completed.
@@ -639,10 +705,25 @@
return errorCode;
}
-void SensorRequestManager::SensorRequests::cancelFlushTimer() {
- EventLoopManagerSingleton::get()->cancelDelayedCallback(
- mFlushRequestTimerHandle);
- mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
+void SensorRequestManager::SensorRequests::clearPendingFlushRequest() {
+ cancelPendingFlushRequestTimer();
+ mFlushRequestPending = false;
+}
+
+void SensorRequestManager::SensorRequests::cancelPendingFlushRequestTimer() {
+ if (mFlushRequestTimerHandle != CHRE_TIMER_INVALID) {
+ EventLoopManagerSingleton::get()->cancelDelayedCallback(
+ mFlushRequestTimerHandle);
+ mFlushRequestTimerHandle = CHRE_TIMER_INVALID;
+ }
+}
+
+bool SensorRequestManager::SensorRequests::doMakeFlushRequest() {
+ // Set to true before making the request since it's a synchronous request
+ // and we may get the complete event before it returns.
+ mFlushRequestPending = true;
+ mFlushRequestPending = mSensor->flushAsync();
+ return mFlushRequestPending;
}
} // namespace chre
diff --git a/core/timer_pool.cc b/core/timer_pool.cc
index c910d80..87d0f31 100644
--- a/core/timer_pool.cc
+++ b/core/timer_pool.cc
@@ -223,11 +223,10 @@
TimerRequest& currentTimerRequest = mTimerRequests.top();
if (currentTime >= currentTimerRequest.expirationTime) {
// Post an event for an expired timer.
- success = EventLoopManagerSingleton::get()->getEventLoop().postEvent(
+ success = EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
currentTimerRequest.eventType,
const_cast<void *>(currentTimerRequest.cookie),
- currentTimerRequest.callback, kSystemInstanceId,
- currentTimerRequest.instanceId);
+ currentTimerRequest.callback, currentTimerRequest.instanceId);
// Reschedule the timer if needed, and release the current request.
if (!currentTimerRequest.isOneShot) {
diff --git a/core/wifi_request_manager.cc b/core/wifi_request_manager.cc
index 549c35d..51b3b25 100644
--- a/core/wifi_request_manager.cc
+++ b/core/wifi_request_manager.cc
@@ -380,9 +380,10 @@
event->cookie = cookie;
// Post the event.
- eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
- kSystemInstanceId, nanoappInstanceId);
+ eventPosted =
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
+ nanoappInstanceId);
if (!eventPosted) {
memoryFree(event);
}
@@ -416,9 +417,10 @@
event->cookie = cookie;
// Post the event.
- eventPosted = EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
- kSystemInstanceId, nanoappInstanceId);
+ eventPosted =
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
+ nanoappInstanceId);
}
return eventPosted;
@@ -434,8 +436,8 @@
}
void WifiRequestManager::postScanEventFatal(chreWifiScanEvent *event) {
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_WIFI_SCAN_RESULT, event, freeWifiScanEventCallback);
}
void WifiRequestManager::handleScanMonitorStateChangeSync(bool enabled,
@@ -556,9 +558,10 @@
event->reserved = 0;
event->cookie = req.cookie;
- eventPosted = EventLoopManagerSingleton::get()->getEventLoop().postEvent(
- CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
- kSystemInstanceId, req.nanoappInstanceId);
+ eventPosted =
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_WIFI_ASYNC_RESULT, event, freeEventDataCallback,
+ req.nanoappInstanceId);
if (!eventPosted) {
memoryFree(event);
}
@@ -593,9 +596,9 @@
if (errorCode != CHRE_ERROR_NONE) {
LOGW("RTT ranging failed with error %d", errorCode);
} else {
- EventLoopManagerSingleton::get()->getEventLoop().postEvent(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
CHRE_EVENT_WIFI_RANGING_RESULT, event, freeWifiRangingEventCallback,
- kSystemInstanceId, mPendingRangingRequests.front().nanoappInstanceId);
+ mPendingRangingRequests.front().nanoappInstanceId);
}
mPendingRangingRequests.pop();
}
diff --git a/core/wwan_request_manager.cc b/core/wwan_request_manager.cc
index 3784566..4cf8243 100644
--- a/core/wwan_request_manager.cc
+++ b/core/wwan_request_manager.cc
@@ -65,10 +65,9 @@
chreWwanCellInfoResult *result) {
if (mCellInfoRequestingNanoappInstanceId.has_value()) {
result->cookie = mCellInfoRequestingNanoappCookie;
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_WWAN_CELL_INFO_RESULT, result,
- freeCellInfoResultCallback, kSystemInstanceId,
- mCellInfoRequestingNanoappInstanceId.value());
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_WWAN_CELL_INFO_RESULT, result, freeCellInfoResultCallback,
+ mCellInfoRequestingNanoappInstanceId.value());
} else {
LOGE("Cell info results received unexpectedly");
}
diff --git a/host/msm/daemon/chre_daemon.cc b/host/msm/daemon/chre_daemon.cc
index 74e7113..e6b8bc5 100644
--- a/host/msm/daemon/chre_daemon.cc
+++ b/host/msm/daemon/chre_daemon.cc
@@ -81,6 +81,7 @@
#include <hardware_legacy/power.h>
using android::sp;
+using android::wp;
using android::hardware::Return;
using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
using android::hardware::soundtrigger::V2_0::SoundModelHandle;
@@ -115,15 +116,32 @@
//! The name of the wakelock to use for the CHRE daemon.
static const char kWakeLockName[] = "chre_daemon";
+//! Forward declarations
+static void onStHalServiceDeath();
+
+//! Class to handle when a connected ST HAL service dies.
+class StHalDeathRecipient : public android::hardware::hidl_death_recipient {
+ virtual void serviceDied(
+ uint64_t /* cookie */,
+ const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
+ LOGE("ST HAL service died.");
+ onStHalServiceDeath();
+ }
+};
+
struct LpmaEnableThreadData {
pthread_t thread;
pthread_mutex_t mutex;
pthread_cond_t cond;
bool currentLpmaEnabled;
bool targetLpmaEnabled;
+ bool connectedToService;
+ sp<StHalDeathRecipient> deathRecipient = new StHalDeathRecipient();
+ sp<ISoundTriggerHw> stHalService;
};
static LpmaEnableThreadData lpmaEnableThread;
+
#endif // CHRE_DAEMON_LPMA_ENABLED
//! The host ID to use when preloading nanoapps. This is used before the server
@@ -275,7 +293,13 @@
return timeOffset;
}
-static void sendTimeSyncMessage() {
+
+/**
+ * @param logOnError If true, logs an error message on failure.
+ *
+ * @return true if the time sync message was successfully sent to CHRE.
+ */
+static bool sendTimeSyncMessage(bool logOnError) {
bool timeSyncSuccess = true;
int64_t timeOffset = getTimeOffset(&timeSyncSuccess);
@@ -287,9 +311,36 @@
static_cast<int>(builder.GetSize()));
if (success != 0) {
- LOGE("Failed to deliver timestamp message from host to CHRE: %d", success);
+ if (logOnError) {
+ LOGE("Failed to deliver time sync message from host to CHRE: %d",
+ success);
+ }
+ timeSyncSuccess = false;
}
}
+
+ return timeSyncSuccess;
+}
+
+/**
+ * Sends a time sync message to CHRE, retrying a specified time until success.
+ *
+ * @param maxNumRetries The number of times to retry sending the message
+ *
+ * @return true if the time sync message was successfully sent to CHRE.
+ */
+static bool sendTimeSyncMessageRetry(size_t maxNumRetries) {
+ size_t numRetries = 0;
+ useconds_t retryDelayUs = 50000; // 50 ms initially
+ bool success = sendTimeSyncMessage(numRetries == maxNumRetries);
+ while (!success && numRetries < maxNumRetries) {
+ usleep(retryDelayUs);
+ numRetries++;
+ retryDelayUs *= 2;
+ success = sendTimeSyncMessage(numRetries == maxNumRetries);
+ }
+
+ return success;
}
#ifdef CHRE_DAEMON_LPMA_ENABLED
@@ -326,6 +377,38 @@
pthread_cond_signal(&lpmaEnableThread.cond);
}
+static void onStHalServiceDeath() {
+ pthread_mutex_lock(&lpmaEnableThread.mutex);
+ lpmaEnableThread.connectedToService = false;
+ if (lpmaEnableThread.targetLpmaEnabled) {
+ // ST HAL has died, so assume that the sound model is no longer active,
+ // and trigger a reload of the sound model.
+ lpmaEnableThread.currentLpmaEnabled = false;
+ pthread_cond_signal(&lpmaEnableThread.cond);
+ }
+ pthread_mutex_unlock(&lpmaEnableThread.mutex);
+}
+
+/**
+ * Connects to the ST HAL service, if not already. This method should only
+ * be invoked after acquiring the lpmaEnableThread.mutex lock.
+ *
+ * @return true if successfully connected to the HAL.
+ */
+static bool connectToStHalServiceLocked() {
+ if (!lpmaEnableThread.connectedToService) {
+ lpmaEnableThread.stHalService = ISoundTriggerHw::getService();
+ if (lpmaEnableThread.stHalService != nullptr) {
+ LOGI("Connected to ST HAL service");
+ lpmaEnableThread.connectedToService = true;
+ lpmaEnableThread.stHalService->linkToDeath(
+ lpmaEnableThread.deathRecipient, 0 /* flags */);
+ }
+ }
+
+ return lpmaEnableThread.connectedToService;
+}
+
/**
* Loads the LPMA use case via the SoundTrigger HAL HIDL service.
*
@@ -348,12 +431,12 @@
soundModel.data.resize(1); // Insert a dummy byte to bypass HAL NULL checks.
bool loaded = false;
- sp<ISoundTriggerHw> stHal = ISoundTriggerHw::getService();
- if (stHal == nullptr) {
+ if (!connectToStHalServiceLocked()) {
LOGE("Failed to get ST HAL service for LPMA load");
} else {
int32_t loadResult;
- Return<void> hidlResult = stHal->loadSoundModel(soundModel, NULL, 0,
+ Return<void> hidlResult = lpmaEnableThread.stHalService->loadSoundModel(
+ soundModel, NULL /* callback */, 0 /* cookie */,
[&](int32_t retval, SoundModelHandle handle) {
loadResult = retval;
*lpmaHandle = handle;
@@ -389,11 +472,11 @@
static void unloadLpma(SoundModelHandle lpmaHandle) {
LOGD("Unloading LPMA");
- sp<ISoundTriggerHw> stHal = ISoundTriggerHw::getService();
- if (stHal == nullptr) {
+ if (!connectToStHalServiceLocked()) {
LOGE("Failed to get ST HAL service for LPMA unload");
} else {
- Return<int32_t> hidlResult = stHal->unloadSoundModel(lpmaHandle);
+ Return<int32_t> hidlResult =
+ lpmaEnableThread.stHalService->unloadSoundModel(lpmaHandle);
if (hidlResult.isOk()) {
if (hidlResult == 0) {
@@ -762,7 +845,7 @@
if (messageType == fbs::ChreMessage::LogMessage) {
parseAndEmitLogMessages(messageBuffer);
} else if (messageType == fbs::ChreMessage::TimeSyncRequest) {
- sendTimeSyncMessage();
+ sendTimeSyncMessage(true /* logOnError */);
#ifdef CHRE_DAEMON_LPMA_ENABLED
} else if (messageType == fbs::ChreMessage::LowPowerMicAccessRequest) {
setLpmaState(true);
@@ -905,15 +988,19 @@
}
#endif // ADSPRPC
- if (!init_reverse_monitor(&reverse_monitor)) {
+ // Send time sync message before nanoapps start, retrying a few times
+ // in case the SLPI is not ready yet. This retry logic must be placed before
+ // any of the other FastRPC method invocations.
+ constexpr size_t kMaxNumRetries = 5;
+ if (!sendTimeSyncMessageRetry(kMaxNumRetries)) {
+ LOGE("Failed to send initial time sync message");
+ } else if (!init_reverse_monitor(&reverse_monitor)) {
LOGE("Couldn't initialize reverse monitor");
#ifdef CHRE_DAEMON_LPMA_ENABLED
} else if (!initLpmaEnableThread(&lpmaEnableThread)) {
LOGE("Couldn't initialize LPMA enable thread");
#endif // CHRE_DAEMON_LPMA_ENABLED
} else {
- // Send time offset message before nanoapps start
- sendTimeSyncMessage();
if ((ret = chre_slpi_start_thread()) != CHRE_FASTRPC_SUCCESS) {
LOGE("Failed to start CHRE: %d", ret);
} else {
diff --git a/platform/platform.mk b/platform/platform.mk
index 78a778b..2b0f74e 100644
--- a/platform/platform.mk
+++ b/platform/platform.mk
@@ -29,6 +29,7 @@
SLPI_CFLAGS += -I$(SLPI_PREFIX)/core/api/systemdrivers
SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/inc
SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/inc/HAP
+SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/inc/a1std
SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/inc/stddef
SLPI_CFLAGS += -I$(SLPI_PREFIX)/platform/rtld/inc
diff --git a/platform/shared/chre_api_core.cc b/platform/shared/chre_api_core.cc
index fbf1e25..82f4ace 100644
--- a/platform/shared/chre_api_core.cc
+++ b/platform/shared/chre_api_core.cc
@@ -57,12 +57,9 @@
LOGW("Rejecting event from app instance %" PRIu32 " because it's stopping",
nanoapp->getInstanceId());
} else {
- success = eventLoop.postEvent(eventType, eventData, freeCallback,
- nanoapp->getInstanceId(), targetInstanceId);
- }
-
- if (!success && freeCallback != nullptr) {
- freeCallback(eventType, eventData);
+ success = eventLoop.postLowPriorityEventOrFree(
+ eventType, eventData, freeCallback, nanoapp->getInstanceId(),
+ targetInstanceId);
}
return success;
}
diff --git a/platform/shared/include/chre/platform/shared/platform_sensor_util.h b/platform/shared/include/chre/platform/shared/platform_sensor_util.h
index 7bcb041..ad7ad8c 100644
--- a/platform/shared/include/chre/platform/shared/platform_sensor_util.h
+++ b/platform/shared/include/chre/platform/shared/platform_sensor_util.h
@@ -30,6 +30,20 @@
*/
void updateLastEvent(SensorType sensorType, const void *eventData);
+/**
+ * A helper chreEventCompleteFunction that handles freeing sensor data and
+ * removing all requests associated with the sensor type if it represents a
+ * one-shot sensor.
+ *
+ * NOTE: This function assumes the eventData was allocated using the memoryAlloc
+ * platform function.
+ *
+ * @see postEvent
+ * @param eventType The type of sample event that eventData represents.
+ * @param eventData The sensor event data that should be freed.
+ */
+void sensorDataEventFree(uint16_t eventType, void *eventData);
+
} // namespace chre
#endif // CHRE_PLATFORM_SHARED_PLATFORM_SENSOR_UTIL_H_
diff --git a/platform/shared/platform_sensor_util.cc b/platform/shared/platform_sensor_util.cc
index 029c3b9..3aec295 100644
--- a/platform/shared/platform_sensor_util.cc
+++ b/platform/shared/platform_sensor_util.cc
@@ -67,4 +67,18 @@
}
}
+void sensorDataEventFree(uint16_t eventType, void *eventData) {
+ // TODO: Consider using a MemoryPool.
+ memoryFree(eventData);
+
+ // Remove all requests if it's a one-shot sensor and only after data has been
+ // delivered to all clients.
+ SensorType sensorType = getSensorTypeForSampleEventType(eventType);
+ if (sensorTypeIsOneShot(sensorType)) {
+ EventLoopManagerSingleton::get()
+ ->getSensorRequestManager()
+ .removeAllRequests(sensorType);
+ }
+}
+
} // namespace chre
diff --git a/platform/slpi/include/chre/platform/slpi/see/see_helper.h b/platform/slpi/include/chre/platform/slpi/see/see_helper.h
index 9d223a9..01bd5ee 100644
--- a/platform/slpi/include/chre/platform/slpi/see/see_helper.h
+++ b/platform/slpi/include/chre/platform/slpi/see/see_helper.h
@@ -81,7 +81,7 @@
//! Default timeout for waitForService. Have a longer timeout since there may be
//! external dependencies blocking SEE initialization.
-constexpr Nanoseconds kDefaultSeeWaitTimeout = Seconds(5);
+constexpr Nanoseconds kDefaultSeeWaitTimeout = Seconds(30);
//! Default timeout for sendReq response
constexpr Nanoseconds kDefaultSeeRespTimeout = Seconds(1);
diff --git a/platform/slpi/see/include/chre/target_platform/platform_sensor_base.h b/platform/slpi/see/include/chre/target_platform/platform_sensor_base.h
index 198e06d..47a5dbf 100644
--- a/platform/slpi/see/include/chre/target_platform/platform_sensor_base.h
+++ b/platform/slpi/see/include/chre/target_platform/platform_sensor_base.h
@@ -18,6 +18,7 @@
#define CHRE_PLATFORM_SLPI_SEE_PLATFORM_SENSOR_BASE_H_
#include "chre/core/sensor_request.h"
+#include "chre/platform/slpi/see/see_helper.h"
namespace chre {
@@ -51,6 +52,10 @@
*/
void setSamplingStatus(const struct chreSensorSamplingStatus& status);
+ //! Stores the last received sampling status from SEE for this sensor making
+ //! it easier to dedup updates that come in later from SEE.
+ SeeHelperCallbackInterface::SamplingStatusData mLastReceivedSamplingStatus {};
+
protected:
//! The sensor type of this sensor.
SensorType mSensorType;
diff --git a/platform/slpi/see/platform_sensor.cc b/platform/slpi/see/platform_sensor.cc
index 16b6639..5d855e0 100644
--- a/platform/slpi/see/platform_sensor.cc
+++ b/platform/slpi/see/platform_sensor.cc
@@ -30,7 +30,6 @@
#include "chre/platform/shared/platform_sensor_util.h"
#include "chre/platform/slpi/power_control_util.h"
#include "chre/platform/slpi/see/see_client.h"
-#include "chre/platform/slpi/see/see_helper.h"
#include "chre/platform/system_time.h"
#ifdef CHREX_SENSOR_SUPPORT
@@ -153,11 +152,12 @@
void handleMissingSensor() {
// Try rebooting if a sensor is missing, which might help recover from a
// transient failure/race condition at startup. But to avoid endless crashes,
- // only do this within the first 45 seconds after boot - we rely on knowledge
- // that getMonotonicTime() maps into QTimer here, and QTimer only resets when
- // the entire system is rebooted (it continues increasing after SLPI SSR).
+ // only do this within 15 seconds of the timeout on initializing SEE - we rely
+ // on knowledge that getMonotonicTime() maps into QTimer here, and QTimer only
+ // resets when the entire system is rebooted (it continues increasing after
+ // SLPI SSR).
#ifndef CHRE_LOG_ONLY_NO_SENSOR
- if (SystemTime::getMonotonicTime() < Seconds(45)) {
+ if (SystemTime::getMonotonicTime() < (kDefaultSeeWaitTimeout + Seconds(15))) {
FATAL_ERROR("Missing required sensor(s)");
} else
#endif
@@ -212,18 +212,6 @@
return sensorType;
}
-void seeSensorDataEventFree(uint16_t eventType, void *eventData) {
- memoryFree(eventData);
-
- // Remove all requests if it's a one-shot sensor and only after data has been
- // delivered to all clients.
- SensorType sensorType = getSensorTypeForSampleEventType(eventType);
- if (sensorTypeIsOneShot(sensorType)) {
- EventLoopManagerSingleton::get()->getSensorRequestManager()
- .removeAllRequests(sensorType);
- }
-}
-
/**
* Posts a CHRE_EVENT_SENSOR_SAMPLING_CHANGE event to the specified Nanoapp.
*
@@ -240,9 +228,9 @@
event->sensorHandle = sensorHandle;
event->status = status;
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
CHRE_EVENT_SENSOR_SAMPLING_CHANGE, event, freeEventDataCallback,
- kSystemInstanceId, instanceId);
+ instanceId);
}
}
@@ -262,7 +250,7 @@
} else {
*event = bias;
event->header.sensorHandle = getSensorHandleFromSensorType(sensorType);
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
eventType, event, freeEventDataCallback);
}
}
@@ -270,17 +258,19 @@
/**
* Updates the sampling status.
+ *
+ * This should only be called when the new SamplingStatusData is different
+ * from the most recently processed SamplingStatusData to avoid duplicate
+ * updates being posted to nanoapps.
*/
void updateSamplingStatus(
const SeeHelperCallbackInterface::SamplingStatusData& update) {
Sensor *sensor = EventLoopManagerSingleton::get()->getSensorRequestManager()
.getSensor(update.sensorType);
- struct chreSensorSamplingStatus prevStatus;
+ struct chreSensorSamplingStatus newStatus;
if (sensor != nullptr && !sensorTypeIsOneShot(update.sensorType)
- && sensor->getSamplingStatus(&prevStatus)) {
- struct chreSensorSamplingStatus newStatus = prevStatus;
-
+ && sensor->getSamplingStatus(&newStatus)) {
if (update.enabledValid) {
newStatus.enabled = update.status.enabled;
}
@@ -291,35 +281,75 @@
newStatus.latency = update.status.latency;
}
- if (newStatus.enabled != prevStatus.enabled ||
- (newStatus.enabled && (newStatus.interval != prevStatus.interval
- || newStatus.latency != prevStatus.latency))) {
- sensor->setSamplingStatus(newStatus);
+ sensor->setSamplingStatus(newStatus);
- // Only post to Nanoapps with an open request.
- uint32_t sensorHandle = getSensorHandleFromSensorType(update.sensorType);
- const DynamicVector<SensorRequest>& requests =
- EventLoopManagerSingleton::get()->getSensorRequestManager()
- .getRequests(update.sensorType);
- for (const auto& req : requests) {
- postSamplingStatusEvent(req.getInstanceId(), sensorHandle, newStatus);
- }
+ // Only post to Nanoapps with an open request.
+ uint32_t sensorHandle = getSensorHandleFromSensorType(update.sensorType);
+ const DynamicVector<SensorRequest>& requests =
+ EventLoopManagerSingleton::get()->getSensorRequestManager()
+ .getRequests(update.sensorType);
+ for (const auto& req : requests) {
+ postSamplingStatusEvent(req.getInstanceId(), sensorHandle, newStatus);
}
}
}
+/**
+ * Compares the given status updates and returns true if they are the same.
+ *
+ * A simple memcmp cannot be done because if a given field is not valid, then
+ * the field may be different across updates, but doesn't indicate the update
+ * is different.
+ */
+bool isSameStatusUpdate(
+ const SeeHelperCallbackInterface::SamplingStatusData& status1,
+ const SeeHelperCallbackInterface::SamplingStatusData& status2) {
+ bool sameStatus = status1.enabledValid == status2.enabledValid;
+ if (sameStatus && status1.enabledValid) {
+ sameStatus &= status1.status.enabled == status2.status.enabled;
+ }
+
+ // Only check interval / latency fields if both status updates say the sensor
+ // is enabled since CHRE doesn't care what the fields are set to if the sensor
+ // is disabled.
+ if (sameStatus && status1.status.enabled) {
+ sameStatus &= status1.intervalValid == status2.intervalValid;
+ if (sameStatus && status1.intervalValid) {
+ sameStatus &= status1.status.interval == status2.status.interval;
+ }
+
+ sameStatus &= status1.latencyValid == status2.latencyValid;
+ if (sameStatus && status1.latencyValid) {
+ sameStatus &= status1.status.latency == status2.status.latency;
+ }
+ }
+
+ return sameStatus;
+}
+
void SeeHelperCallback::onSamplingStatusUpdate(
UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>&& status) {
- auto callback = [](uint16_t /* type */, void *data) {
- auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>(
- static_cast<SeeHelperCallbackInterface::SamplingStatusData *>(data));
- updateSamplingStatus(*cbData);
- };
+ Sensor *sensor = EventLoopManagerSingleton::get()->getSensorRequestManager()
+ .getSensor(status->sensorType);
- // Schedule a deferred callback to handle sensor status change in the main
- // thread.
- EventLoopManagerSingleton::get()->deferCallback(
- SystemCallbackType::SensorStatusUpdate, status.release(), callback);
+ // TODO: Once the latency field is actually filled in by SEE, modify this
+ // logic to avoid reacting if the latency and interval of the sensor are
+ // updated separately, but contain the same info as before.
+ if (sensor != nullptr &&
+ !isSameStatusUpdate(sensor->mLastReceivedSamplingStatus, *status.get())) {
+ sensor->mLastReceivedSamplingStatus = *status.get();
+
+ auto callback = [](uint16_t /* type */, void *data) {
+ auto cbData = UniquePtr<SeeHelperCallbackInterface::SamplingStatusData>(
+ static_cast<SeeHelperCallbackInterface::SamplingStatusData *>(data));
+ updateSamplingStatus(*cbData);
+ };
+
+ // Schedule a deferred callback to handle sensor status change in the main
+ // thread.
+ EventLoopManagerSingleton::get()->deferCallback(
+ SystemCallbackType::SensorStatusUpdate, status.release(), callback);
+ }
}
void SeeHelperCallback::onSensorDataEvent(
@@ -330,9 +360,8 @@
updateLastEvent(sensorType, eventData.get());
}
- uint16_t eventType = getSampleEventTypeForSensorType(sensorType);
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
- eventType, eventData.get(), seeSensorDataEventFree);
+ EventLoopManagerSingleton::get()->getSensorRequestManager().handleSensorEvent(
+ sensorType, eventData.get());
eventData.release();
}
@@ -356,7 +385,7 @@
// Posts a newly allocated event for the uncalibrated type
postSensorBiasEvent(toUncalibratedSensorType(sensorType), *biasData.get());
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
eventType, biasData.release(), freeEventDataCallback);
}
}
diff --git a/platform/slpi/see/power_control_manager.cc b/platform/slpi/see/power_control_manager.cc
index a681a9c..8d2c97b 100644
--- a/platform/slpi/see/power_control_manager.cc
+++ b/platform/slpi/see/power_control_manager.cc
@@ -43,7 +43,7 @@
if (mHostIsAwake != awake) {
mHostIsAwake = awake;
- EventLoopManagerSingleton::get()->getEventLoop().postEvent(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
mHostIsAwake ? CHRE_EVENT_HOST_AWAKE : CHRE_EVENT_HOST_ASLEEP,
nullptr /* eventData */, nullptr /* freeCallback */);
diff --git a/platform/slpi/smgr/platform_sensor.cc b/platform/slpi/smgr/platform_sensor.cc
index b8b90e9..3f7e609 100644
--- a/platform/slpi/smgr/platform_sensor.cc
+++ b/platform/slpi/smgr/platform_sensor.cc
@@ -532,21 +532,6 @@
}
}
-void smgrSensorDataEventFree(uint16_t eventType, void *eventData) {
- // Events are allocated using the simple memoryAlloc/memoryFree platform
- // functions.
- // TODO: Consider using a MemoryPool.
- memoryFree(eventData);
-
- // Remove all requests if it's a one-shot sensor and only after data has been
- // delivered to all clients.
- SensorType sensorType = getSensorTypeForSampleEventType(eventType);
- if (sensorTypeIsOneShot(sensorType)) {
- EventLoopManagerSingleton::get()->getSensorRequestManager()
- .removeAllRequests(sensorType);
- }
-}
-
/**
* Handles sensor data provided by the SMGR framework.
*
@@ -599,9 +584,9 @@
updateLastEvent(sensorType, eventData);
}
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
- getSampleEventTypeForSensorType(sensorType), eventData,
- smgrSensorDataEventFree);
+ EventLoopManagerSingleton::get()
+ ->getSensorRequestManager()
+ .handleSensorEvent(sensorType, eventData);
}
}
} // if (validReport)
@@ -871,9 +856,9 @@
event->sensorHandle = sensorHandle;
memcpy(&event->status, &status, sizeof(event->status));
- EventLoopManagerSingleton::get()->getEventLoop().postEventOrFree(
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
CHRE_EVENT_SENSOR_SAMPLING_CHANGE, event, freeEventDataCallback,
- kSystemInstanceId, instanceId);
+ instanceId);
}
}
@@ -933,7 +918,7 @@
if (sensor == nullptr) {
LOGE("Sensor ID: %" PRIu8 " in status update doesn't correspond to "
"valid sensor.", sensorId);
- // SMGR should send all callbacks back on the same thread which
+ // SMGR should send all callbacks back on the same thread which
// means the following code won't result in any timers overriding one
// another.
} else if (sensor->timerHandle.load() == CHRE_TIMER_INVALID) {
diff --git a/platform/slpi/smgr/power_control_manager.cc b/platform/slpi/smgr/power_control_manager.cc
index 5876268..c0e1f45 100644
--- a/platform/slpi/smgr/power_control_manager.cc
+++ b/platform/slpi/smgr/power_control_manager.cc
@@ -63,11 +63,11 @@
EventLoopManagerSingleton::get()->getEventLoop()
.getPowerControlManager().mHostIsAwake = !apSuspended;
if (apSuspended) {
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_HOST_ASLEEP, nullptr, nullptr);
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_HOST_ASLEEP, nullptr, nullptr);
} else {
- EventLoopManagerSingleton::get()->getEventLoop()
- .postEvent(CHRE_EVENT_HOST_AWAKE, nullptr, nullptr);
+ EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
+ CHRE_EVENT_HOST_AWAKE, nullptr, nullptr);
}
}
diff --git a/util/include/chre/util/nested_data_ptr.h b/util/include/chre/util/nested_data_ptr.h
new file mode 100644
index 0000000..f4e4b2c
--- /dev/null
+++ b/util/include/chre/util/nested_data_ptr.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 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 UTIL_CHRE_NESTED_DATA_PTR_H_
+#define UTIL_CHRE_NESTED_DATA_PTR_H_
+
+namespace chre {
+
+/**
+ * A template that provides the ability to store data inside of a void pointer
+ * to avoid allocating space on the heap in the case where the data is smaller
+ * than the size of a void pointer.
+ */
+template<typename DataType>
+union NestedDataPtr {
+ NestedDataPtr() {
+ static_assert(sizeof(NestedDataPtr<DataType>) == sizeof(void *),
+ "Size of NestedDataPtr must be equal to that of void *");
+ }
+ void *dataPtr;
+ DataType data;
+};
+
+} // namespace chre
+
+#endif // UTIL_CHRE_NESTED_DATA_PTR_H_
\ No newline at end of file