mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 22:04:26 +00:00
MH2 | Add restart logic in HalProxy::initialize method.
Bug: 136511617 Test: None yet Change-Id: I389a7243d3612586aae4e8a802afda92af8dcc6d
This commit is contained in:
@@ -65,15 +65,7 @@ HalProxy::HalProxy(std::vector<ISensorsSubHal*>& subHalList) : mSubHalList(subHa
|
||||
}
|
||||
|
||||
HalProxy::~HalProxy() {
|
||||
mThreadsRun.store(false);
|
||||
mWakelockCV.notify_one();
|
||||
mEventQueueWriteCV.notify_one();
|
||||
if (mPendingWritesThread.joinable()) {
|
||||
mPendingWritesThread.join();
|
||||
}
|
||||
if (mWakelockThread.joinable()) {
|
||||
mWakelockThread.join();
|
||||
}
|
||||
stopThreads();
|
||||
}
|
||||
|
||||
Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) {
|
||||
@@ -119,8 +111,18 @@ Return<Result> HalProxy::initialize(
|
||||
const sp<ISensorsCallback>& sensorsCallback) {
|
||||
Result result = Result::OK;
|
||||
|
||||
// TODO: clean up sensor requests, if not already done elsewhere through a death recipient, and
|
||||
// clean up any other resources that exist (FMQs, flags, threads, etc.)
|
||||
stopThreads();
|
||||
resetSharedWakelock();
|
||||
|
||||
// So that the pending write events queue can be cleared safely and when we start threads
|
||||
// again we do not get new events until after initialize resets the subhals.
|
||||
disableAllSensors();
|
||||
|
||||
// Clears the queue if any events were pending write before.
|
||||
mPendingWriteEventsQueue = std::queue<std::pair<std::vector<Event>, size_t>>();
|
||||
|
||||
// Clears previously connected dynamic sensors
|
||||
mDynamicSensors.clear();
|
||||
|
||||
mDynamicSensorsCallback = sensorsCallback;
|
||||
|
||||
@@ -128,21 +130,29 @@ Return<Result> HalProxy::initialize(
|
||||
mEventQueue =
|
||||
std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);
|
||||
|
||||
// Create the EventFlag that is used to signal to the framework that sensor events have been
|
||||
// written to the Event FMQ
|
||||
if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
|
||||
result = Result::BAD_VALUE;
|
||||
}
|
||||
|
||||
// Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP
|
||||
// events have been successfully read and handled by the framework.
|
||||
mWakeLockQueue =
|
||||
std::make_unique<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);
|
||||
|
||||
if (mEventQueueFlag != nullptr) {
|
||||
EventFlag::deleteEventFlag(&mEventQueueFlag);
|
||||
}
|
||||
if (mWakelockQueueFlag != nullptr) {
|
||||
EventFlag::deleteEventFlag(&mWakelockQueueFlag);
|
||||
}
|
||||
if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
|
||||
result = Result::BAD_VALUE;
|
||||
}
|
||||
if (EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakelockQueueFlag) != OK) {
|
||||
result = Result::BAD_VALUE;
|
||||
}
|
||||
if (!mDynamicSensorsCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
|
||||
result = Result::BAD_VALUE;
|
||||
}
|
||||
|
||||
mThreadsRun.store(true);
|
||||
|
||||
mPendingWritesThread = std::thread(startPendingWritesThread, this);
|
||||
mWakelockThread = std::thread(startWakelockThread, this);
|
||||
|
||||
@@ -157,6 +167,8 @@ Return<Result> HalProxy::initialize(
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentOperationMode = OperationMode::NORMAL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -331,6 +343,41 @@ void HalProxy::init() {
|
||||
initializeSensorList();
|
||||
}
|
||||
|
||||
void HalProxy::stopThreads() {
|
||||
mThreadsRun.store(false);
|
||||
if (mEventQueueFlag != nullptr && mEventQueue != nullptr) {
|
||||
size_t numToRead = mEventQueue->availableToRead();
|
||||
std::vector<Event> events(numToRead);
|
||||
mEventQueue->read(events.data(), numToRead);
|
||||
mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ));
|
||||
}
|
||||
if (mWakelockQueueFlag != nullptr && mWakeLockQueue != nullptr) {
|
||||
uint32_t kZero = 0;
|
||||
mWakeLockQueue->write(&kZero);
|
||||
mWakelockQueueFlag->wake(static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN));
|
||||
}
|
||||
mWakelockCV.notify_one();
|
||||
mEventQueueWriteCV.notify_one();
|
||||
if (mPendingWritesThread.joinable()) {
|
||||
mPendingWritesThread.join();
|
||||
}
|
||||
if (mWakelockThread.joinable()) {
|
||||
mWakelockThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
void HalProxy::disableAllSensors() {
|
||||
for (const auto& sensorEntry : mSensors) {
|
||||
int32_t sensorHandle = sensorEntry.first;
|
||||
activate(sensorHandle, false /* enabled */);
|
||||
}
|
||||
std::lock_guard<std::mutex> dynamicSensorsLock(mDynamicSensorsMutex);
|
||||
for (const auto& sensorEntry : mDynamicSensors) {
|
||||
int32_t sensorHandle = sensorEntry.first;
|
||||
activate(sensorHandle, false /* enabled */);
|
||||
}
|
||||
}
|
||||
|
||||
void HalProxy::startPendingWritesThread(HalProxy* halProxy) {
|
||||
halProxy->handlePendingWrites();
|
||||
}
|
||||
@@ -347,8 +394,6 @@ void HalProxy::handlePendingWrites() {
|
||||
size_t eventQueueSize = mEventQueue->getQuantumCount();
|
||||
size_t numToWrite = std::min(pendingWriteEvents.size(), eventQueueSize);
|
||||
lock.unlock();
|
||||
// TODO: Find a way to interrup writeBlocking if the thread should exit
|
||||
// so we don't have to wait for timeout on framework restarts.
|
||||
if (!mEventQueue->writeBlocking(
|
||||
pendingWriteEvents.data(), numToWrite,
|
||||
static_cast<uint32_t>(EventQueueFlagBits::EVENTS_READ),
|
||||
|
||||
@@ -149,9 +149,13 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter {
|
||||
std::unique_ptr<WakeLockMessageQueue> mWakeLockQueue;
|
||||
|
||||
/**
|
||||
* Event Flag to signal to the framework when sensor events are available to be read
|
||||
* Event Flag to signal to the framework when sensor events are available to be read and to
|
||||
* interrupt event queue blocking write.
|
||||
*/
|
||||
EventFlag* mEventQueueFlag;
|
||||
EventFlag* mEventQueueFlag = nullptr;
|
||||
|
||||
//! Event Flag to signal internally that the wakelock queue should stop its blocking read.
|
||||
EventFlag* mWakelockQueueFlag = nullptr;
|
||||
|
||||
/**
|
||||
* Callback to the sensors framework to inform it that new sensors have been added or removed.
|
||||
@@ -253,6 +257,16 @@ class HalProxy : public ISensors, public IScopedWakelockRefCounter {
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Stops all threads by setting the threads running flag to false and joining to them.
|
||||
*/
|
||||
void stopThreads();
|
||||
|
||||
/**
|
||||
* Disable all the sensors observed by the HalProxy.
|
||||
*/
|
||||
void disableAllSensors();
|
||||
|
||||
/**
|
||||
* Starts the thread that handles pending writes to event fmq.
|
||||
*
|
||||
|
||||
@@ -130,11 +130,13 @@ class ISensorsSubHal : public ISensors {
|
||||
virtual const std::string getName() = 0;
|
||||
|
||||
/**
|
||||
* First method invoked on the sub-HAL after it's allocated through sensorsHalGetSubHal() by the
|
||||
* HalProxy. Sub-HALs should use this to initialize any state and retain the callback given in
|
||||
* order to communicate with the HalProxy. Method will be called anytime the sensors framework
|
||||
* restarts. Therefore, this method will be responsible for reseting the state of the subhal and
|
||||
* cleaning up and reallocating any previously allocated data.
|
||||
* This is the first method invoked on the sub-HAL after it's allocated through
|
||||
* sensorsHalGetSubHal() by the HalProxy. Sub-HALs should use this to initialize any state and
|
||||
* retain the callback given in order to communicate with the HalProxy. Method will be called
|
||||
* anytime the sensors framework restarts. Therefore, this method will be responsible for
|
||||
* reseting the state of the subhal and cleaning up and reallocating any previously allocated
|
||||
* data. Initialize should ensure that the subhal has reset its operation mode to NORMAL state
|
||||
* as well.
|
||||
*
|
||||
* @param halProxyCallback callback used to inform the HalProxy when a dynamic sensor's state
|
||||
* changes, new sensor events should be sent to the framework, and when a new ScopedWakelock
|
||||
|
||||
@@ -432,7 +432,7 @@ TEST(HalProxyTest, PostEventsMultipleSubhalsThreaded) {
|
||||
EXPECT_EQ(eventQueue->availableToRead(), kNumEvents * 2);
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, DestructingWithEventsPendingOnBackgroundThreadTest) {
|
||||
TEST(HalProxyTest, DestructingWithEventsPendingOnBackgroundThread) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
constexpr size_t kNumEvents = 6;
|
||||
AllSensorsSubHal subHal;
|
||||
@@ -447,13 +447,145 @@ TEST(HalProxyTest, DestructingWithEventsPendingOnBackgroundThreadTest) {
|
||||
std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
|
||||
subHal.postEvents(events, false /* wakeup */);
|
||||
|
||||
// Sleep for a half second so that background thread has time to attempt it's blocking write
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||
// Destructing HalProxy object with events on the background thread
|
||||
}
|
||||
|
||||
// Should see a 5 second wait for blocking write timeout here
|
||||
TEST(HalProxyTest, DestructingWithUnackedWakeupEventsPosted) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
AllSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> subHals{&subHal};
|
||||
|
||||
// Should be one events left on pending writes queue here and proxy will destruct
|
||||
// If this TEST completes then it was a success, if it hangs we will see a crash
|
||||
std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
|
||||
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
::android::sp<ISensorsCallback> callback = new SensorsCallback();
|
||||
HalProxy proxy(subHals);
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
|
||||
std::vector<Event> events{makeProximityEvent()};
|
||||
subHal.postEvents(events, true /* wakeup */);
|
||||
|
||||
// Not sending any acks back through wakeLockQueue
|
||||
|
||||
// Destructing HalProxy object with unacked wakeup events posted
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, ReinitializeWithEventsPendingOnBackgroundThread) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
constexpr size_t kNumEvents = 10;
|
||||
AllSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> subHals{&subHal};
|
||||
|
||||
std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
|
||||
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
::android::sp<ISensorsCallback> callback = new SensorsCallback();
|
||||
HalProxy proxy(subHals);
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
|
||||
std::vector<Event> events = makeMultipleAccelerometerEvents(kNumEvents);
|
||||
subHal.postEvents(events, false /* wakeup */);
|
||||
|
||||
eventQueue = makeEventFMQ(kQueueSize);
|
||||
wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
|
||||
Result secondInitResult =
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
EXPECT_EQ(secondInitResult, Result::OK);
|
||||
// Small sleep so that pending writes thread has a change to hit writeBlocking call.
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
||||
Event eventOut;
|
||||
EXPECT_FALSE(eventQueue->read(&eventOut));
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, ReinitializingWithUnackedWakeupEventsPosted) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
AllSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> subHals{&subHal};
|
||||
|
||||
std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
|
||||
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
::android::sp<ISensorsCallback> callback = new SensorsCallback();
|
||||
HalProxy proxy(subHals);
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
|
||||
std::vector<Event> events{makeProximityEvent()};
|
||||
subHal.postEvents(events, true /* wakeup */);
|
||||
|
||||
// Not sending any acks back through wakeLockQueue
|
||||
|
||||
eventQueue = makeEventFMQ(kQueueSize);
|
||||
wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
|
||||
Result secondInitResult =
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
EXPECT_EQ(secondInitResult, Result::OK);
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, InitializeManyTimesInARow) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
constexpr size_t kNumTimesToInit = 100;
|
||||
AllSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> subHals{&subHal};
|
||||
|
||||
std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
|
||||
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
::android::sp<ISensorsCallback> callback = new SensorsCallback();
|
||||
HalProxy proxy(subHals);
|
||||
|
||||
for (size_t i = 0; i < kNumTimesToInit; i++) {
|
||||
Result secondInitResult =
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
EXPECT_EQ(secondInitResult, Result::OK);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, OperationModeResetOnInitialize) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
AllSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> subHals{&subHal};
|
||||
std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
|
||||
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
::android::sp<ISensorsCallback> callback = new SensorsCallback();
|
||||
HalProxy proxy(subHals);
|
||||
proxy.setOperationMode(OperationMode::DATA_INJECTION);
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
|
||||
Event event = makeAccelerometerEvent();
|
||||
// Should not be able to inject a non AdditionInfo type event because operation mode should
|
||||
// have been reset to NORMAL
|
||||
EXPECT_EQ(proxy.injectSensorData(event), Result::BAD_VALUE);
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, DynamicSensorsDiscardedOnInitialize) {
|
||||
constexpr size_t kQueueSize = 5;
|
||||
constexpr size_t kNumSensors = 5;
|
||||
AddAndRemoveDynamicSensorsSubHal subHal;
|
||||
std::vector<ISensorsSubHal*> subHals{&subHal};
|
||||
std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
|
||||
std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
|
||||
HalProxy proxy(subHals);
|
||||
|
||||
std::vector<SensorInfo> sensorsToConnect;
|
||||
std::vector<int32_t> sensorHandlesToAttemptToRemove;
|
||||
makeSensorsAndSensorHandlesStartingAndOfSize(1, kNumSensors, sensorsToConnect,
|
||||
sensorHandlesToAttemptToRemove);
|
||||
|
||||
std::vector<int32_t> nonDynamicSensorHandles;
|
||||
for (int32_t sensorHandle = 1; sensorHandle < 10; sensorHandle++) {
|
||||
nonDynamicSensorHandles.push_back(sensorHandle);
|
||||
}
|
||||
|
||||
TestSensorsCallback* callback = new TestSensorsCallback();
|
||||
::android::sp<ISensorsCallback> callbackPtr = callback;
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
|
||||
subHal.addDynamicSensors(sensorsToConnect);
|
||||
|
||||
proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callbackPtr);
|
||||
subHal.removeDynamicSensors(sensorHandlesToAttemptToRemove);
|
||||
|
||||
std::vector<int32_t> sensorHandlesActuallyRemoved = callback->getSensorHandlesDisconnected();
|
||||
|
||||
// Should not have received the sensorHandles for any dynamic sensors that were removed since
|
||||
// all of them should have been removed in the second initialize call.
|
||||
EXPECT_TRUE(sensorHandlesActuallyRemoved.empty());
|
||||
}
|
||||
|
||||
TEST(HalProxyTest, DynamicSensorsConnectedTest) {
|
||||
|
||||
@@ -158,6 +158,7 @@ Return<void> SensorsSubHal::debug(const hidl_handle& fd, const hidl_vec<hidl_str
|
||||
|
||||
Return<Result> SensorsSubHal::initialize(const sp<IHalProxyCallback>& halProxyCallback) {
|
||||
mCallback = halProxyCallback;
|
||||
setOperationMode(OperationMode::NORMAL);
|
||||
return Result::OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user