Merge "SensorService performance improvements." into lmp-dev

This commit is contained in:
Aravind Akella 2014-07-25 18:04:57 +00:00 committed by Android (Google) Code Review
commit c268068c55
7 changed files with 331 additions and 87 deletions

View File

@ -48,6 +48,9 @@ public:
// get receive file-descriptor
int getFd() const;
// get the send file-descriptor.
int getSendFd() const;
// send objects (sized blobs). All objects are guaranteed to be written or the call fails.
template <typename T>
static ssize_t sendObjects(const sp<BitTube>& tube,

View File

@ -40,7 +40,6 @@ 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;
};
// ----------------------------------------------------------------------------

View File

@ -99,6 +99,11 @@ int BitTube::getFd() const
return mReceiveFd;
}
int BitTube::getSendFd() const
{
return mSendFd;
}
ssize_t BitTube::write(void const* vaddr, size_t size)
{
ssize_t err, len;

View File

@ -34,8 +34,7 @@ enum {
GET_SENSOR_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
ENABLE_DISABLE,
SET_EVENT_RATE,
FLUSH_SENSOR,
DECREASE_WAKE_LOCK_REFCOUNT
FLUSH_SENSOR
};
class BpSensorEventConnection : public BpInterface<ISensorEventConnection>
@ -84,13 +83,6 @@ 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");
@ -133,11 +125,6 @@ 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);
}

View File

@ -18,6 +18,7 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@ -147,7 +148,14 @@ status_t SensorEventQueue::setEventRate(Sensor const* sensor, nsecs_t ns) const
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();
// Send just a byte of data to acknowledge for the wake up sensor events
// received
char buf = '1';
ssize_t size = ::send(mSensorChannel->getFd(), &buf, sizeof(buf),
MSG_DONTWAIT | MSG_NOSIGNAL);
if (size < 0) {
ALOGE("sendAck failure %d", size);
}
}
}
return;

View File

@ -18,6 +18,7 @@
#include <math.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <cutils/properties.h>
@ -165,6 +166,7 @@ void SensorService::onFirstRef()
mWakeLockAcquired = false;
run("SensorService", PRIORITY_URGENT_DISPLAY);
mLooper = new Looper(false);
mInitCheck = NO_ERROR;
}
}
@ -340,6 +342,8 @@ bool SensorService::threadLoop()
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
SensorEventAckReceiver sender(this);
sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
ssize_t count;
const int halVersion = device.getHalDeviceVersion();
do {
@ -348,6 +352,11 @@ bool SensorService::threadLoop()
ALOGE("sensor poll failed (%s)", strerror(-count));
break;
}
// Reset sensors_event_t.flags to zero for all events in the buffer.
for (int i = 0; i < count; i++) {
buffer[i].flags = 0;
}
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,
@ -443,6 +452,19 @@ bool SensorService::threadLoop()
return false;
}
sp<Looper> SensorService::getLooper() const {
return mLooper;
}
bool SensorService::SensorEventAckReceiver::threadLoop() {
ALOGD("new thread SensorEventAckReceiver");
do {
sp<Looper> looper = mService->getLooper();
looper->pollOnce(-1);
} while(!Thread::exitPending());
return false;
}
void SensorService::recordLastValueLocked(
const sensors_event_t* buffer, size_t count) {
const sensors_event_t* last = NULL;
@ -656,6 +678,12 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
err = sensor->activate(connection.get(), true);
}
if (err == NO_ERROR && sensor->getSensor().isWakeUpSensor()) {
// Add the file descriptor to the Looper for receiving acknowledgments;
int ret = mLooper->addFd(connection->getSensorChannel()->getSendFd(), 0,
ALOOPER_EVENT_INPUT, connection.get(), NULL);
}
if (err != NO_ERROR) {
// batch/activate has failed, reset our state.
cleanupWithoutDisableLocked(connection, handle);
@ -752,9 +780,8 @@ status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection,
bool SensorService::canAccessSensor(const Sensor& sensor) {
String16 permissionString(sensor.getRequiredPermission());
return permissionString.size() == 0 ||
PermissionCache::checkCallingPermission(permissionString);
return (sensor.getRequiredPermission().isEmpty()) ||
PermissionCache::checkCallingPermission(String16(sensor.getRequiredPermission()));
}
bool SensorService::verifyCanAccessSensor(const Sensor& sensor, const char* operation) {
@ -797,7 +824,6 @@ void SensorService::checkWakeLockStateLocked() {
}
}
// ---------------------------------------------------------------------------
SensorService::SensorRecord::SensorRecord(
const sp<SensorEventConnection>& connection)
{
@ -828,25 +854,30 @@ bool SensorService::SensorRecord::removeConnection(
SensorService::SensorEventConnection::SensorEventConnection(
const sp<SensorService>& service, uid_t uid)
: mService(service), mUid(uid), mWakeLockRefCount(0)
{
: mService(service), mUid(uid), mWakeLockRefCount(0), mEventCache(NULL), mCacheSize(0),
mMaxCacheSize(0) {
const SensorDevice& device(SensorDevice::getInstance());
if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) {
// Increase socket buffer size to 1MB for batching capabilities.
mChannel = new BitTube(service->mSocketBufferSize);
// Increase socket buffer size to a max of 100 KB for batching capabilities.
mChannel = new BitTube(mService->mSocketBufferSize);
} else {
mChannel = new BitTube(SOCKET_BUFFER_SIZE_NON_BATCHED);
}
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
#endif
}
SensorService::SensorEventConnection::~SensorEventConnection()
{
SensorService::SensorEventConnection::~SensorEventConnection() {
ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
if (mEventCache != NULL) {
delete mEventCache;
}
mService->cleanupConnection(this);
}
void SensorService::SensorEventConnection::onFirstRef()
{
void SensorService::SensorEventConnection::onFirstRef() {
LooperCallback::onFirstRef();
}
bool SensorService::SensorEventConnection::needsWakeLock() {
@ -856,15 +887,28 @@ bool SensorService::SensorEventConnection::needsWakeLock() {
void SensorService::SensorEventConnection::dump(String8& result) {
Mutex::Autolock _l(mConnectionLock);
result.appendFormat("%d WakeLockRefCount\n", mWakeLockRefCount);
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 | uid %d\n",
result.appendFormat("\t %s | status: %s | pending flush events %d | flush calls %d| uid %d|"
"cache size: %d max cache size %d\n",
mService->getSensorName(mSensorInfo.keyAt(i)).string(),
flushInfo.mFirstFlushPending ? "First flush pending" :
"active",
flushInfo.mPendingFlushEventsToSend,
mUid);
flushInfo.mNumFlushCalls,
mUid,
mCacheSize,
mMaxCacheSize);
#if DEBUG_CONNECTIONS
result.appendFormat("\t events recvd: %d | sent %d | cache %d | dropped %d\n",
mEventsReceived,
mEventsSent,
mEventsSentFromCache,
mEventsReceived - (mEventsSentFromCache +
mEventsSent + mCacheSize));
#endif
}
}
@ -910,8 +954,7 @@ void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch)
{
sensors_event_t* scratch) {
// filter out events not for this connection
size_t count = 0;
Mutex::Autolock _l(mConnectionLock);
@ -927,30 +970,127 @@ status_t SensorService::SensorEventConnection::sendEvents(
curr = buffer[i].meta_data.sensor;
}
ssize_t index = mSensorInfo.indexOfKey(curr);
if (index >= 0 && mSensorInfo[index].mFirstFlushPending == true &&
buffer[i].type == SENSOR_TYPE_META_DATA) {
// This is the first flush before activate is called. Events can now be sent for
// this sensor on this connection.
ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
buffer[i].meta_data.sensor);
mSensorInfo.editValueAt(index).mFirstFlushPending = false;
// Check if this connection has registered for this sensor. If not continue to the
// next sensor_event.
if (index < 0) {
++i;
continue;
}
if (index >= 0 && mSensorInfo[index].mFirstFlushPending == false) {
do {
// Check if there is a pending flush_complete event for this sensor on this connection.
FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
if (flushInfo.mFirstFlushPending == true) {
// This is the first flush before activate is called. Events can now be sent for
// this sensor on this connection.
ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
buffer[i].meta_data.sensor);
flushInfo.mFirstFlushPending = false;
++i;
continue;
}
}
// If there is a pending flush complete event for this sensor on this connection,
// ignore the event and proceed to the next.
if (flushInfo.mFirstFlushPending) {
++i;
continue;
}
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) {
scratch[count++] = buffer[i];
flushInfo.mNumFlushCalls--;
}
++i;
} else {
// Regular sensor event, just copy it to the scratch buffer.
scratch[count++] = buffer[i++];
} while ((i<numEvents) && ((buffer[i].sensor == curr) ||
(buffer[i].type == SENSOR_TYPE_META_DATA &&
buffer[i].meta_data.sensor == curr)));
} else {
i++;
}
}
} while ((i<numEvents) && ((buffer[i].sensor == curr) ||
(buffer[i].type == SENSOR_TYPE_META_DATA &&
buffer[i].meta_data.sensor == curr)));
}
} else {
scratch = const_cast<sensors_event_t *>(buffer);
count = numEvents;
}
// Send pending flush events (if any) before sending events from the cache.
// Early return if there are no events for this connection.
if (count == 0) {
return status_t(NO_ERROR);
}
#if DEBUG_CONNECTIONS
mEventsReceived += count;
#endif
if (mCacheSize != 0) {
// There are some events in the cache which need to be sent first. Copy this buffer to
// the end of cache.
if (mCacheSize + count <= mMaxCacheSize) {
memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
mCacheSize += count;
} else {
// Some events need to be dropped.
int remaningCacheSize = mMaxCacheSize - mCacheSize;
if (remaningCacheSize != 0) {
memcpy(&mEventCache[mCacheSize], scratch,
remaningCacheSize * sizeof(sensors_event_t));
}
int numEventsDropped = count - remaningCacheSize;
countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
// Drop the first "numEventsDropped" in the cache.
memmove(mEventCache, &mEventCache[numEventsDropped],
(mCacheSize - numEventsDropped) * sizeof(sensors_event_t));
// Copy the remainingEvents in scratch buffer to the end of cache.
memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
numEventsDropped * sizeof(sensors_event_t));
}
return status_t(NO_ERROR);
}
int numWakeUpSensorEvents = countWakeUpSensorEventsLocked(scratch, count);
mWakeLockRefCount += numWakeUpSensorEvents;
// NOTE: ASensorEvent and sensors_event_t are the same type.
ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(scratch), count);
if (size < 0) {
// Write error, copy events to local cache.
mWakeLockRefCount -= numWakeUpSensorEvents;
if (mEventCache == NULL) {
mMaxCacheSize = computeMaxCacheSizeLocked();
mEventCache = new sensors_event_t[mMaxCacheSize];
mCacheSize = 0;
}
memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
mCacheSize += count;
// Add this file descriptor to the looper to get a callback when this fd is available for
// writing.
mService->getLooper()->addFd(mChannel->getSendFd(), 0,
ALOOPER_EVENT_OUTPUT | ALOOPER_EVENT_INPUT, this, NULL);
return size;
}
#if DEBUG_CONNECTIONS
if (size > 0) {
mEventsSent += count;
}
#endif
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
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;
@ -963,35 +1103,44 @@ status_t SensorService::SensorEventConnection::sendEvents(
flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i);
ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
if (size < 0) {
// ALOGW("dropping %d events on the floor", count);
countFlushCompleteEventsLocked(scratch, count);
return size;
return;
}
ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
flushCompleteEvent.meta_data.sensor);
flushCompleteEvent.meta_data.sensor);
flushInfo.mPendingFlushEventsToSend--;
}
}
}
// Write "count" events at a time.
for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
const int count = (mCacheSize - numEventsSent) < maxWriteSize ?
mCacheSize - numEventsSent : maxWriteSize;
int numWakeUpSensorEvents =
countWakeUpSensorEventsLocked(mEventCache + numEventsSent, count);
mWakeLockRefCount += numWakeUpSensorEvents;
// Early return if there are no events for this connection.
if (count == 0) {
return status_t(NO_ERROR);
ssize_t size = SensorEventQueue::write(mChannel,
reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
count);
if (size < 0) {
memmove(mEventCache, &mEventCache[numEventsSent],
(mCacheSize - numEventsSent) * sizeof(sensors_event_t));
ALOGD_IF(DEBUG_CONNECTIONS, "wrote %d events from cache size==%d ",
numEventsSent, mCacheSize);
mCacheSize -= numEventsSent;
mWakeLockRefCount -= numWakeUpSensorEvents;
return;
}
numEventsSent += count;
#if DEBUG_CONNECTIONS
mEventsSentFromCache += count;
#endif
}
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);
if (size == -EAGAIN) {
// 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);
countFlushCompleteEventsLocked(scratch, count);
mWakeLockRefCount -= numWakeUpSensorEvents;
return size;
}
return size < 0 ? status_t(size) : status_t(NO_ERROR);
ALOGD_IF(DEBUG_CONNECTIONS, "wrote all events from cache size=%d ", mCacheSize);
// All events from the cache have been sent. Reset cache size to zero.
mCacheSize = 0;
// Poll only for ALOOPER_EVENT_INPUT(read) on the file descriptor.
mService->getLooper()->addFd(mChannel->getSendFd(), 0, ALOOPER_EVENT_INPUT, this, NULL);
}
void SensorService::SensorEventConnection::countFlushCompleteEventsLocked(
@ -1015,7 +1164,6 @@ int SensorService::SensorEventConnection::countWakeUpSensorEventsLocked(
for (int i = 0; i < count; ++i) {
if (mService->isWakeUpSensorEvent(scratch[i])) {
scratch[i].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
++mWakeLockRefCount;
return 1;
}
}
@ -1035,6 +1183,7 @@ status_t SensorService::SensorEventConnection::enableDisable(
if (enabled) {
err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
reservedFlags);
} else {
err = mService->disable(this, handle);
}
@ -1055,14 +1204,16 @@ status_t SensorService::SensorEventConnection::flush() {
// Loop through all sensors for this connection and call flush on each of them.
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const int handle = mSensorInfo.keyAt(i);
FlushInfo& flushInfo = mSensorInfo.editValueFor(handle);
if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 || mService->isVirtualSensor(handle)) {
// For older devices just increment pending flush count which will send a trivial
// flush complete event.
FlushInfo& flushInfo = mSensorInfo.editValueFor(handle);
flushInfo.mPendingFlushEventsToSend++;
} else {
status_t err_flush = mService->flushSensor(this, handle);
if (err_flush != NO_ERROR) {
if (err_flush == NO_ERROR) {
flushInfo.mNumFlushCalls++;
} else {
ALOGE("Flush error handle=%d %s", handle, strerror(-err_flush));
}
err = (err_flush != NO_ERROR) ? err_flush : err;
@ -1071,15 +1222,69 @@ status_t SensorService::SensorEventConnection::flush() {
return err;
}
void SensorService::SensorEventConnection::decreaseWakeLockRefCount() {
{
int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* data) {
if (events & ALOOPER_EVENT_HANGUP || events & ALOOPER_EVENT_ERROR) {
return 0;
}
if (events & ALOOPER_EVENT_INPUT) {
char buf;
ssize_t ret = ::recv(fd, &buf, sizeof(buf), MSG_DONTWAIT);
{
Mutex::Autolock _l(mConnectionLock);
--mWakeLockRefCount;
}
// Check if wakelock can be released by sensorservice. mConnectionLock needs to be released
// here as checkWakeLockState() will need it.
if (mWakeLockRefCount == 0) {
mService->checkWakeLockState();
}
// continue getting callbacks.
return 1;
}
if (events & ALOOPER_EVENT_OUTPUT) {
// send sensor data that is stored in mEventCache.
Mutex::Autolock _l(mConnectionLock);
--mWakeLockRefCount;
}
// Release the lock before calling checkWakeLockState which also needs the same connectionLock.
if (mWakeLockRefCount == 0) {
mService->checkWakeLockState();
writeToSocketFromCacheLocked();
}
return 1;
}
int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const {
int fifoWakeUpSensors = 0;
int fifoNonWakeUpSensors = 0;
for (size_t i = 0; i < mSensorInfo.size(); ++i) {
const Sensor& sensor = mService->getSensorFromHandle(mSensorInfo.keyAt(i));
if (sensor.getFifoReservedEventCount() == sensor.getFifoMaxEventCount()) {
// Each sensor has a reserved fifo. Sum up the fifo sizes for all wake up sensors and
// non wake_up sensors.
if (sensor.isWakeUpSensor()) {
fifoWakeUpSensors += sensor.getFifoReservedEventCount();
} else {
fifoNonWakeUpSensors += sensor.getFifoReservedEventCount();
}
} else {
// Shared fifo. Compute the max of the fifo sizes for wake_up and non_wake up sensors.
if (sensor.isWakeUpSensor()) {
fifoWakeUpSensors = fifoWakeUpSensors > sensor.getFifoMaxEventCount() ?
fifoWakeUpSensors : sensor.getFifoMaxEventCount();
} else {
fifoNonWakeUpSensors = fifoNonWakeUpSensors > sensor.getFifoMaxEventCount() ?
fifoNonWakeUpSensors : sensor.getFifoMaxEventCount();
}
}
}
if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) {
// It is extremely unlikely that there is a write failure in non batch mode. Return a cache
// size of 100.
ALOGI("Write failure in non-batch mode");
return 100;
}
return fifoWakeUpSensors + fifoNonWakeUpSensors;
}
// ---------------------------------------------------------------------------

View File

@ -24,7 +24,9 @@
#include <utils/SortedVector.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/AndroidThreads.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
#include <binder/BinderService.h>
@ -38,10 +40,11 @@
// ---------------------------------------------------------------------------
#define DEBUG_CONNECTIONS false
// Max size is 1 MB which is enough to accept a batch of about 10k events.
#define MAX_SOCKET_BUFFER_SIZE_BATCHED 1024 * 1024
// Max size is 100 KB which is enough to accept a batch of about 1000 events.
#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 (1 << 31)
#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
struct sensors_poll_device_t;
struct sensors_module_t;
@ -72,7 +75,8 @@ class SensorService :
virtual sp<ISensorEventConnection> createSensorEventConnection();
virtual status_t dump(int fd, const Vector<String16>& args);
class SensorEventConnection : public BnSensorEventConnection {
class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
friend class SensorService;
virtual ~SensorEventConnection();
virtual void onFirstRef();
virtual sp<BitTube> getSensorChannel() const;
@ -80,7 +84,6 @@ 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.
@ -90,7 +93,20 @@ class SensorService :
// 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);
int countWakeUpSensorEventsLocked(sensors_event_t* scratch, int count);
// Writes events from mEventCache to the socket.
void writeToSocketFromCacheLocked();
// 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
// shared amongst wake-up sensors and non-wake up sensors.
int computeMaxCacheSizeLocked() const;
// 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.
virtual int handleEvent(int fd, int events, void* data);
sp<SensorService> const mService;
sp<BitTube> mChannel;
@ -108,10 +124,20 @@ 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;
FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
// 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) {}
};
// protected by SensorService::mLock. Key for this vector is the sensor handle.
KeyedVector<int, FlushInfo> mSensorInfo;
sensors_event_t *mEventCache;
int mCacheSize, mMaxCacheSize;
#if DEBUG_CONNECTIONS
int mEventsReceived, mEventsSent, mEventsSentFromCache;
#endif
public:
SensorEventConnection(const sp<SensorService>& service, uid_t uid);
@ -138,6 +164,13 @@ class SensorService :
size_t getNumConnections() const { return mConnections.size(); }
};
class SensorEventAckReceiver : public Thread {
sp<SensorService> const mService;
public:
virtual bool threadLoop();
SensorEventAckReceiver(const sp<SensorService>& service): mService(service) {}
};
String8 getSensorName(int handle) const;
bool isVirtualSensor(int handle) const;
Sensor getSensorFromHandle(int handle) const;
@ -160,6 +193,9 @@ class SensorService :
void checkWakeLockState();
void checkWakeLockStateLocked();
bool isWakeUpSensorEvent(const sensors_event_t& event) const;
sp<Looper> getLooper() const;
// constants
Vector<Sensor> mSensorList;
Vector<Sensor> mUserSensorListDebug;
@ -168,6 +204,7 @@ class SensorService :
Vector<SensorInterface *> mVirtualSensorList;
status_t mInitCheck;
size_t mSocketBufferSize;
sp<Looper> mLooper;
// protected by mLock
mutable Mutex mLock;