Process runtime sensor events in a separate thread.
SensorService::threadLoop blocks while polling from the device, which
causes the runtime sensor events to never be processed in case there
are no "real" sensor events.
Separating the threads that handle the "real" and the runtime sensor
events solves the issue - verified by adding a long sleep in poll()
and VirtualSensorTest still passes.
The new thread is only started when the the first runtime sensor is
registered.
Bug: 281452823
Bug: 288383960
Test: atest VirtualSensorTest
Test: atest cts/tests/sensor
Change-Id: I96bb217c72462d29c68c510bd7cea97ac925ccb2
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 398d602..cfafc69 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -63,8 +63,10 @@
#include <sys/types.h>
#include <unistd.h>
+#include <condition_variable>
#include <ctime>
#include <future>
+#include <mutex>
#include <string>
#include <private/android_filesystem_config.h>
@@ -196,6 +198,16 @@
if (mRuntimeSensorCallbacks.find(deviceId) == mRuntimeSensorCallbacks.end()) {
mRuntimeSensorCallbacks.emplace(deviceId, callback);
}
+
+ if (mRuntimeSensorHandler == nullptr) {
+ mRuntimeSensorEventBuffer =
+ new sensors_event_t[SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT];
+ mRuntimeSensorHandler = new RuntimeSensorHandler(this);
+ // Use PRIORITY_URGENT_DISPLAY as the injected sensor events should be dispatched as soon as
+ // possible, and also for consistency within the SensorService.
+ mRuntimeSensorHandler->run("RuntimeSensorHandler", PRIORITY_URGENT_DISPLAY);
+ }
+
return handle;
}
@@ -232,8 +244,9 @@
}
status_t SensorService::sendRuntimeSensorEvent(const sensors_event_t& event) {
- Mutex::Autolock _l(mLock);
+ std::unique_lock<std::mutex> lock(mRutimeSensorThreadMutex);
mRuntimeSensorEventQueue.push(event);
+ mRuntimeSensorsCv.notify_all();
return OK;
}
@@ -458,6 +471,7 @@
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
+ mRuntimeSensorEventBuffer = nullptr;
mMapFlushEventsToConnections = new wp<const SensorEventConnection> [minBufferSize];
mCurrentOperatingMode = NORMAL;
@@ -1089,7 +1103,6 @@
recordLastValueLocked(mSensorEventBuffer, count);
// handle virtual sensors
- bool bufferNeedsSorting = false;
if (count && vcount) {
sensors_event_t const * const event = mSensorEventBuffer;
if (!mActiveVirtualSensors.empty()) {
@@ -1125,37 +1138,11 @@
// record the last synthesized values
recordLastValueLocked(&mSensorEventBuffer[count], k);
count += k;
- bufferNeedsSorting = true;
+ sortEventBuffer(mSensorEventBuffer, count);
}
}
}
- // handle runtime sensors
- {
- size_t k = 0;
- while (!mRuntimeSensorEventQueue.empty()) {
- if (count + k >= minBufferSize) {
- ALOGE("buffer too small to hold all events: count=%zd, k=%zu, size=%zu",
- count, k, minBufferSize);
- break;
- }
- mSensorEventBuffer[count + k] = mRuntimeSensorEventQueue.front();
- mRuntimeSensorEventQueue.pop();
- k++;
- }
- if (k) {
- // record the last synthesized values
- recordLastValueLocked(&mSensorEventBuffer[count], k);
- count += k;
- bufferNeedsSorting = true;
- }
- }
-
- if (bufferNeedsSorting) {
- // sort the buffer by time-stamps
- sortEventBuffer(mSensorEventBuffer, count);
- }
-
// handle backward compatibility for RotationVector sensor
if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
for (int i = 0; i < count; i++) {
@@ -1234,7 +1221,7 @@
bool needsWakeLock = false;
for (const sp<SensorEventConnection>& connection : activeConnections) {
connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
- mMapFlushEventsToConnections);
+ mMapFlushEventsToConnections);
needsWakeLock |= connection->needsWakeLock();
// If the connection has one-shot sensors, it may be cleaned up after first trigger.
// Early check for one-shot sensors.
@@ -1253,6 +1240,46 @@
return false;
}
+void SensorService::processRuntimeSensorEvents() {
+ size_t count = 0;
+ const size_t maxBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
+
+ {
+ std::unique_lock<std::mutex> lock(mRutimeSensorThreadMutex);
+
+ if (mRuntimeSensorEventQueue.empty()) {
+ mRuntimeSensorsCv.wait(lock, [this] { return !mRuntimeSensorEventQueue.empty(); });
+ }
+
+ // Pop the events from the queue into the buffer until it's empty or the buffer is full.
+ while (!mRuntimeSensorEventQueue.empty()) {
+ if (count >= maxBufferSize) {
+ ALOGE("buffer too small to hold all events: count=%zd, size=%zu", count,
+ maxBufferSize);
+ break;
+ }
+ mRuntimeSensorEventBuffer[count] = mRuntimeSensorEventQueue.front();
+ mRuntimeSensorEventQueue.pop();
+ count++;
+ }
+ }
+
+ if (count) {
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+
+ recordLastValueLocked(mRuntimeSensorEventBuffer, count);
+ sortEventBuffer(mRuntimeSensorEventBuffer, count);
+
+ for (const sp<SensorEventConnection>& connection : connLock.getActiveConnections()) {
+ connection->sendEvents(mRuntimeSensorEventBuffer, count, /* scratch= */ nullptr,
+ /* mapFlushEventsToConnections= */ nullptr);
+ if (connection->hasOneShotSensors()) {
+ cleanupAutoDisabledSensorLocked(connection, mRuntimeSensorEventBuffer, count);
+ }
+ }
+ }
+}
+
sp<Looper> SensorService::getLooper() const {
return mLooper;
}
@@ -1300,6 +1327,14 @@
return false;
}
+bool SensorService::RuntimeSensorHandler::threadLoop() {
+ ALOGD("new thread RuntimeSensorHandler");
+ do {
+ mService->processRuntimeSensorEvents();
+ } while (!Thread::exitPending());
+ return false;
+}
+
void SensorService::recordLastValueLocked(
const sensors_event_t* buffer, size_t count) {
for (size_t i = 0; i < count; i++) {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 545f6c2..bf43101 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -42,6 +42,8 @@
#include <stdint.h>
#include <sys/types.h>
+#include <condition_variable>
+#include <mutex>
#include <queue>
#include <unordered_map>
#include <unordered_set>
@@ -208,6 +210,7 @@
class SensorEventAckReceiver;
class SensorRecord;
class SensorRegistrationInfo;
+ class RuntimeSensorHandler;
// Promoting a SensorEventConnection or SensorDirectConnection from wp to sp must be done with
// mLock held, but destroying that sp must be done unlocked to avoid a race condition that
@@ -264,6 +267,14 @@
SortedVector< wp<SensorDirectConnection> > mDirectConnections;
};
+ class RuntimeSensorHandler : public Thread {
+ sp<SensorService> const mService;
+ public:
+ virtual bool threadLoop();
+ explicit RuntimeSensorHandler(const sp<SensorService>& service) : mService(service) {
+ }
+ };
+
// If accessing a sensor we need to make sure the UID has access to it. If
// the app UID is idle then it cannot access sensors and gets no trigger
// events, no on-change events, flush event behavior does not change, and
@@ -368,6 +379,8 @@
// Thread interface
virtual bool threadLoop();
+ void processRuntimeSensorEvents();
+
// ISensorServer interface
virtual Vector<Sensor> getSensorList(const String16& opPackageName);
virtual Vector<Sensor> getDynamicSensorList(const String16& opPackageName);
@@ -512,6 +525,10 @@
uint32_t mSocketBufferSize;
sp<Looper> mLooper;
sp<SensorEventAckReceiver> mAckReceiver;
+ sp<RuntimeSensorHandler> mRuntimeSensorHandler;
+ // Mutex and CV used to notify the mRuntimeSensorHandler thread that there are new events.
+ std::mutex mRutimeSensorThreadMutex;
+ std::condition_variable mRuntimeSensorsCv;
// protected by mLock
mutable Mutex mLock;
@@ -519,7 +536,7 @@
std::unordered_set<int> mActiveVirtualSensors;
SensorConnectionHolder mConnectionHolder;
bool mWakeLockAcquired;
- sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
+ sensors_event_t *mSensorEventBuffer, *mSensorEventScratch, *mRuntimeSensorEventBuffer;
// WARNING: these SensorEventConnection instances must not be promoted to sp, except via
// modification to add support for them in ConnectionSafeAutolock
wp<const SensorEventConnection> * mMapFlushEventsToConnections;