summaryrefslogtreecommitdiffstats
path: root/services/sensorservice
diff options
context:
space:
mode:
authorAravind Akella <aakella@google.com>2014-02-11 18:58:52 -0800
committerAravind Akella <aakella@google.com>2014-04-23 14:38:56 -0700
commit9a844cf78f09953145200b4074d47589257a408c (patch)
tree8168fc7ede93ec3e6c7567f8d24215ae1820e858 /services/sensorservice
parent4cbf3c53447215a31f69d3ac615ba0daa902f717 (diff)
downloadframeworks_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.cpp2
-rw-r--r--services/sensorservice/SensorService.cpp170
-rw-r--r--services/sensorservice/SensorService.h31
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;