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

Commit e93fdf9a authored by Stan Rokita's avatar Stan Rokita
Browse files

MH2 | Implement dynamic sensors callbacks on HalProxy

Additionally, have HalProxyCallback::processEvents use
HalProxy::setSubHalIndex static method instead of its own helper.
Add unit tests to test the dynamic sensor methods.

Bug: 136511617
Test: New unit tests are passing.
Change-Id: Ib903291a83df2fafa480082f9305c594bd325f79
parent 8beed0b7
Loading
Loading
Loading
Loading
+53 −11
Original line number Diff line number Diff line
@@ -38,6 +38,18 @@ using ::android::hardware::sensors::V2_0::EventQueueFlagBits;

typedef ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*);

/**
 * Set the subhal index as first byte of sensor handle and return this modified version.
 *
 * @param sensorHandle The sensor handle to modify.
 * @param subHalIndex The index in the hal proxy of the sub hal this sensor belongs to.
 *
 * @return The modified sensor handle.
 */
uint32_t setSubHalIndex(uint32_t sensorHandle, size_t subHalIndex) {
    return sensorHandle | (subHalIndex << 24);
}

HalProxy::HalProxy() {
    const char* kMultiHalConfigFile = "/vendor/etc/sensors/hals.conf";
    initializeSubHalListFromConfigFile(kMultiHalConfigFile);
@@ -206,15 +218,45 @@ Return<void> HalProxy::debug(const hidl_handle& /* fd */, const hidl_vec<hidl_st
    return Return<void>();
}

Return<void> HalProxy::onDynamicSensorsConnected(
        const hidl_vec<SensorInfo>& /* dynamicSensorsAdded */, int32_t /* subHalIndex */) {
    // TODO: Map the SensorInfo to the global list and then invoke the framework's callback.
Return<void> HalProxy::onDynamicSensorsConnected(const hidl_vec<SensorInfo>& dynamicSensorsAdded,
                                                 int32_t subHalIndex) {
    std::vector<SensorInfo> sensors;
    {
        std::lock_guard<std::mutex> lock(mDynamicSensorsMutex);
        for (SensorInfo sensor : dynamicSensorsAdded) {
            if (!subHalIndexIsClear(sensor.sensorHandle)) {
                ALOGE("Dynamic sensor added %s had sensorHandle with first byte not 0.",
                      sensor.name.c_str());
            } else {
                sensor.sensorHandle = setSubHalIndex(sensor.sensorHandle, subHalIndex);
                mDynamicSensors[sensor.sensorHandle] = sensor;
                sensors.push_back(sensor);
            }
        }
    }
    mDynamicSensorsCallback->onDynamicSensorsConnected(sensors);
    return Return<void>();
}

Return<void> HalProxy::onDynamicSensorsDisconnected(
        const hidl_vec<int32_t>& /* dynamicSensorHandlesRemoved */, int32_t /* subHalIndex */) {
    // TODO: Unmap the SensorInfo from the global list and then invoke the framework's callback.
        const hidl_vec<int32_t>& dynamicSensorHandlesRemoved, int32_t subHalIndex) {
    // TODO: Block this call until all pending events are flushed from queue
    std::vector<int32_t> sensorHandles;
    {
        std::lock_guard<std::mutex> lock(mDynamicSensorsMutex);
        for (int32_t sensorHandle : dynamicSensorHandlesRemoved) {
            if (!subHalIndexIsClear(sensorHandle)) {
                ALOGE("Dynamic sensorHandle removed had first byte not 0.");
            } else {
                sensorHandle = setSubHalIndex(sensorHandle, subHalIndex);
                if (mDynamicSensors.find(sensorHandle) != mDynamicSensors.end()) {
                    mDynamicSensors.erase(sensorHandle);
                    sensorHandles.push_back(sensorHandle);
                }
            }
        }
    }
    mDynamicSensorsCallback->onDynamicSensorsDisconnected(sensorHandles);
    return Return<void>();
}

@@ -264,7 +306,7 @@ void HalProxy::initializeSensorList() {
        ISensorsSubHal* subHal = mSubHalList[subHalIndex];
        auto result = subHal->getSensorsList([&](const auto& list) {
            for (SensorInfo sensor : list) {
                if ((sensor.sensorHandle & kSensorHandleSubHalIndexMask) != 0) {
                if (!subHalIndexIsClear(sensor.sensorHandle)) {
                    ALOGE("SubHal sensorHandle's first byte was not 0");
                } else {
                    ALOGV("Loaded sensor: %s", sensor.name.c_str());
@@ -389,6 +431,10 @@ uint32_t HalProxy::clearSubHalIndex(uint32_t sensorHandle) {
    return sensorHandle & (~kSensorHandleSubHalIndexMask);
}

bool HalProxy::subHalIndexIsClear(uint32_t sensorHandle) {
    return (sensorHandle & kSensorHandleSubHalIndexMask) == 0;
}

void HalProxyCallback::postEvents(const std::vector<Event>& events, ScopedWakelock wakelock) {
    (void)wakelock;
    size_t numWakeupEvents;
@@ -418,7 +464,7 @@ std::vector<Event> HalProxyCallback::processEvents(const std::vector<Event>& eve
    std::vector<Event> eventsOut;
    *numWakeupEvents = 0;
    for (Event event : events) {
        event.sensorHandle = setSubHalIndex(event.sensorHandle);
        event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex);
        eventsOut.push_back(event);
        if ((mHalProxy->getSensorInfo(event.sensorHandle).flags & V1_0::SensorFlagBits::WAKE_UP) !=
            0) {
@@ -428,10 +474,6 @@ std::vector<Event> HalProxyCallback::processEvents(const std::vector<Event>& eve
    return eventsOut;
}

uint32_t HalProxyCallback::setSubHalIndex(uint32_t sensorHandle) const {
    return sensorHandle | mSubHalIndex << 24;
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace sensors
+13 −2
Original line number Diff line number Diff line
@@ -176,6 +176,9 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter {
     */
    std::map<uint32_t, SensorInfo> mSensors;

    //! Map of the dynamic sensors that have been added to halproxy.
    std::map<uint32_t, SensorInfo> mDynamicSensors;

    //! The current operation mode for all subhals.
    OperationMode mCurrentOperationMode = OperationMode::NORMAL;

@@ -212,6 +215,9 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter {
    //! The bool indicating whether to end the pending writes background thread or not
    bool mPendingWritesRun = true;

    //! The mutex protecting access to the dynamic sensors added and removed methods.
    std::mutex mDynamicSensorsMutex;

    /**
     * Initialize the list of SubHal objects in mSubHalList by reading from dynamic libraries
     * listed in a config file.
@@ -271,6 +277,13 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter {
     * @return The modified version of the sensor handle.
     */
    static uint32_t clearSubHalIndex(uint32_t sensorHandle);

    /**
     * @param sensorHandle The sensor handle to modify.
     *
     * @return true if subHalIndex byte of sensorHandle is zeroed.
     */
    static bool subHalIndexIsClear(uint32_t sensorHandle);
};

/**
@@ -303,8 +316,6 @@ class HalProxyCallback : public IHalProxyCallback {

    std::vector<Event> processEvents(const std::vector<Event>& events,
                                     size_t* numWakeupEvents) const;

    uint32_t setSubHalIndex(uint32_t sensorHandle) const;
};

}  // namespace implementation
+135 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "SensorsSubHal.h"

#include <chrono>
#include <set>
#include <thread>
#include <vector>

@@ -38,6 +39,7 @@ using ::android::hardware::sensors::V1_0::SensorType;
using ::android::hardware::sensors::V2_0::ISensorsCallback;
using ::android::hardware::sensors::V2_0::implementation::HalProxy;
using ::android::hardware::sensors::V2_0::implementation::HalProxyCallback;
using ::android::hardware::sensors::V2_0::subhal::implementation::AddAndRemoveDynamicSensorsSubHal;
using ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal;
using ::android::hardware::sensors::V2_0::subhal::implementation::
        AllSupportDirectChannelSensorsSubHal;
@@ -68,6 +70,34 @@ class SensorsCallback : public ISensorsCallback {
    }
};

// The sensors callback that expects a variable list of sensors to be added
class TestSensorsCallback : public ISensorsCallback {
  public:
    Return<void> onDynamicSensorsConnected(
            const hidl_vec<SensorInfo>& dynamicSensorsAdded) override {
        mSensorsConnected.insert(mSensorsConnected.end(), dynamicSensorsAdded.begin(),
                                 dynamicSensorsAdded.end());
        return Return<void>();
    }

    Return<void> onDynamicSensorsDisconnected(
            const hidl_vec<int32_t>& dynamicSensorHandlesRemoved) override {
        mSensorHandlesDisconnected.insert(mSensorHandlesDisconnected.end(),
                                          dynamicSensorHandlesRemoved.begin(),
                                          dynamicSensorHandlesRemoved.end());
        return Return<void>();
    }

    const std::vector<SensorInfo>& getSensorsConnected() const { return mSensorsConnected; }
    const std::vector<int32_t>& getSensorHandlesDisconnected() const {
        return mSensorHandlesDisconnected;
    }

  private:
    std::vector<SensorInfo> mSensorsConnected;
    std::vector<int32_t> mSensorHandlesDisconnected;
};

// Helper declarations follow

/**
@@ -129,6 +159,20 @@ std::vector<Event> makeMultipleProximityEvents(size_t numEvents);
 */
std::vector<Event> makeMultipleAccelerometerEvents(size_t numEvents);

/**
 * Given a SensorInfo vector and a sensor handles vector populate 'sensors' with SensorInfo
 * objects that have the sensorHandle property set to int32_ts from start to start + size
 * (exclusive) and push those sensorHandles also onto 'sensorHandles'.
 *
 * @param start The starting sensorHandle value.
 * @param size The ending (not included) sensorHandle value.
 * @param sensors The SensorInfo object vector reference to push_back to.
 * @param sensorHandles The sensor handles int32_t vector reference to push_back to.
 */
void makeSensorsAndSensorHandlesStartingAndOfSize(int32_t start, size_t size,
                                                  std::vector<SensorInfo>& sensors,
                                                  std::vector<int32_t>& sensorHandles);

// Tests follow
TEST(HalProxyTest, GetSensorsListOneSubHalTest) {
    AllSensorsSubHal subHal;
@@ -396,6 +440,83 @@ TEST(HalProxyTest, DestructingWithEventsPendingOnBackgroundThreadTest) {
    // If this TEST completes then it was a success, if it hangs we will see a crash
}

TEST(HalProxyTest, DynamicSensorsConnectedTest) {
    constexpr size_t kNumSensors = 3;
    AddAndRemoveDynamicSensorsSubHal subHal;
    std::vector<ISensorsSubHal*> subHals{&subHal};
    HalProxy proxy(subHals);
    std::unique_ptr<EventMessageQueue> eventQueue = std::make_unique<EventMessageQueue>(0, true);
    std::unique_ptr<WakeupMessageQueue> wakeLockQueue =
            std::make_unique<WakeupMessageQueue>(0, true);

    std::vector<SensorInfo> sensorsToConnect;
    std::vector<int32_t> sensorHandlesToExpect;
    makeSensorsAndSensorHandlesStartingAndOfSize(1, kNumSensors, sensorsToConnect,
                                                 sensorHandlesToExpect);

    TestSensorsCallback* callback = new TestSensorsCallback();
    ::android::sp<ISensorsCallback> callbackPtr = callback;
    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
    subHal.addDynamicSensors(sensorsToConnect);

    std::vector<SensorInfo> sensorsSeen = callback->getSensorsConnected();
    EXPECT_EQ(kNumSensors, sensorsSeen.size());
    for (size_t i = 0; i < kNumSensors; i++) {
        auto sensorHandleSeen = sensorsSeen[i].sensorHandle;
        // Note since only one subhal we do not need to change first byte for expected
        auto sensorHandleExpected = sensorHandlesToExpect[i];
        EXPECT_EQ(sensorHandleSeen, sensorHandleExpected);
    }
}

TEST(HalProxyTest, DynamicSensorsDisconnectedTest) {
    constexpr size_t kNumSensors = 3;
    AddAndRemoveDynamicSensorsSubHal subHal;
    std::vector<ISensorsSubHal*> subHals{&subHal};
    HalProxy proxy(subHals);
    std::unique_ptr<EventMessageQueue> eventQueue = std::make_unique<EventMessageQueue>(0, true);
    std::unique_ptr<WakeupMessageQueue> wakeLockQueue =
            std::make_unique<WakeupMessageQueue>(0, true);

    std::vector<SensorInfo> sensorsToConnect;
    std::vector<int32_t> sensorHandlesToExpect;
    makeSensorsAndSensorHandlesStartingAndOfSize(20, kNumSensors, sensorsToConnect,
                                                 sensorHandlesToExpect);

    std::vector<int32_t> nonDynamicSensorHandles;
    for (int32_t sensorHandle = 1; sensorHandle < 10; sensorHandle++) {
        nonDynamicSensorHandles.push_back(sensorHandle);
    }

    std::set<int32_t> nonDynamicSensorHandlesSet(nonDynamicSensorHandles.begin(),
                                                 nonDynamicSensorHandles.end());

    std::vector<int32_t> sensorHandlesToAttemptToRemove;
    sensorHandlesToAttemptToRemove.insert(sensorHandlesToAttemptToRemove.end(),
                                          sensorHandlesToExpect.begin(),
                                          sensorHandlesToExpect.end());
    sensorHandlesToAttemptToRemove.insert(sensorHandlesToAttemptToRemove.end(),
                                          nonDynamicSensorHandles.begin(),
                                          nonDynamicSensorHandles.end());

    TestSensorsCallback* callback = new TestSensorsCallback();
    ::android::sp<ISensorsCallback> callbackPtr = callback;
    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
    subHal.addDynamicSensors(sensorsToConnect);
    subHal.removeDynamicSensors(sensorHandlesToAttemptToRemove);

    std::vector<int32_t> sensorHandlesSeen = callback->getSensorHandlesDisconnected();
    EXPECT_EQ(kNumSensors, sensorHandlesSeen.size());
    for (size_t i = 0; i < kNumSensors; i++) {
        auto sensorHandleSeen = sensorHandlesSeen[i];
        // Note since only one subhal we do not need to change first byte for expected
        auto sensorHandleExpected = sensorHandlesToExpect[i];
        EXPECT_EQ(sensorHandleSeen, sensorHandleExpected);
        EXPECT_TRUE(nonDynamicSensorHandlesSet.find(sensorHandleSeen) ==
                    nonDynamicSensorHandlesSet.end());
    }
}

// Helper implementations follow
void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
                                       const std::vector<SensorInfo>& subHalSensorsList) {
@@ -463,4 +584,18 @@ std::vector<Event> makeMultipleAccelerometerEvents(size_t numEvents) {
    return events;
}

void makeSensorsAndSensorHandlesStartingAndOfSize(int32_t start, size_t size,
                                                  std::vector<SensorInfo>& sensors,
                                                  std::vector<int32_t>& sensorHandles) {
    for (int32_t sensorHandle = start; sensorHandle < start + static_cast<int32_t>(size);
         sensorHandle++) {
        SensorInfo sensor;
        // Just set the sensorHandle field to the correct value so as to not have
        // to compare every field
        sensor.sensorHandle = sensorHandle;
        sensors.push_back(sensor);
        sensorHandles.push_back(sensorHandle);
    }
}

}  // namespace
+10 −0
Original line number Diff line number Diff line
@@ -221,6 +221,16 @@ Return<void> DoesNotSupportDirectChannelSensorsSubHal::getSensorsList(getSensors
    return Void();
}

void AddAndRemoveDynamicSensorsSubHal::addDynamicSensors(
        const std::vector<SensorInfo>& sensorsAdded) {
    mCallback->onDynamicSensorsConnected(sensorsAdded);
}

void AddAndRemoveDynamicSensorsSubHal::removeDynamicSensors(
        const std::vector<int32_t>& sensorHandlesRemoved) {
    mCallback->onDynamicSensorsDisconnected(sensorHandlesRemoved);
}

}  // namespace implementation
}  // namespace subhal
}  // namespace V2_0
+13 −7
Original line number Diff line number Diff line
@@ -98,13 +98,6 @@ class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback {
     */
    std::map<int32_t, std::shared_ptr<Sensor>> mSensors;

  private:
    /**
     * The current operation mode of the multihal framework. Ensures that all subhals are set to
     * the same operation mode.
     */
    OperationMode mCurrentOperationMode = OperationMode::NORMAL;

    /**
     * Callback used to communicate to the HalProxy when dynamic sensors are connected /
     * disconnected, sensor events need to be sent to the framework, and when a wakelock should be
@@ -112,6 +105,13 @@ class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback {
     */
    sp<IHalProxyCallback> mCallback;

  private:
    /**
     * The current operation mode of the multihal framework. Ensures that all subhals are set to
     * the same operation mode.
     */
    OperationMode mCurrentOperationMode = OperationMode::NORMAL;

    /**
     * The next available sensor handle
     */
@@ -151,6 +151,12 @@ class DoesNotSupportDirectChannelSensorsSubHal : public AllSensorsSubHal {
    Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
};

class AddAndRemoveDynamicSensorsSubHal : public AllSensorsSubHal {
  public:
    void addDynamicSensors(const std::vector<SensorInfo>& sensorsAdded);
    void removeDynamicSensors(const std::vector<int32_t>& sensorHandlesAdded);
};

}  // namespace implementation
}  // namespace subhal
}  // namespace V2_0