diff options
author | Aravind Akella <aakella@google.com> | 2014-02-11 18:58:52 -0800 |
---|---|---|
committer | Aravind Akella <aakella@google.com> | 2014-04-23 14:38:56 -0700 |
commit | 9a844cf78f09953145200b4074d47589257a408c (patch) | |
tree | 8168fc7ede93ec3e6c7567f8d24215ae1820e858 /services/sensorservice | |
parent | 4cbf3c53447215a31f69d3ac615ba0daa902f717 (diff) | |
download | frameworks_native-9a844cf78f09953145200b4074d47589257a408c.zip frameworks_native-9a844cf78f09953145200b4074d47589257a408c.tar.gz frameworks_native-9a844cf78f09953145200b4074d47589257a408c.tar.bz2 |
Enable wakeup sensors.
SensorService should hold a wakelock till the app reads events from a wakeup sensor. Currently drivers hold a wakelock with a
timeout while delivering events from a wake up sensor like Significant Motion. This hack can be removed now.
Bug: 9774884
Change-Id: If3b5acb99c9cf0cd29012fcfa9d6b04c74133d01
Diffstat (limited to 'services/sensorservice')
-rw-r--r-- | services/sensorservice/SensorDevice.cpp | 2 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 170 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 31 |
3 files changed, 141 insertions, 62 deletions
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 3b64f0a..01dbdfb 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -309,7 +309,7 @@ int SensorDevice::getHalDeviceVersion() const { return mSensorDevice->common.version; } -status_t SensorDevice::flush(void* /*ident*/, int handle) { +status_t SensorDevice::flush(void* ident, int handle) { if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) { return INVALID_OPERATION; } diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 8837a4d..aff4e9a 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -164,6 +164,7 @@ void SensorService::onFirstRef() fclose(fp); } + mWakeLockAcquired = false; run("SensorService", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; } @@ -284,6 +285,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/) } result.appendFormat("%zu Max Socket Buffer size\n", mSocketBufferSize); + result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held"); result.appendFormat("%zd active connections\n", mActiveConnections.size()); for (size_t i=0 ; i < mActiveConnections.size() ; i++) { @@ -298,7 +300,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/) return NO_ERROR; } -void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, +void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count) { SensorInterface* sensor; status_t err = NO_ERROR; @@ -311,7 +313,7 @@ void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& c if (sensor != NULL) { sensor->autoDisable(connection.get(), handle); } - cleanupWithoutDisable(connection, handle); + cleanupWithoutDisableLocked(connection, handle); } } } @@ -333,7 +335,6 @@ bool SensorService::threadLoop() const size_t vcount = mVirtualSensorList.size(); ssize_t count; - bool wakeLockAcquired = false; const int halVersion = device.getHalDeviceVersion(); do { count = device.poll(buffer, numEventMax); @@ -341,26 +342,31 @@ bool SensorService::threadLoop() ALOGE("sensor poll failed (%s)", strerror(-count)); break; } - - // Poll has returned. Hold a wakelock. - // Todo(): add a flag to the sensors definitions to indicate - // the sensors which can wake up the AP + 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, + // sending events to clients (incrementing SensorEventConnection::mWakeLockRefCount) should + // not be interleaved with decrementing SensorEventConnection::mWakeLockRefCount and + // releasing the wakelock. + bool bufferHasWakeUpEvent = false; for (int i = 0; i < count; i++) { - if (buffer[i].type == SENSOR_TYPE_SIGNIFICANT_MOTION) { - acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); - wakeLockAcquired = true; - break; + if (isWakeUpSensorEvent(buffer[i])) { + bufferHasWakeUpEvent = true; + break; } } - recordLastValue(buffer, count); + if (bufferHasWakeUpEvent && !mWakeLockAcquired) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); + mWakeLockAcquired = true; + ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock %s", WAKE_LOCK_NAME); + } + recordLastValueLocked(buffer, count); // handle virtual sensors if (count && vcount) { sensors_event_t const * const event = buffer; - const DefaultKeyedVector<int, SensorInterface*> virtualSensors( - getActiveVirtualSensors()); - const size_t activeVirtualSensorCount = virtualSensors.size(); + const size_t activeVirtualSensorCount = mActiveVirtualSensors.size(); if (activeVirtualSensorCount) { size_t k = 0; SensorFusion& fusion(SensorFusion::getInstance()); @@ -378,7 +384,7 @@ bool SensorService::threadLoop() break; } sensors_event_t out; - SensorInterface* si = virtualSensors.valueAt(j); + SensorInterface* si = mActiveVirtualSensors.valueAt(j); if (si->process(&out, event[i])) { buffer[count + k] = out; k++; @@ -387,7 +393,7 @@ bool SensorService::threadLoop() } if (k) { // record the last synthesized values - recordLastValue(&buffer[count], k); + recordLastValueLocked(&buffer[count], k); count += k; // sort the buffer by time-stamps sortEventBuffer(buffer, count); @@ -406,22 +412,24 @@ bool SensorService::threadLoop() } } - // send our events to clients... - const SortedVector< wp<SensorEventConnection> > activeConnections( - getActiveConnections()); - size_t numConnections = activeConnections.size(); - for (size_t i=0 ; i<numConnections ; i++) { - sp<SensorEventConnection> connection( - activeConnections[i].promote()); + // Send our events to clients. Check the state of wake lock for each client and release the + // lock if none of the clients need it. + bool needsWakeLock = false; + for (size_t i=0 ; i < mActiveConnections.size(); i++) { + sp<SensorEventConnection> connection(mActiveConnections[i].promote()); if (connection != 0) { connection->sendEvents(buffer, count, scratch); + needsWakeLock |= connection->needsWakeLock(); // Some sensors need to be auto disabled after the trigger - cleanupAutoDisabledSensor(connection, buffer, count); + cleanupAutoDisabledSensorLocked(connection, buffer, count); } } - // We have read the data, upper layers should hold the wakelock. - if (wakeLockAcquired) release_wake_lock(WAKE_LOCK_NAME); + if (mWakeLockAcquired && !needsWakeLock) { + release_wake_lock(WAKE_LOCK_NAME); + mWakeLockAcquired = false; + ALOGD_IF(DEBUG_CONNECTIONS, "released wakelock %s", WAKE_LOCK_NAME); + } } while (count >= 0 || Thread::exitPending()); ALOGW("Exiting SensorService::threadLoop => aborting..."); @@ -429,9 +437,8 @@ bool SensorService::threadLoop() return false; } -void SensorService::recordLastValue( +void SensorService::recordLastValueLocked( const sensors_event_t* buffer, size_t count) { - Mutex::Autolock _l(mLock); const sensors_event_t* last = NULL; for (size_t i = 0; i < count; i++) { const sensors_event_t* event = &buffer[i]; @@ -459,20 +466,6 @@ void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count) qsort(buffer, count, sizeof(sensors_event_t), compar::cmp); } -SortedVector< wp<SensorService::SensorEventConnection> > -SensorService::getActiveConnections() const -{ - Mutex::Autolock _l(mLock); - return mActiveConnections; -} - -DefaultKeyedVector<int, SensorInterface*> -SensorService::getActiveVirtualSensors() const -{ - Mutex::Autolock _l(mLock); - return mActiveVirtualSensors; -} - String8 SensorService::getSensorName(int handle) const { size_t count = mUserSensorList.size(); for (size_t i=0 ; i<count ; i++) { @@ -490,6 +483,11 @@ bool SensorService::isVirtualSensor(int handle) const { return sensor->isVirtual(); } +bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const { + SensorInterface* sensor = mSensorMap.valueFor(event.sensor); + return sensor->getSensor().isWakeUpSensor(); +} + Vector<Sensor> SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; @@ -554,6 +552,9 @@ void SensorService::cleanupConnection(SensorEventConnection* c) } mActiveConnections.remove(connection); BatteryService::cleanup(c->getUid()); + if (c->needsWakeLock()) { + checkWakeLockStateLocked(); + } } Sensor SensorService::getSensorFromHandle(int handle) const { @@ -585,15 +586,24 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, } } else { if (rec->addConnection(connection)) { - // this sensor is already activated, but we are adding a - // connection that uses it. Immediately send down the last - // known value of the requested sensor if it's not a + // this sensor is already activated, but we are adding a connection that uses it. + // Immediately send down the last known value of the requested sensor if it's not a // "continuous" sensor. if (sensor->getSensor().getMinDelay() == 0) { - sensors_event_t scratch; + // NOTE: The wake_up flag of this event may get set to + // WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event. sensors_event_t& event(mLastEventSeen.editValueFor(handle)); if (event.version == sizeof(sensors_event_t)) { - connection->sendEvents(&event, 1); + 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); + } + connection->sendEvents(&event, 1, NULL); + if (!connection->needsWakeLock() && mWakeLockAcquired) { + checkWakeLockStateLocked(); + } } } } @@ -751,6 +761,31 @@ bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* oper } } +void SensorService::checkWakeLockState() { + Mutex::Autolock _l(mLock); + checkWakeLockStateLocked(); +} + +void SensorService::checkWakeLockStateLocked() { + if (!mWakeLockAcquired) { + return; + } + bool releaseLock = true; + for (size_t i=0 ; i<mActiveConnections.size() ; i++) { + sp<SensorEventConnection> connection(mActiveConnections[i].promote()); + if (connection != 0) { + if (connection->needsWakeLock()) { + releaseLock = false; + break; + } + } + } + if (releaseLock) { + ALOGD_IF(DEBUG_CONNECTIONS, "releasing wakelock %s", WAKE_LOCK_NAME); + release_wake_lock(WAKE_LOCK_NAME); + mWakeLockAcquired = false; + } +} // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( @@ -783,7 +818,7 @@ bool SensorService::SensorRecord::removeConnection( SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service, uid_t uid) - : mService(service), mUid(uid) + : mService(service), mUid(uid), mWakeLockRefCount(0) { const SensorDevice& device(SensorDevice::getInstance()); if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) { @@ -804,8 +839,14 @@ void SensorService::SensorEventConnection::onFirstRef() { } +bool SensorService::SensorEventConnection::needsWakeLock() { + Mutex::Autolock _l(mConnectionLock); + return mWakeLockRefCount > 0; +} + void SensorService::SensorEventConnection::dump(String8& result) { Mutex::Autolock _l(mConnectionLock); + result.appendFormat("%d WakeLockRefCount\n", mWakeLockRefCount); for (size_t i = 0; i < mSensorInfo.size(); ++i) { const FlushInfo& flushInfo = mSensorInfo.valueAt(i); result.appendFormat("\t %s | status: %s | pending flush events %d | uid %d\n", @@ -863,9 +904,8 @@ status_t SensorService::SensorEventConnection::sendEvents( { // filter out events not for this connection size_t count = 0; - + Mutex::Autolock _l(mConnectionLock); if (scratch) { - Mutex::Autolock _l(mConnectionLock); size_t i=0; while (i<numEvents) { int32_t curr = buffer[i].sensor; @@ -905,7 +945,6 @@ status_t SensorService::SensorEventConnection::sendEvents( ASensorEvent flushCompleteEvent; flushCompleteEvent.type = SENSOR_TYPE_META_DATA; flushCompleteEvent.sensor = 0; - Mutex::Autolock _l(mConnectionLock); // Loop through all the sensors for this connection and check if there are any pending // flush complete events to be sent. for (size_t i = 0; i < mSensorInfo.size(); ++i) { @@ -930,6 +969,7 @@ status_t SensorService::SensorEventConnection::sendEvents( return status_t(NO_ERROR); } + int numWakeUpSensorEvents = countWakeUpSensorEventsLocked(scratch, count); // NOTE: ASensorEvent and sensors_event_t are the same type ssize_t size = SensorEventQueue::write(mChannel, reinterpret_cast<ASensorEvent const*>(scratch), count); @@ -937,11 +977,10 @@ status_t SensorService::SensorEventConnection::sendEvents( // the destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor. // ALOGW("dropping %d events on the floor", count); - Mutex::Autolock _l(mConnectionLock); countFlushCompleteEventsLocked(scratch, count); + mWakeLockRefCount -= numWakeUpSensorEvents; return size; } - return size < 0 ? status_t(size) : status_t(NO_ERROR); } @@ -961,6 +1000,18 @@ void SensorService::SensorEventConnection::countFlushCompleteEventsLocked( return; } +int SensorService::SensorEventConnection::countWakeUpSensorEventsLocked( + sensors_event_t* scratch, const int count) { + for (int i = 0; i < count; ++i) { + if (mService->isWakeUpSensorEvent(scratch[i])) { + scratch[i].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; + ++mWakeLockRefCount; + return 1; + } + } + return 0; +} + sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const { return mChannel; @@ -1010,6 +1061,17 @@ status_t SensorService::SensorEventConnection::flush() { return err; } +void SensorService::SensorEventConnection::decreaseWakeLockRefCount() { + { + Mutex::Autolock _l(mConnectionLock); + --mWakeLockRefCount; + } + // Release the lock before calling checkWakeLockState which also needs the same connectionLock. + if (mWakeLockRefCount == 0) { + mService->checkWakeLockState(); + } +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index e88ffc8..5fd56b8 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -41,6 +41,7 @@ // Max size is 1 MB which is enough to accept a batch of about 10k events. #define MAX_SOCKET_BUFFER_SIZE_BATCHED 1024 * 1024 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024 +#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1 << 31) struct sensors_poll_device_t; struct sensors_module_t; @@ -71,7 +72,6 @@ class SensorService : virtual sp<ISensorEventConnection> createSensorEventConnection(); virtual status_t dump(int fd, const Vector<String16>& args); - class SensorEventConnection : public BnSensorEventConnection { virtual ~SensorEventConnection(); virtual void onFirstRef(); @@ -80,15 +80,26 @@ class SensorService : nsecs_t maxBatchReportLatencyNs, int reservedFlags); virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs); virtual status_t flush(); + void decreaseWakeLockRefCount(); // Count the number of flush complete events which are about to be dropped in the buffer. // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be // sent separately before the next batch of events. void countFlushCompleteEventsLocked(sensors_event_t* scratch, int numEventsDropped); + // Check if there are any wake up events in the buffer. If yes, increment the ref count. + // Increment it by exactly one unit for each packet sent on the socket. SOCK_SEQPACKET for + // the socket ensures that either the entire packet is read or dropped. + // Return 1 if mWakeLockRefCount has been incremented, zero if not. + int countWakeUpSensorEventsLocked(sensors_event_t* scratch, const int count); + sp<SensorService> const mService; sp<BitTube> mChannel; uid_t mUid; mutable Mutex mConnectionLock; + // Number of events from wake up sensors which are still pending and haven't been delivered + // to the corresponding application. It is incremented by one unit for each write to the + // socket. + int mWakeLockRefCount; struct FlushInfo { // The number of flush complete events dropped for this sensor is stored here. @@ -106,13 +117,14 @@ class SensorService : SensorEventConnection(const sp<SensorService>& service, uid_t uid); status_t sendEvents(sensors_event_t const* buffer, size_t count, - sensors_event_t* scratch = NULL); + sensors_event_t* scratch); bool hasSensor(int32_t handle) const; bool hasAnySensor() const; bool addSensor(int32_t handle); bool removeSensor(int32_t handle); void setFirstFlushPending(int32_t handle, bool value); void dump(String8& result); + bool needsWakeLock(); uid_t getUid() const { return mUid; } }; @@ -126,13 +138,11 @@ class SensorService : size_t getNumConnections() const { return mConnections.size(); } }; - SortedVector< wp<SensorEventConnection> > getActiveConnections() const; - DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const; - String8 getSensorName(int handle) const; bool isVirtualSensor(int handle) const; Sensor getSensorFromHandle(int handle) const; - void recordLastValue(const sensors_event_t* buffer, size_t count); + bool isWakeUpSensor(int type) const; + void recordLastValueLocked(const sensors_event_t* buffer, size_t count); static void sortEventBuffer(sensors_event_t* buffer, size_t count); Sensor registerSensor(SensorInterface* sensor); Sensor registerVirtualSensor(SensorInterface* sensor); @@ -140,10 +150,16 @@ class SensorService : const sp<SensorEventConnection>& connection, int handle); status_t cleanupWithoutDisableLocked( const sp<SensorEventConnection>& connection, int handle); - void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, + void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection, sensors_event_t const* buffer, const int count); static bool canAccessSensor(const Sensor& sensor); static bool verifyCanAccessSensor(const Sensor& sensor, const char* operation); + // SensorService acquires a partial wakelock for delivering events from wake up sensors. This + // method checks whether all the events from these wake up sensors have been delivered to the + // corresponding applications, if yes the wakelock is released. + void checkWakeLockState(); + void checkWakeLockStateLocked(); + bool isWakeUpSensorEvent(const sensors_event_t& event) const; // constants Vector<Sensor> mSensorList; Vector<Sensor> mUserSensorListDebug; @@ -158,6 +174,7 @@ class SensorService : DefaultKeyedVector<int, SensorRecord*> mActiveSensors; DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors; SortedVector< wp<SensorEventConnection> > mActiveConnections; + bool mWakeLockAcquired; // The size of this vector is constant, only the items are mutable KeyedVector<int32_t, sensors_event_t> mLastEventSeen; |