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
This commit is contained in:
parent
8beed0b7be
commit
e93fdf9a4a
5 changed files with 224 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue