Respect reserved event count for postEventOrFree

Continuous sensor data can quickly flood CHRE's event queue when several
sensors are enabled at a max rate and CHRE stalls when issuing an
external request for some reason.

To avoid this, modify postEventOrFree to respect the
kMinReservedHighPriorityEventCount var that reserves space for high
priority events and migrate several methods that (mistakenly) use this
API to the postEvent method to guarantee their event delivery.

Additionally, modify the postEvent method to become postEventOrDie and
only allow system events to be posted here which also requires moving
nanoapp events to the new postLowPriorityEventOrFree function.

Bug: 139448882
Test: Load onto device and play w/ a_sns_test and see if crashes occur
Test: ./load_chre, ./run_tests.sh, ./run_sim.sh
Change-Id: I1e6d0268b96934b805aaa0dd8ee831e05f74f0f7
Merged-In: I1e6d0268b96934b805aaa0dd8ee831e05f74f0f7
diff --git a/core/audio_request_manager.cc b/core/audio_request_manager.cc
index a5ed914..7e162e7 100644
--- a/core/audio_request_manager.cc
+++ b/core/audio_request_manager.cc
@@ -392,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(
@@ -404,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_loop.cc b/core/event_loop.cc
index 77a963d..5fdfd4b 100644
--- a/core/event_loop.cc
+++ b/core/event_loop.cc
@@ -244,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
@@ -264,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);
     }
@@ -288,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() {
@@ -453,7 +457,7 @@
     info->version    = nanoapp.getAppVersion();
     info->instanceId = nanoapp.getInstanceId();
 
-    postEvent(eventType, info, freeEventDataCallback);
+    postEventOrDie(eventType, info, freeEventDataCallback);
   }
 }
 
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/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 2248c0e..2e48938 100644
--- a/core/include/chre/core/sensor_request_manager.h
+++ b/core/include/chre/core/sensor_request_manager.h
@@ -179,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.
    *
diff --git a/core/sensor_request_manager.cc b/core/sensor_request_manager.cc
index acc1cd8..4053569 100644
--- a/core/sensor_request_manager.cc
+++ b/core/sensor_request_manager.cc
@@ -19,6 +19,7 @@
 #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"
 
@@ -193,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 {
@@ -415,6 +415,20 @@
   }
 }
 
+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,
                                             size_t bufferSize) const {
   debugDumpPrint(buffer, bufferPos, bufferSize, "\nSensors:\n");
@@ -446,9 +460,9 @@
     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);
   }
 }
 
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/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/see/platform_sensor.cc b/platform/slpi/see/platform_sensor.cc
index d58e269..5d855e0 100644
--- a/platform/slpi/see/platform_sensor.cc
+++ b/platform/slpi/see/platform_sensor.cc
@@ -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);
     }
   }
@@ -372,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();
 }
 
@@ -398,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);
   }
 }