From b4373ac9f53e3a6edee915715101d535e1a851a1 Mon Sep 17 00:00:00 2001 From: Aravind Akella Date: Wed, 29 Oct 2014 17:55:20 -0700 Subject: [PATCH] Add a timeout for releasing SensorService wake_lock. If SensorService is holding a wake_lock and there are no acknowledgements from ANY app within 5 seconds, release the wake_lock and reset the wake_lock refcounts for all connections. Bug: 16874240 Change-Id: I5e950dd393c20173c439cbd5a4ba614ee09d61f4 --- services/sensorservice/SensorService.cpp | 111 +++++++++++++++++------ services/sensorservice/SensorService.h | 21 ++++- 2 files changed, 102 insertions(+), 30 deletions(-) diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index dc8fa649d..c316ef6eb 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -191,6 +191,8 @@ void SensorService::onFirstRef() mSensorEventScratch = new sensors_event_t[minBufferSize]; mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize]; + mAckReceiver = new SensorEventAckReceiver(this); + mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; run("SensorService", PRIORITY_URGENT_DISPLAY); } @@ -386,8 +388,6 @@ bool SensorService::threadLoop() SensorDevice& device(SensorDevice::getInstance()); const size_t vcount = mVirtualSensorList.size(); - SensorEventAckReceiver sender(this); - sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY); const int halVersion = device.getHalDeviceVersion(); do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax); @@ -408,16 +408,7 @@ bool SensorService::threadLoop() // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for // cleanup. So copy all the strongPointers to a vector before the lock is acquired. SortedVector< sp > activeConnections; - { - Mutex::Autolock _l(mLock); - for (size_t i=0 ; i < mActiveConnections.size(); ++i) { - sp connection(mActiveConnections[i].promote()); - if (connection != 0) { - activeConnections.add(connection); - } - } - } - + populateActiveConnections(&activeConnections); Mutex::Autolock _l(mLock); // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock, @@ -433,8 +424,7 @@ bool SensorService::threadLoop() } if (bufferHasWakeUpEvent && !mWakeLockAcquired) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - mWakeLockAcquired = true; + setWakeLockAcquiredLocked(true); } recordLastValueLocked(mSensorEventBuffer, count); @@ -522,8 +512,7 @@ bool SensorService::threadLoop() } if (mWakeLockAcquired && !needsWakeLock) { - release_wake_lock(WAKE_LOCK_NAME); - mWakeLockAcquired = false; + setWakeLockAcquiredLocked(false); } } while (!Thread::exitPending()); @@ -536,11 +525,52 @@ sp SensorService::getLooper() const { return mLooper; } +void SensorService::resetAllWakeLockRefCounts() { + SortedVector< sp > activeConnections; + populateActiveConnections(&activeConnections); + { + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i < activeConnections.size(); ++i) { + if (activeConnections[i] != 0) { + activeConnections[i]->resetWakeLockRefCount(); + } + } + setWakeLockAcquiredLocked(false); + } +} + +void SensorService::setWakeLockAcquiredLocked(bool acquire) { + if (acquire) { + if (!mWakeLockAcquired) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); + mWakeLockAcquired = true; + } + mLooper->wake(); + } else { + if (mWakeLockAcquired) { + release_wake_lock(WAKE_LOCK_NAME); + mWakeLockAcquired = false; + } + } +} + + +bool SensorService::isWakeLockAcquired() { + Mutex::Autolock _l(mLock); + return mWakeLockAcquired; +} + bool SensorService::SensorEventAckReceiver::threadLoop() { ALOGD("new thread SensorEventAckReceiver"); + sp looper = mService->getLooper(); do { - sp looper = mService->getLooper(); - looper->pollOnce(-1); + bool wakeLockAcquired = mService->isWakeLockAcquired(); + int timeout = -1; + if (wakeLockAcquired) timeout = 5000; + int ret = looper->pollOnce(timeout); + if (ret == ALOOPER_POLL_TIMEOUT) { + mService->resetAllWakeLockRefCounts(); + } } while(!Thread::exitPending()); return false; } @@ -714,10 +744,7 @@ status_t SensorService::enable(const sp& connection, sensors_event_t& event(mLastEventSeen.editValueFor(handle)); if (event.version == sizeof(sensors_event_t)) { if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - mWakeLockAcquired = true; - ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock for on_change sensor %s", - WAKE_LOCK_NAME); + setWakeLockAcquiredLocked(true); } connection->sendEvents(&event, 1, NULL); if (!connection->needsWakeLock() && mWakeLockAcquired) { @@ -922,8 +949,26 @@ void SensorService::checkWakeLockStateLocked() { } } if (releaseLock) { - release_wake_lock(WAKE_LOCK_NAME); - mWakeLockAcquired = false; + setWakeLockAcquiredLocked(false); + } +} + +void SensorService::sendEventsFromCache(const sp& connection) { + Mutex::Autolock _l(mLock); + connection->writeToSocketFromCache(); + if (connection->needsWakeLock()) { + setWakeLockAcquiredLocked(true); + } +} + +void SensorService::populateActiveConnections( + SortedVector< sp >* activeConnections) { + Mutex::Autolock _l(mLock); + for (size_t i=0 ; i < mActiveConnections.size(); ++i) { + sp connection(mActiveConnections[i].promote()); + if (connection != 0) { + activeConnections->add(connection); + } } } @@ -1013,6 +1058,11 @@ bool SensorService::SensorEventConnection::needsWakeLock() { return !mDead && mWakeLockRefCount > 0; } +void SensorService::SensorEventConnection::resetWakeLockRefCount() { + Mutex::Autolock _l(mConnectionLock); + mWakeLockRefCount = 0; +} + void SensorService::SensorEventConnection::dump(String8& result) { Mutex::Autolock _l(mConnectionLock); result.appendFormat("\t WakeLockRefCount %d | uid %d | cache size %d | max cache size %d\n", @@ -1334,11 +1384,14 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { while (flushInfo.mPendingFlushEventsToSend > 0) { const int sensor_handle = mSensorInfo.keyAt(i); flushCompleteEvent.meta_data.sensor = sensor_handle; - if (mService->getSensorFromHandle(sensor_handle).isWakeUpSensor()) { + bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor(); + if (wakeUpSensor) { + ++mWakeLockRefCount; flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; } ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1); if (size < 0) { + if (wakeUpSensor) --mWakeLockRefCount; return; } ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ", @@ -1348,11 +1401,12 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { } } -void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() { +void SensorService::SensorEventConnection::writeToSocketFromCache() { // At a time write at most half the size of the receiver buffer in SensorEventQueue OR // half the size of the socket buffer allocated in BitTube whichever is smaller. const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2, int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2))); + Mutex::Autolock _l(mConnectionLock); // Send pending flush complete events (if any) sendPendingFlushEventsLocked(); for (int numEventsSent = 0; numEventsSent < mCacheSize;) { @@ -1503,9 +1557,8 @@ int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* } if (events & ALOOPER_EVENT_OUTPUT) { - // send sensor data that is stored in mEventCache. - Mutex::Autolock _l(mConnectionLock); - writeToSocketFromCacheLocked(); + // send sensor data that is stored in mEventCache for this connection. + mService->sendEventsFromCache(this); } return 1; } diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 5e3eeb59f..8719487e2 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -101,7 +101,7 @@ class SensorService : void sendPendingFlushEventsLocked(); // Writes events from mEventCache to the socket. - void writeToSocketFromCacheLocked(); + void writeToSocketFromCache(); // Compute the approximate cache size from the FIFO sizes of various sensors registered for // this connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be @@ -182,6 +182,7 @@ class SensorService : void setFirstFlushPending(int32_t handle, bool value); void dump(String8& result); bool needsWakeLock(); + void resetWakeLockRefCount(); uid_t getUid() const { return mUid; } }; @@ -230,12 +231,29 @@ class SensorService : // corresponding applications, if yes the wakelock is released. void checkWakeLockState(); void checkWakeLockStateLocked(); + bool isWakeLockAcquired(); bool isWakeUpSensorEvent(const sensors_event_t& event) const; SensorRecord * getSensorRecord(int handle); sp getLooper() const; + // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if + // SensorService did not receive any acknowledgements from apps which have registered for + // wake_up sensors. + void resetAllWakeLockRefCounts(); + + // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to + // 5 seconds and wake the looper. + void setWakeLockAcquiredLocked(bool acquire); + + // Send events from the event cache for this particular connection. + void sendEventsFromCache(const sp& connection); + + // Promote all weak referecences in mActiveConnections vector to strong references and add them + // to the output vector. + void populateActiveConnections(SortedVector< sp >* activeConnections); + // constants Vector mSensorList; Vector mUserSensorListDebug; @@ -247,6 +265,7 @@ class SensorService : // supported or not. uint32_t mSocketBufferSize; sp mLooper; + sp mAckReceiver; // protected by mLock mutable Mutex mLock;