Divide huge SensorService files into managable pieces

Splitted SensorService.cpp and SensorService.h into smaller more
manageable pieces with the embedded classes/structs now in individual
files.

Change-Id: I5e75c41b9e0e5c9aff102fe4b0f142c61d1203e2
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
new file mode 100644
index 0000000..ca26535
--- /dev/null
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/socket.h>
+#include <utils/threads.h>
+
+#include <gui/SensorEventQueue.h>
+
+#include "vec.h"
+#include "SensorEventConnection.h"
+
+namespace android {
+
+SensorService::SensorEventConnection::SensorEventConnection(
+        const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
+        const String16& opPackageName)
+    : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
+      mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
+      mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName) {
+    mChannel = new BitTube(mService->mSocketBufferSize);
+#if DEBUG_CONNECTIONS
+    mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
+    mTotalAcksNeeded = mTotalAcksReceived = 0;
+#endif
+}
+
+SensorService::SensorEventConnection::~SensorEventConnection() {
+    ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
+    mService->cleanupConnection(this);
+    if (mEventCache != NULL) {
+        delete mEventCache;
+    }
+}
+
+void SensorService::SensorEventConnection::onFirstRef() {
+    LooperCallback::onFirstRef();
+}
+
+bool SensorService::SensorEventConnection::needsWakeLock() {
+    Mutex::Autolock _l(mConnectionLock);
+    return !mDead && mWakeLockRefCount > 0;
+}
+
+void SensorService::SensorEventConnection::resetWakeLockRefCount() {
+    Mutex::Autolock _l(mConnectionLock);
+    mWakeLockRefCount = 0;
+}
+
+void SensorService::SensorEventConnection::dump(String8& result) {
+    Mutex::Autolock _l(mConnectionLock);
+    result.appendFormat("\tOperating Mode: %s\n",mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
+    result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
+            "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
+            mMaxCacheSize);
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
+        result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
+                            mService->getSensorName(mSensorInfo.keyAt(i)).string(),
+                            mSensorInfo.keyAt(i),
+                            flushInfo.mFirstFlushPending ? "First flush pending" :
+                                                           "active",
+                            flushInfo.mPendingFlushEventsToSend);
+    }
+#if DEBUG_CONNECTIONS
+    result.appendFormat("\t events recvd: %d | sent %d | cache %d | dropped %d |"
+            " total_acks_needed %d | total_acks_recvd %d\n",
+            mEventsReceived,
+            mEventsSent,
+            mEventsSentFromCache,
+            mEventsReceived - (mEventsSentFromCache + mEventsSent + mCacheSize),
+            mTotalAcksNeeded,
+            mTotalAcksReceived);
+#endif
+}
+
+bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    if (!canAccessSensor(mService->getSensorFromHandle(handle),
+            "Tried adding", mOpPackageName)) {
+        return false;
+    }
+    if (mSensorInfo.indexOfKey(handle) < 0) {
+        mSensorInfo.add(handle, FlushInfo());
+        return true;
+    }
+    return false;
+}
+
+bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    if (mSensorInfo.removeItem(handle) >= 0) {
+        return true;
+    }
+    return false;
+}
+
+bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
+    Mutex::Autolock _l(mConnectionLock);
+    return mSensorInfo.indexOfKey(handle) >= 0;
+}
+
+bool SensorService::SensorEventConnection::hasAnySensor() const {
+    Mutex::Autolock _l(mConnectionLock);
+    return mSensorInfo.size() ? true : false;
+}
+
+bool SensorService::SensorEventConnection::hasOneShotSensors() const {
+    Mutex::Autolock _l(mConnectionLock);
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const int handle = mSensorInfo.keyAt(i);
+        if (mService->getSensorFromHandle(handle).getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+            return true;
+        }
+    }
+    return false;
+}
+
+String8 SensorService::SensorEventConnection::getPackageName() const {
+    return mPackageName;
+}
+
+void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
+                                bool value) {
+    Mutex::Autolock _l(mConnectionLock);
+    ssize_t index = mSensorInfo.indexOfKey(handle);
+    if (index >= 0) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+        flushInfo.mFirstFlushPending = value;
+    }
+}
+
+void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {
+    Mutex::Autolock _l(mConnectionLock);
+    updateLooperRegistrationLocked(looper);
+}
+
+void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
+        const sp<Looper>& looper) {
+    bool isConnectionActive = (mSensorInfo.size() > 0 && !mDataInjectionMode) ||
+                              mDataInjectionMode;
+    // If all sensors are unregistered OR Looper has encountered an error, we can remove the Fd from
+    // the Looper if it has been previously added.
+    if (!isConnectionActive || mDead) { if (mHasLooperCallbacks) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "%p removeFd fd=%d", this,
+                 mChannel->getSendFd());
+        looper->removeFd(mChannel->getSendFd()); mHasLooperCallbacks = false; }
+    return; }
+
+    int looper_flags = 0;
+    if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
+    if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const int handle = mSensorInfo.keyAt(i);
+        if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
+            looper_flags |= ALOOPER_EVENT_INPUT;
+            break;
+        }
+    }
+
+    // If flags is still set to zero, we don't need to add this fd to the Looper, if the fd has
+    // already been added, remove it. This is likely to happen when ALL the events stored in the
+    // cache have been sent to the corresponding app.
+    if (looper_flags == 0) {
+        if (mHasLooperCallbacks) {
+            ALOGD_IF(DEBUG_CONNECTIONS, "removeFd fd=%d", mChannel->getSendFd());
+            looper->removeFd(mChannel->getSendFd());
+            mHasLooperCallbacks = false;
+        }
+        return;
+    }
+
+    // Add the file descriptor to the Looper for receiving acknowledegments if the app has
+    // registered for wake-up sensors OR for sending events in the cache.
+    int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, NULL);
+    if (ret == 1) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "%p addFd fd=%d", this, mChannel->getSendFd());
+        mHasLooperCallbacks = true;
+    } else {
+        ALOGE("Looper::addFd failed ret=%d fd=%d", ret, mChannel->getSendFd());
+    }
+}
+
+void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    ssize_t index = mSensorInfo.indexOfKey(handle);
+    if (index >= 0) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+        flushInfo.mPendingFlushEventsToSend++;
+    }
+}
+
+status_t SensorService::SensorEventConnection::sendEvents(
+        sensors_event_t const* buffer, size_t numEvents,
+        sensors_event_t* scratch,
+        SensorEventConnection const * const * mapFlushEventsToConnections) {
+    // filter out events not for this connection
+    int count = 0;
+    Mutex::Autolock _l(mConnectionLock);
+    if (scratch) {
+        size_t i=0;
+        while (i<numEvents) {
+            int32_t sensor_handle = buffer[i].sensor;
+            if (buffer[i].type == SENSOR_TYPE_META_DATA) {
+                ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
+                        buffer[i].meta_data.sensor);
+                // Setting sensor_handle to the correct sensor to ensure the sensor events per
+                // connection are filtered correctly.  buffer[i].sensor is zero for meta_data
+                // events.
+                sensor_handle = buffer[i].meta_data.sensor;
+            }
+
+            ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
+            // Check if this connection has registered for this sensor. If not continue to the
+            // next sensor_event.
+            if (index < 0) {
+                ++i;
+                continue;
+            }
+
+            FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+            // Check if there is a pending flush_complete event for this sensor on this connection.
+            if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
+                    this == mapFlushEventsToConnections[i]) {
+                flushInfo.mFirstFlushPending = false;
+                ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
+                        buffer[i].meta_data.sensor);
+                ++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 {
+                // Keep copying events into the scratch buffer as long as they are regular
+                // sensor_events are from the same sensor_handle OR they are flush_complete_events
+                // from the same sensor_handle AND the current connection is mapped to the
+                // corresponding flush_complete_event.
+                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
+                    if (this == mapFlushEventsToConnections[i]) {
+                        scratch[count++] = buffer[i];
+                    }
+                    ++i;
+                } else {
+                    // Regular sensor event, just copy it to the scratch buffer.
+                    scratch[count++] = buffer[i++];
+                }
+            } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle &&
+                                        buffer[i].type != SENSOR_TYPE_META_DATA) ||
+                                       (buffer[i].type == SENSOR_TYPE_META_DATA  &&
+                                        buffer[i].meta_data.sensor == sensor_handle)));
+        }
+    } else {
+        scratch = const_cast<sensors_event_t *>(buffer);
+        count = numEvents;
+    }
+
+    sendPendingFlushEventsLocked();
+    // 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 {
+            // 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) {
+                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 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;
+#if DEBUG_CONNECTIONS
+        ++mTotalAcksNeeded;
+#endif
+    }
+
+    // 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.
+        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;
+            if (mWakeLockRefCount > 0) {
+                --mWakeLockRefCount;
+            }
+#if DEBUG_CONNECTIONS
+            --mTotalAcksNeeded;
+#endif
+        }
+        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.
+        updateLooperRegistrationLocked(mService->getLooper());
+        return size;
+    }
+
+#if DEBUG_CONNECTIONS
+    if (size > 0) {
+        mEventsSent += count;
+    }
+#endif
+
+    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;
+    memset(&flushCompleteEvent, 0, sizeof(flushCompleteEvent));
+    flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
+    // 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) {
+            const int sensor_handle = mSensorInfo.keyAt(i);
+            flushCompleteEvent.meta_data.sensor = sensor_handle;
+            bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor();
+            if (wakeUpSensor) {
+               ++mWakeLockRefCount;
+               flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            }
+            ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
+            if (size < 0) {
+                if (wakeUpSensor) --mWakeLockRefCount;
+                return;
+            }
+            ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
+                    flushCompleteEvent.meta_data.sensor);
+            flushInfo.mPendingFlushEventsToSend--;
+        }
+    }
+}
+
+void SensorService::SensorEventConnection::writeToSocketFromCache() {
+    // At a time write at most half the size of the receiver buffer in SensorEventQueue OR
+    // half the size of the socket buffer allocated in BitTube whichever is smaller.
+    const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
+            int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
+    Mutex::Autolock _l(mConnectionLock);
+    // Send pending flush complete events (if any)
+    sendPendingFlushEventsLocked();
+    for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
+        const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize);
+        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;
+#if DEBUG_CONNECTIONS
+            ++mTotalAcksNeeded;
+#endif
+        }
+
+        ssize_t size = SensorEventQueue::write(mChannel,
+                          reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
+                          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;
+                if (mWakeLockRefCount > 0) {
+                    --mWakeLockRefCount;
+                }
+#if DEBUG_CONNECTIONS
+                --mTotalAcksNeeded;
+#endif
+            }
+            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;
+            return;
+        }
+        numEventsSent += numEventsToWrite;
+#if DEBUG_CONNECTIONS
+        mEventsSentFromCache += numEventsToWrite;
+#endif
+    }
+    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;
+    // There are no more events in the cache. We don't need to poll for write on the fd.
+    // Update Looper registration.
+    updateLooperRegistrationLocked(mService->getLooper());
+}
+
+void SensorService::SensorEventConnection::countFlushCompleteEventsLocked(
+                sensors_event_t const* scratch, const int numEventsDropped) {
+    ALOGD_IF(DEBUG_CONNECTIONS, "dropping %d events ", numEventsDropped);
+    // Count flushComplete events in the events that are about to the dropped. These will be sent
+    // separately before the next batch of events.
+    for (int j = 0; j < numEventsDropped; ++j) {
+        if (scratch[j].type == SENSOR_TYPE_META_DATA) {
+            FlushInfo& flushInfo = mSensorInfo.editValueFor(scratch[j].meta_data.sensor);
+            flushInfo.mPendingFlushEventsToSend++;
+            ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
+                     flushInfo.mPendingFlushEventsToSend);
+        }
+    }
+    return;
+}
+
+int SensorService::SensorEventConnection::findWakeUpSensorEventLocked(
+                       sensors_event_t const* scratch, const int count) {
+    for (int i = 0; i < count; ++i) {
+        if (mService->isWakeUpSensorEvent(scratch[i])) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
+{
+    return mChannel;
+}
+
+status_t SensorService::SensorEventConnection::enableDisable(
+        int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
+        int reservedFlags)
+{
+    status_t err;
+    if (enabled) {
+        err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
+                               reservedFlags, mOpPackageName);
+
+    } else {
+        err = mService->disable(this, handle);
+    }
+    return err;
+}
+
+status_t SensorService::SensorEventConnection::setEventRate(
+        int handle, nsecs_t samplingPeriodNs)
+{
+    return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+}
+
+status_t  SensorService::SensorEventConnection::flush() {
+    return  mService->flushSensor(this, mOpPackageName);
+}
+
+int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* /*data*/) {
+    if (events & ALOOPER_EVENT_HANGUP || events & ALOOPER_EVENT_ERROR) {
+        {
+            // If the Looper encounters some error, set the flag mDead, reset mWakeLockRefCount,
+            // and remove the fd from Looper. Call checkWakeLockState to know if SensorService
+            // can release the wake-lock.
+            ALOGD_IF(DEBUG_CONNECTIONS, "%p Looper error %d", this, fd);
+            Mutex::Autolock _l(mConnectionLock);
+            mDead = true;
+            mWakeLockRefCount = 0;
+            updateLooperRegistrationLocked(mService->getLooper());
+        }
+        mService->checkWakeLockState();
+        if (mDataInjectionMode) {
+            // If the Looper has encountered some error in data injection mode, reset SensorService
+            // back to normal mode.
+            mService->resetToNormalMode();
+            mDataInjectionMode = false;
+        }
+        return 1;
+    }
+
+    if (events & ALOOPER_EVENT_INPUT) {
+        unsigned char buf[sizeof(sensors_event_t)];
+        ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
+        {
+           Mutex::Autolock _l(mConnectionLock);
+           if (numBytesRead == sizeof(sensors_event_t)) {
+               if (!mDataInjectionMode) {
+                   ALOGE("Data injected in normal mode, dropping event"
+                         "package=%s uid=%d", mPackageName.string(), mUid);
+                   // Unregister call backs.
+                   return 0;
+               }
+               SensorDevice& dev(SensorDevice::getInstance());
+               sensors_event_t sensor_event;
+               memset(&sensor_event, 0, sizeof(sensor_event));
+               memcpy(&sensor_event, buf, sizeof(sensors_event_t));
+               Sensor sensor = mService->getSensorFromHandle(sensor_event.sensor);
+               sensor_event.type = sensor.getType();
+               dev.injectSensorData(&sensor_event);
+#if DEBUG_CONNECTIONS
+               ++mEventsReceived;
+#endif
+           } else if (numBytesRead == sizeof(uint32_t)) {
+               uint32_t numAcks = 0;
+               memcpy(&numAcks, buf, numBytesRead);
+               // Sanity check to ensure  there are no read errors in recv, numAcks is always
+               // within the range and not zero. If any of the above don't hold reset
+               // mWakeLockRefCount to zero.
+               if (numAcks > 0 && numAcks < mWakeLockRefCount) {
+                   mWakeLockRefCount -= numAcks;
+               } else {
+                   mWakeLockRefCount = 0;
+               }
+#if DEBUG_CONNECTIONS
+               mTotalAcksReceived += numAcks;
+#endif
+           } else {
+               // Read error, reset wakelock refcount.
+               mWakeLockRefCount = 0;
+           }
+        }
+        // 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 for this connection.
+        mService->sendEventsFromCache(this);
+    }
+    return 1;
+}
+
+int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const {
+    size_t fifoWakeUpSensors = 0;
+    size_t 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 that is equal to that of the batch mode.
+       // ALOGW("Write failure in non-batch mode");
+       return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t);
+   }
+   return fifoWakeUpSensors + fifoNonWakeUpSensors;
+}
+
+} // namespace android
+