From 6c2664ae34fd582bc174d3c83e2b18e895ca2496 Mon Sep 17 00:00:00 2001 From: Aravind Akella Date: Wed, 13 Aug 2014 12:24:50 -0700 Subject: [PATCH] SensorService fixes. 1) Flush should only be received by the app calling flush(). Maintain a queue of all flush() calls and send flush_complete events in that order. 2) Log warnings for older HALs. Remove batch() calls with DRY_RUN flag. 3) Reallocate event cache when more sensors register and the desired maxCacheSize increases. Clear NEEDS_ACK flag in the buffer whenever there is a write() failure. 4) More dump information. Add wake-up flag, maxDelay and timestamps for sensor events. Bug: 16874778 Change-Id: I195646191059fd31f75f2f07886c0f98bf9b509a --- include/gui/SensorEventQueue.h | 2 +- services/sensorservice/SensorDevice.cpp | 26 +-- services/sensorservice/SensorService.cpp | 277 +++++++++++++++-------- services/sensorservice/SensorService.h | 36 ++- 4 files changed, 222 insertions(+), 119 deletions(-) diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h index 4e8a2d292..019308d0c 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) +#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31) struct ALooper; struct ASensorEvent; diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index 3934509e2..80845a287 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -54,6 +54,11 @@ SensorDevice::SensorDevice() SENSORS_HARDWARE_MODULE_ID, strerror(-err)); if (mSensorDevice) { + if (mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_1 || + mSensorDevice->common.version == SENSORS_DEVICE_API_VERSION_1_2) { + ALOGE(">>>> WARNING <<< Upgrade sensor HAL to version 1_3"); + } + sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); mActivationCount.setCapacity(count); @@ -74,6 +79,7 @@ void SensorDevice::dump(String8& result) sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); + result.appendFormat("halVersion %d\n", getHalDeviceVersion()); result.appendFormat("%d h/w sensors:\n", int(count)); Mutex::Autolock _l(mLock); @@ -210,24 +216,8 @@ status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplin } const int halVersion = getHalDeviceVersion(); - if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) { - if (flags & SENSORS_BATCH_DRY_RUN) { - return mSensorDevice->batch(mSensorDevice, handle, flags, samplingPeriodNs, - maxBatchReportLatencyNs); - } else { - // Call h/w with dry run to see if the given parameters are feasible or not. Return if - // there is an error. - status_t errDryRun(NO_ERROR); - errDryRun = mSensorDevice->batch(mSensorDevice, handle, flags | SENSORS_BATCH_DRY_RUN, - samplingPeriodNs, maxBatchReportLatencyNs); - if (errDryRun != NO_ERROR) { - ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::batch dry run error %s", - strerror(-errDryRun)); - return errDryRun; - } - } - } else if (maxBatchReportLatencyNs != 0) { - // Batch is not supported on older devices. + if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 && maxBatchReportLatencyNs != 0) { + // Batch is not supported on older devices return invalid operation. return INVALID_OPERATION; } diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 8fe79d013..bee506269 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -218,69 +218,85 @@ status_t SensorService::dump(int fd, const Vector& /*args*/) const Sensor& s(mSensorList[i]); const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle())); result.appendFormat( - "%-48s| %-32s| %-48s| 0x%08x | \"%s\"\n\t", + "%-15s| %-10s| %-20s| 0x%08x | \"%s\" | type=%d |", s.getName().string(), s.getVendor().string(), s.getStringType().string(), s.getHandle(), - s.getRequiredPermission().string()); + s.getRequiredPermission().string(), + s.getType()); const int reportingMode = s.getReportingMode(); if (reportingMode == AREPORTING_MODE_CONTINUOUS) { - result.append("continuous |"); + result.append(" continuous | "); } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) { - result.append("on-change | "); + result.append(" on-change | "); } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) { - result.append("one-shot | "); + result.append(" one-shot | "); } else { - result.append("special-trigger | "); + result.append(" special-trigger | "); + } + + if (s.getMaxDelay() > 0) { + result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay()); + } else { + result.appendFormat("maxDelay=%dus |", s.getMaxDelay()); } if (s.getMinDelay() > 0) { - result.appendFormat("maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); + result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay()); } else { - result.appendFormat("minDelay=%5dus |", s.getMinDelay()); + result.appendFormat("minDelay=%dus |", s.getMinDelay()); } if (s.getFifoMaxEventCount() > 0) { result.appendFormat("FifoMax=%d events | ", s.getFifoMaxEventCount()); } else { - result.append("no batching support | "); + result.append("no batching | "); + } + + if (s.isWakeUpSensor()) { + result.appendFormat("wakeUp | "); + } else { + result.appendFormat("non-wakeUp | "); } switch (s.getType()) { case SENSOR_TYPE_ROTATION_VECTOR: case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR: result.appendFormat( - "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n", - e.data[0], e.data[1], e.data[2], e.data[3], e.data[4]); + "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n", + e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.timestamp); break; case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: result.appendFormat( - "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n", - e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5]); + "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n", + e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5], + e.timestamp); break; case SENSOR_TYPE_GAME_ROTATION_VECTOR: result.appendFormat( - "last=<%5.1f,%5.1f,%5.1f,%5.1f>\n", - e.data[0], e.data[1], e.data[2], e.data[3]); + "last=<%5.1f,%5.1f,%5.1f,%5.1f, %" PRId64 ">\n", + e.data[0], e.data[1], e.data[2], e.data[3], e.timestamp); break; case SENSOR_TYPE_SIGNIFICANT_MOTION: case SENSOR_TYPE_STEP_DETECTOR: - result.appendFormat( "last=<%f>\n", e.data[0]); + result.appendFormat( "last=<%f %" PRId64 ">\n", e.data[0], e.timestamp); break; case SENSOR_TYPE_STEP_COUNTER: - result.appendFormat( "last=<%" PRIu64 ">\n", e.u64.step_counter); + result.appendFormat( "last=<%" PRIu64 ", %" PRId64 ">\n", e.u64.step_counter, + e.timestamp); break; default: // default to 3 values result.appendFormat( - "last=<%5.1f,%5.1f,%5.1f>\n", - e.data[0], e.data[1], e.data[2]); + "last=<%5.1f,%5.1f,%5.1f, %" PRId64 ">\n", + e.data[0], e.data[1], e.data[2], e.timestamp); break; } + result.append("\n"); } SensorFusion::getInstance().dump(result); SensorDevice::getInstance().dump(result); @@ -294,7 +310,8 @@ status_t SensorService::dump(int fd, const Vector& /*args*/) mActiveSensors.valueAt(i)->getNumConnections()); } - result.appendFormat("%zu Max Socket Buffer size\n", mSocketBufferSize); + result.appendFormat("Max Socket Buffer size = %d events\n", + mSocketBufferSize/sizeof(sensors_event_t)); result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held"); result.appendFormat("%zd active connections\n", mActiveConnections.size()); @@ -520,6 +537,11 @@ bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const { return sensor != NULL && sensor->getSensor().isWakeUpSensor(); } + +SensorService::SensorRecord * SensorService::getSensorRecord(int handle) { + return mActiveSensors.valueFor(handle); +} + Vector SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; @@ -658,18 +680,20 @@ status_t SensorService::enable(const sp& connection, samplingPeriodNs = minDelayNs; } - ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d rate=%" PRId64 " timeout== %" PRId64, + ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d" + "rate=%" PRId64 " timeout== %" PRId64"", handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs); status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs); - if (err == NO_ERROR) { - connection->setFirstFlushPending(handle, true); + + if (err == NO_ERROR && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT) { status_t err_flush = sensor->flush(connection.get(), handle); // Flush may return error if the sensor is not activated or the underlying h/w sensor does // not support flush. - if (err_flush != NO_ERROR) { - connection->setFirstFlushPending(handle, false); + if (err_flush == NO_ERROR) { + connection->setFirstFlushPending(handle, true); + rec->addPendingFlushConnection(connection.get()); } } @@ -775,7 +799,13 @@ status_t SensorService::flushSensor(const sp& connection, ALOGE("flush called on a one-shot sensor"); return INVALID_OPERATION; } - return sensor->flush(connection.get(), handle); + + status_t ret = sensor->flush(connection.get(), handle); + if (ret == NO_ERROR) { + SensorRecord* rec = mActiveSensors.valueFor(handle); + if (rec != NULL) rec->addPendingFlushConnection(connection); + } + return ret; } @@ -823,6 +853,7 @@ void SensorService::checkWakeLockStateLocked() { mWakeLockAcquired = false; } } + // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( const sp& connection) @@ -847,9 +878,37 @@ bool SensorService::SensorRecord::removeConnection( if (index >= 0) { mConnections.removeItemsAt(index, 1); } + // Remove this connections from the queue of flush() calls made on this sensor. + for (Vector< wp >::iterator it = + mPendingFlushConnections.begin(); it != mPendingFlushConnections.end();) { + if (it->unsafe_get() == connection.unsafe_get()) { + it = mPendingFlushConnections.erase(it); + } else { + ++it; + } + } return mConnections.size() ? false : true; } +void SensorService::SensorRecord::addPendingFlushConnection( + const sp& connection) { + mPendingFlushConnections.add(connection); +} + +void SensorService::SensorRecord::removeFirstPendingFlushConnection() { + if (mPendingFlushConnections.size() > 0) { + mPendingFlushConnections.removeAt(0); + } +} + +SensorService::SensorEventConnection * +SensorService::SensorRecord::getFirstPendingFlushConnection() { + if (mPendingFlushConnections.size() > 0) { + return mPendingFlushConnections[0].unsafe_get(); + } + return NULL; +} + // --------------------------------------------------------------------------- SensorService::SensorEventConnection::SensorEventConnection( @@ -890,13 +949,13 @@ void SensorService::SensorEventConnection::dump(String8& result) { result.appendFormat("\t %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 | flush calls %d| uid %d|" + result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d | uid %d|" "cache size: %d max cache size %d\n", mService->getSensorName(mSensorInfo.keyAt(i)).string(), + mSensorInfo.keyAt(i), flushInfo.mFirstFlushPending ? "First flush pending" : "active", flushInfo.mPendingFlushEventsToSend, - flushInfo.mNumFlushCalls, mUid, mCacheSize, mMaxCacheSize); @@ -905,7 +964,7 @@ void SensorService::SensorEventConnection::dump(String8& result) { mEventsReceived, mEventsSent, mEventsSentFromCache, - mEventsReceived - (mEventsSentFromCache + + mEventsReceived - (mEventsSentFromCache mEventsSent + mCacheSize)); #endif @@ -961,15 +1020,15 @@ status_t SensorService::SensorEventConnection::sendEvents( if (scratch) { size_t i=0; while (igetSensorRecord(sensor_handle); + if (rec && rec->getFirstPendingFlushConnection() == this) { + rec->removeFirstPendingFlushConnection(); flushInfo.mFirstFlushPending = false; ++i; + ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ", + buffer[i].meta_data.sensor); continue; } } @@ -1000,26 +1059,28 @@ status_t SensorService::SensorEventConnection::sendEvents( do { if (buffer[i].type == SENSOR_TYPE_META_DATA) { - // Send flush complete event only if flush() has been explicitly called by - // this app else ignore. - if (flushInfo.mNumFlushCalls > 0) { + // Check if this connection has called flush() on this sensor. Only if + // a flush() has been explicitly called, send a flush_complete_event. + SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle); + if (rec && rec->getFirstPendingFlushConnection() == this) { + rec->removeFirstPendingFlushConnection(); scratch[count++] = buffer[i]; - flushInfo.mNumFlushCalls--; } ++i; } else { // Regular sensor event, just copy it to the scratch buffer. scratch[count++] = buffer[i++]; } - } while ((i(buffer); count = numEvents; } + sendPendingFlushEventsLocked(); // Early return if there are no events for this connection. if (count == 0) { return status_t(NO_ERROR); @@ -1035,6 +1096,12 @@ status_t SensorService::SensorEventConnection::sendEvents( memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t)); mCacheSize += count; } else { + // Check if any new sensors have registered on this connection which may have increased + // the max cache size that is desired. + if (mCacheSize + count < computeMaxCacheSizeLocked()) { + reAllocateCacheLocked(scratch, count); + return status_t(NO_ERROR); + } // Some events need to be dropped. int remaningCacheSize = mMaxCacheSize - mCacheSize; if (remaningCacheSize != 0) { @@ -1054,15 +1121,22 @@ status_t SensorService::SensorEventConnection::sendEvents( return status_t(NO_ERROR); } - int numWakeUpSensorEvents = countWakeUpSensorEventsLocked(scratch, count); - mWakeLockRefCount += numWakeUpSensorEvents; + int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count); + if (index_wake_up_event >= 0) { + scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK; + ++mWakeLockRefCount; + } // NOTE: ASensorEvent and sensors_event_t are the same type. ssize_t size = SensorEventQueue::write(mChannel, reinterpret_cast(scratch), count); if (size < 0) { // Write error, copy events to local cache. - mWakeLockRefCount -= numWakeUpSensorEvents; + if (index_wake_up_event >= 0) { + // If there was a wake_up sensor_event, reset the flag. + scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK; + --mWakeLockRefCount; + } if (mEventCache == NULL) { mMaxCacheSize = computeMaxCacheSizeLocked(); mEventCache = new sensors_event_t[mMaxCacheSize]; @@ -1087,53 +1161,81 @@ status_t SensorService::SensorEventConnection::sendEvents( return size < 0 ? status_t(size) : status_t(NO_ERROR); } +void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch, + int count) { + sensors_event_t *eventCache_new; + const int new_cache_size = computeMaxCacheSizeLocked(); + // Allocate new cache, copy over events from the old cache & scratch, free up memory. + eventCache_new = new sensors_event_t[new_cache_size]; + memcpy(eventCache_new, mEventCache, mCacheSize * sizeof(sensors_event_t)); + memcpy(&eventCache_new[mCacheSize], scratch, count * sizeof(sensors_event_t)); + + ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize, + new_cache_size); + + delete mEventCache; + mEventCache = eventCache_new; + mCacheSize += count; + mMaxCacheSize = new_cache_size; +} + +void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() { + ASensorEvent flushCompleteEvent; + flushCompleteEvent.type = SENSOR_TYPE_META_DATA; + flushCompleteEvent.sensor = 0; + // 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) { + FlushInfo& flushInfo = mSensorInfo.editValueAt(i); + while (flushInfo.mPendingFlushEventsToSend > 0) { + flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i); + ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1); + if (size < 0) { + return; + } + ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ", + flushCompleteEvent.meta_data.sensor); + flushInfo.mPendingFlushEventsToSend--; + } + } +} + void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() { // At a time write at most half the size of the receiver buffer in SensorEventQueue. const int maxWriteSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2; - // Send pending flush events (if any) before sending events from the buffer. - { - ASensorEvent flushCompleteEvent; - flushCompleteEvent.type = SENSOR_TYPE_META_DATA; - flushCompleteEvent.sensor = 0; - // 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) { - FlushInfo& flushInfo = mSensorInfo.editValueAt(i); - while (flushInfo.mPendingFlushEventsToSend > 0) { - flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i); - ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1); - if (size < 0) { - return; - } - ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ", - flushCompleteEvent.meta_data.sensor); - flushInfo.mPendingFlushEventsToSend--; - } - } - } + sendPendingFlushEventsLocked(); // Write "count" events at a time. for (int numEventsSent = 0; numEventsSent < mCacheSize;) { - const int count = (mCacheSize - numEventsSent) < maxWriteSize ? + const int numEventsToWrite = (mCacheSize - numEventsSent) < maxWriteSize ? mCacheSize - numEventsSent : maxWriteSize; - int numWakeUpSensorEvents = - countWakeUpSensorEventsLocked(mEventCache + numEventsSent, count); - mWakeLockRefCount += numWakeUpSensorEvents; + int index_wake_up_event = + findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite); + if (index_wake_up_event >= 0) { + mEventCache[index_wake_up_event + numEventsSent].flags |= + WAKE_UP_SENSOR_EVENT_NEEDS_ACK; + ++mWakeLockRefCount; + } ssize_t size = SensorEventQueue::write(mChannel, reinterpret_cast(mEventCache + numEventsSent), - count); + numEventsToWrite); if (size < 0) { + if (index_wake_up_event >= 0) { + // If there was a wake_up sensor_event, reset the flag. + mEventCache[index_wake_up_event + numEventsSent].flags &= + ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK; + --mWakeLockRefCount; + } memmove(mEventCache, &mEventCache[numEventsSent], (mCacheSize - numEventsSent) * sizeof(sensors_event_t)); ALOGD_IF(DEBUG_CONNECTIONS, "wrote %d events from cache size==%d ", - numEventsSent, mCacheSize); + numEventsSent, mCacheSize); mCacheSize -= numEventsSent; - mWakeLockRefCount -= numWakeUpSensorEvents; return; } - numEventsSent += count; + numEventsSent += numEventsToWrite; #if DEBUG_CONNECTIONS - mEventsSentFromCache += count; + mEventsSentFromCache += numEventsToWrite; #endif } ALOGD_IF(DEBUG_CONNECTIONS, "wrote all events from cache size=%d ", mCacheSize); @@ -1159,15 +1261,14 @@ void SensorService::SensorEventConnection::countFlushCompleteEventsLocked( return; } -int SensorService::SensorEventConnection::countWakeUpSensorEventsLocked( - sensors_event_t* scratch, const int count) { +int SensorService::SensorEventConnection::findWakeUpSensorEventLocked( + sensors_event_t const* 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; - return 1; + return i; } } - return 0; + return -1; } sp SensorService::SensorEventConnection::getSensorChannel() const @@ -1211,9 +1312,7 @@ status_t SensorService::SensorEventConnection::flush() { flushInfo.mPendingFlushEventsToSend++; } else { status_t err_flush = mService->flushSensor(this, handle); - if (err_flush == NO_ERROR) { - flushInfo.mNumFlushCalls++; - } else { + if (err_flush != NO_ERROR) { ALOGE("Flush error handle=%d %s", handle, strerror(-err_flush)); } err = (err_flush != NO_ERROR) ? err_flush : err; @@ -1280,9 +1379,9 @@ int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const { } if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) { // It is extremely unlikely that there is a write failure in non batch mode. Return a cache - // size of 100. + // size that is equal to that of the batch mode. ALOGI("Write failure in non-batch mode"); - return 100; + return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t); } return fifoWakeUpSensors + fifoNonWakeUpSensors; } diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 3cdc825d7..15759aefd 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -44,7 +44,6 @@ #define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024 // For older HALs which don't support batching, use a smaller socket buffer size. #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024 -#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31) struct sensors_poll_device_t; struct sensors_module_t; @@ -89,11 +88,17 @@ class SensorService : // 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, int count); + // Check if there are any wake up events in the buffer. If yes, return the index of the + // first wake_up sensor event in the buffer else return -1. This wake_up sensor event will + // have the flag WAKE_UP_SENSOR_EVENT_NEEDS_ACK set. Exactly one event per packet will have + // the wake_up flag set. SOCK_SEQPACKET ensures that either the entire packet is read or + // dropped. + int findWakeUpSensorEventLocked(sensors_event_t const* scratch, int count); + + // Send pending flush_complete events. There may have been flush_complete_events that are + // dropped which need to be sent separately before other events. On older HALs (1_0) this + // method emulates the behavior of flush(). + void sendPendingFlushEventsLocked(); // Writes events from mEventCache to the socket. void writeToSocketFromCacheLocked(); @@ -103,6 +108,10 @@ class SensorService : // shared amongst wake-up sensors and non-wake up sensors. int computeMaxCacheSizeLocked() const; + // When more sensors register, the maximum cache size desired may change. Compute max cache + // size, reallocate memory and copy over events from the older cache. + void reAllocateCacheLocked(sensors_event_t const* scratch, int count); + // LooperCallback method. If there is data to read on this fd, it is an ack from the // app that it has read events from a wake up sensor, decrement mWakeLockRefCount. // If this fd is available for writing send the data from the cache. @@ -124,11 +133,7 @@ class SensorService : // Every activate is preceded by a flush. Only after the first flush complete is // received, the events for the sensor are sent on that *connection*. bool mFirstFlushPending; - // Number of time flush() was called on this connection. This is incremented every time - // flush() is called and decremented when flush_complete_event is received. - int mNumFlushCalls; - FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false), - mNumFlushCalls(0) {} + FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {} }; // protected by SensorService::mLock. Key for this vector is the sensor handle. KeyedVector mSensorInfo; @@ -157,11 +162,18 @@ class SensorService : class SensorRecord { SortedVector< wp > mConnections; + // A queue of all flush() calls made on this sensor. Flush complete events will be + // sent in this order. + Vector< wp > mPendingFlushConnections; public: SensorRecord(const sp& connection); bool addConnection(const sp& connection); bool removeConnection(const wp& connection); size_t getNumConnections() const { return mConnections.size(); } + + void addPendingFlushConnection(const sp& connection); + void removeFirstPendingFlushConnection(); + SensorEventConnection * getFirstPendingFlushConnection(); }; class SensorEventAckReceiver : public Thread { @@ -194,6 +206,8 @@ class SensorService : void checkWakeLockStateLocked(); bool isWakeUpSensorEvent(const sensors_event_t& event) const; + SensorRecord * getSensorRecord(int handle); + sp getLooper() const; // constants