Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 60ed8366 authored by Vladimir Komsiyski's avatar Vladimir Komsiyski
Browse files

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
parent 8fa4561d
Loading
Loading
Loading
Loading
+65 −30
Original line number Diff line number Diff line
@@ -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 @@ int SensorService::registerRuntimeSensor(
    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::unregisterRuntimeSensor(int handle) {
}

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 @@ void SensorService::onFirstRef() {
            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 @@ bool SensorService::threadLoop() {
        recordLastValueLocked(mSensorEventBuffer, count);

        // handle virtual sensors
        bool bufferNeedsSorting = false;
        if (count && vcount) {
            sensors_event_t const * const event = mSensorEventBuffer;
            if (!mActiveVirtualSensors.empty()) {
@@ -1125,35 +1138,9 @@ bool SensorService::threadLoop() {
                    // record the last synthesized values
                    recordLastValueLocked(&mSensorEventBuffer[count], k);
                    count += k;
                    bufferNeedsSorting = true;
                }
            }
        }

        // 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;
                    sortEventBuffer(mSensorEventBuffer, count);
                }
            }

        if (bufferNeedsSorting) {
            // sort the buffer by time-stamps
            sortEventBuffer(mSensorEventBuffer, count);
        }

        // handle backward compatibility for RotationVector sensor
@@ -1253,6 +1240,46 @@ bool SensorService::threadLoop() {
    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 @@ bool SensorService::SensorEventAckReceiver::threadLoop() {
    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++) {
+18 −1
Original line number Diff line number Diff line
@@ -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 @@ private:
    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 @@ private:
        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 @@ private:
    // 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 @@ private:
    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 @@ private:
    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;