diff --git a/include/android/sensor.h b/include/android/sensor.h index b4e7ebee9..86de93020 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -157,7 +157,9 @@ typedef struct ASensorEvent { uint64_t step_counter; } u64; }; - int32_t reserved1[4]; + + uint32_t flags; + int32_t reserved1[3]; } ASensorEvent; struct ASensorManager; diff --git a/include/gui/ISensorEventConnection.h b/include/gui/ISensorEventConnection.h index f64c6b860..b2967975d 100644 --- a/include/gui/ISensorEventConnection.h +++ b/include/gui/ISensorEventConnection.h @@ -40,6 +40,7 @@ public: nsecs_t maxBatchReportLatencyNs, int reservedFlags) = 0; virtual status_t setEventRate(int handle, nsecs_t ns) = 0; virtual status_t flush() = 0; + virtual void decreaseWakeLockRefCount() = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h index 033b26296..41a6cc6cc 100644 --- a/include/gui/Sensor.h +++ b/include/gui/Sensor.h @@ -71,6 +71,7 @@ public: int32_t getFifoMaxEventCount() const; const String8& getStringType() const; const String8& getRequiredPermission() const; + bool isWakeUpSensor() const; // LightFlattenable protocol inline bool isFixedSize() const { return false; } @@ -93,6 +94,8 @@ private: int32_t mFifoMaxEventCount; String8 mStringType; String8 mRequiredPermission; + // Todo: Surface this in java SDK. + bool mWakeUpSensor; static void flattenString8(void*& buffer, size_t& size, const String8& string8); static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8); }; diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h index 0bfc7a0df..4e8a2d292 100644 --- a/include/gui/SensorEventQueue.h +++ b/include/gui/SensorEventQueue.h @@ -27,7 +27,7 @@ #include // ---------------------------------------------------------------------------- - +#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1 << 31) struct ALooper; struct ASensorEvent; @@ -75,7 +75,8 @@ public: int reservedFlags) const; status_t disableSensor(int32_t handle) const; status_t flush() const; - + // Send an ack for every wake_up sensor event that is set to WAKE_UP_SENSOR_EVENT_NEEDS_ACK. + void sendAck(const ASensorEvent* events, int count); private: sp getLooper() const; sp mSensorEventConnection; diff --git a/libs/gui/ISensorEventConnection.cpp b/libs/gui/ISensorEventConnection.cpp index 28fcb53d8..8f8814142 100644 --- a/libs/gui/ISensorEventConnection.cpp +++ b/libs/gui/ISensorEventConnection.cpp @@ -34,7 +34,8 @@ enum { GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION, ENABLE_DISABLE, SET_EVENT_RATE, - FLUSH_SENSOR + FLUSH_SENSOR, + DECREASE_WAKE_LOCK_REFCOUNT }; class BpSensorEventConnection : public BpInterface @@ -83,6 +84,13 @@ public: remote()->transact(FLUSH_SENSOR, data, &reply); return reply.readInt32(); } + + virtual void decreaseWakeLockRefCount() { + Parcel data, reply; + data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor()); + remote()->transact(DECREASE_WAKE_LOCK_REFCOUNT, data, &reply, IBinder::FLAG_ONEWAY); + return; + } }; IMPLEMENT_META_INTERFACE(SensorEventConnection, "android.gui.SensorEventConnection"); @@ -125,6 +133,11 @@ status_t BnSensorEventConnection::onTransact( reply->writeInt32(result); return NO_ERROR; } break; + case DECREASE_WAKE_LOCK_REFCOUNT: { + CHECK_INTERFACE(ISensorEventConnection, data, reply); + decreaseWakeLockRefCount(); + return NO_ERROR; + } break; } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp index 6f1a3f206..b363411a5 100644 --- a/libs/gui/Sensor.cpp +++ b/libs/gui/Sensor.cpp @@ -32,7 +32,8 @@ namespace android { Sensor::Sensor() : mHandle(0), mType(0), mMinValue(0), mMaxValue(0), mResolution(0), - mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0) + mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0), + mWakeUpSensor(false) { } @@ -48,6 +49,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) mResolution = hwSensor->resolution; mPower = hwSensor->power; mMinDelay = hwSensor->minDelay; + mWakeUpSensor = false; // Set fifo event count zero for older devices which do not support batching. Fused // sensors also have their fifo counts set to zero. @@ -104,6 +106,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) break; case SENSOR_TYPE_PROXIMITY: mStringType = SENSOR_STRING_TYPE_PROXIMITY; + mWakeUpSensor = true; break; case SENSOR_TYPE_RELATIVE_HUMIDITY: mStringType = SENSOR_STRING_TYPE_RELATIVE_HUMIDITY; @@ -113,6 +116,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) break; case SENSOR_TYPE_SIGNIFICANT_MOTION: mStringType = SENSOR_STRING_TYPE_SIGNIFICANT_MOTION; + mWakeUpSensor = true; break; case SENSOR_TYPE_STEP_COUNTER: mStringType = SENSOR_STRING_TYPE_STEP_COUNTER; @@ -123,14 +127,93 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) case SENSOR_TYPE_TEMPERATURE: mStringType = SENSOR_STRING_TYPE_TEMPERATURE; break; + case SENSOR_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR: + mStringType = SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR; + break; + case SENSOR_TYPE_WAKE_UP_ACCELEROMETER: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_ACCELEROMETER; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_ORIENTATION: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_ORIENTATION; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_GYROSCOPE: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_LIGHT: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_LIGHT; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_PRESSURE: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_PRESSURE; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_GRAVITY: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_GRAVITY; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_LINEAR_ACCELERATION: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_ROTATION_VECTOR; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_RELATIVE_HUMIDITY: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_AMBIENT_TEMPERATURE: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_GAME_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_STEP_DETECTOR: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_DETECTOR; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_STEP_COUNTER: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_STEP_COUNTER; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR; + mWakeUpSensor = true; + break; + case SENSOR_TYPE_WAKE_UP_HEART_RATE: + mStringType = SENSOR_STRING_TYPE_WAKE_UP_HEART_RATE; + mRequiredPermission = SENSOR_PERMISSION_BODY_SENSORS; + mWakeUpSensor = true; + break; default: - // Only pipe the stringType and requiredPermission for custom sensors. + // Only pipe the stringType, requiredPermission and flags for custom sensors. if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) { mStringType = hwSensor->stringType; } if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) { mRequiredPermission = hwSensor->requiredPermission; } + if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) { + mWakeUpSensor = hwSensor->flags & SENSOR_FLAG_WAKE_UP; + } break; } } @@ -199,6 +282,10 @@ const String8& Sensor::getRequiredPermission() const { return mRequiredPermission; } +bool Sensor::isWakeUpSensor() const { + return mWakeUpSensor; +} + size_t Sensor::getFlattenedSize() const { size_t fixedSize = diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp index c3656718d..c2eaf4ec7 100644 --- a/libs/gui/SensorEventQueue.cpp +++ b/libs/gui/SensorEventQueue.cpp @@ -144,6 +144,15 @@ status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const return mSensorEventConnection->setEventRate(sensor->getHandle(), ns); } +void SensorEventQueue::sendAck(const ASensorEvent* events, int count) { + for (int i = 0; i < count; ++i) { + if (events[i].flags & WAKE_UP_SENSOR_EVENT_NEEDS_ACK) { + mSensorEventConnection->decreaseWakeLockRefCount(); + } + } + return; +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 3b64f0a8b..01dbdfbee 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 8837a4deb..aff4e9a50 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& /*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& /*args*/) return NO_ERROR; } -void SensorService::cleanupAutoDisabledSensor(const sp& connection, +void SensorService::cleanupAutoDisabledSensorLocked(const sp& 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& 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 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 > activeConnections( - getActiveConnections()); - size_t numConnections = activeConnections.size(); - for (size_t i=0 ; i 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 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::getActiveConnections() const -{ - Mutex::Autolock _l(mLock); - return mActiveConnections; -} - -DefaultKeyedVector -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 ; iisVirtual(); } +bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const { + SensorInterface* sensor = mSensorMap.valueFor(event.sensor); + return sensor->getSensor().isWakeUpSensor(); +} + Vector 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& 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 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& 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(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 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 e88ffc875..5fd56b8b5 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 createSensorEventConnection(); virtual status_t dump(int fd, const Vector& 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 const mService; sp 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& 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 > getActiveConnections() const; - DefaultKeyedVector 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& connection, int handle); status_t cleanupWithoutDisableLocked( const sp& connection, int handle); - void cleanupAutoDisabledSensor(const sp& connection, + void cleanupAutoDisabledSensorLocked(const sp& 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 mSensorList; Vector mUserSensorListDebug; @@ -158,6 +174,7 @@ class SensorService : DefaultKeyedVector mActiveSensors; DefaultKeyedVector mActiveVirtualSensors; SortedVector< wp > mActiveConnections; + bool mWakeLockAcquired; // The size of this vector is constant, only the items are mutable KeyedVector mLastEventSeen;