OSDN Git Service

Divide huge SensorService files into managable pieces
authorPeng Xu <pengxu@google.com>
Fri, 11 Dec 2015 02:02:41 +0000 (18:02 -0800)
committerPeng Xu <pengxu@google.com>
Sun, 20 Dec 2015 21:46:07 +0000 (13:46 -0800)
Splitted SensorService.cpp and SensorService.h into smaller more
manageable pieces with the embedded classes/structs now in individual
files.

Change-Id: I5e75c41b9e0e5c9aff102fe4b0f142c61d1203e2

services/sensorservice/Android.mk
services/sensorservice/MostRecentEventLogger.cpp [new file with mode: 0644]
services/sensorservice/MostRecentEventLogger.h [new file with mode: 0644]
services/sensorservice/SensorEventAckReceiver.h [new file with mode: 0644]
services/sensorservice/SensorEventConnection.cpp [new file with mode: 0644]
services/sensorservice/SensorEventConnection.h [new file with mode: 0644]
services/sensorservice/SensorRecord.cpp [new file with mode: 0644]
services/sensorservice/SensorRecord.h [new file with mode: 0644]
services/sensorservice/SensorRegistrationInfo.h [new file with mode: 0644]
services/sensorservice/SensorService.cpp
services/sensorservice/SensorService.h

index 4f24ddc..d84ce42 100644 (file)
@@ -12,7 +12,11 @@ LOCAL_SRC_FILES:= \
     SensorDevice.cpp \
     SensorFusion.cpp \
     SensorInterface.cpp \
-    SensorService.cpp
+    SensorService.cpp \
+    SensorEventConnection.cpp \
+    MostRecentEventLogger.cpp \
+    SensorRecord.cpp \
+
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
 
diff --git a/services/sensorservice/MostRecentEventLogger.cpp b/services/sensorservice/MostRecentEventLogger.cpp
new file mode 100644 (file)
index 0000000..0bd0e17
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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 "MostRecentEventLogger.h"
+
+namespace android {
+
+SensorService::MostRecentEventLogger::MostRecentEventLogger(int sensorType) :
+        mSensorType(sensorType), mNextInd(0) {
+
+    mBufSize = (sensorType == SENSOR_TYPE_STEP_COUNTER ||
+                sensorType == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+                sensorType == SENSOR_TYPE_ACCELEROMETER) ? LOG_SIZE : LOG_SIZE_LARGE;
+
+    mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
+    mSensorType = sensorType;
+    for (int i = 0; i < mBufSize; ++i) {
+        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
+    }
+}
+
+void SensorService::MostRecentEventLogger::addEvent(const sensors_event_t& event) {
+    TrimmedSensorEvent *curr_event = mTrimmedSensorEventArr[mNextInd];
+    curr_event->mTimestamp = event.timestamp;
+    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+        curr_event->mStepCounter = event.u64.step_counter;
+    } else {
+        memcpy(curr_event->mData, event.data,
+                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
+    }
+    time_t rawtime = time(NULL);
+    struct tm * timeinfo = localtime(&rawtime);
+    curr_event->mHour = timeinfo->tm_hour;
+    curr_event->mMin = timeinfo->tm_min;
+    curr_event->mSec = timeinfo->tm_sec;
+    mNextInd = (mNextInd + 1) % mBufSize;
+}
+
+void SensorService::MostRecentEventLogger::printBuffer(String8& result) const {
+    const int numData = SensorService::getNumEventsForSensorType(mSensorType);
+    int i = mNextInd, eventNum = 1;
+    result.appendFormat("last %d events = < ", mBufSize);
+    do {
+        if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
+            // Sentinel, ignore.
+            i = (i + 1) % mBufSize;
+            continue;
+        }
+        result.appendFormat("%d) ", eventNum++);
+        if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+            result.appendFormat("%llu,", mTrimmedSensorEventArr[i]->mStepCounter);
+        } else {
+            for (int j = 0; j < numData; ++j) {
+                result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]);
+            }
+        }
+        result.appendFormat("%lld %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
+                mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
+                mTrimmedSensorEventArr[i]->mSec);
+        i = (i + 1) % mBufSize;
+    } while (i != mNextInd);
+    result.appendFormat(">\n");
+}
+
+bool SensorService::MostRecentEventLogger::populateLastEvent(sensors_event_t *event) {
+    int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
+    // Check if the buffer is empty.
+    if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
+        return false;
+    }
+    event->version = sizeof(sensors_event_t);
+    event->type = mSensorType;
+    event->timestamp = mTrimmedSensorEventArr[lastEventInd]->mTimestamp;
+    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+          event->u64.step_counter = mTrimmedSensorEventArr[lastEventInd]->mStepCounter;
+    } else {
+        memcpy(event->data, mTrimmedSensorEventArr[lastEventInd]->mData,
+                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
+    }
+    return true;
+}
+
+SensorService::MostRecentEventLogger::~MostRecentEventLogger() {
+    for (int i = 0; i < mBufSize; ++i) {
+        delete mTrimmedSensorEventArr[i];
+    }
+    delete [] mTrimmedSensorEventArr;
+}
+
+// -----------------------------------------------------------------------------
+SensorService::MostRecentEventLogger::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
+    mTimestamp = -1;
+    const int numData = SensorService::getNumEventsForSensorType(sensorType);
+    if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
+        mStepCounter = 0;
+    } else {
+        mData = new float[numData];
+        for (int i = 0; i < numData; ++i) {
+            mData[i] = -1.0;
+        }
+    }
+    mHour = mMin = mSec = INT32_MIN;
+}
+
+bool SensorService::MostRecentEventLogger::TrimmedSensorEvent::
+    isSentinel(const TrimmedSensorEvent& event) {
+    return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
+}
+
+} // namespace android
diff --git a/services/sensorservice/MostRecentEventLogger.h b/services/sensorservice/MostRecentEventLogger.h
new file mode 100644 (file)
index 0000000..68c1661
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_MOST_RECENT_EVENT_LOGGER_H
+#define ANDROID_MOST_RECENT_EVENT_LOGGER_H
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+// A circular buffer of TrimmedSensorEvents. The size of this buffer is typically 10. The last N
+// events generated from the sensor are stored in this buffer. The buffer is NOT cleared when the
+// sensor unregisters and as a result very old data in the dumpsys output can be seen, which is an
+// intended behavior.
+class SensorService::MostRecentEventLogger {
+public:
+    MostRecentEventLogger(int sensorType);
+    void addEvent(const sensors_event_t& event);
+    void printBuffer(String8& buffer) const;
+    bool populateLastEvent(sensors_event_t *event);
+    ~MostRecentEventLogger();
+
+private:
+    // sensor_event_t with only the data and the timestamp.
+    static const size_t LOG_SIZE = 10;
+    static const size_t LOG_SIZE_LARGE = 50;
+
+    struct TrimmedSensorEvent {
+        union {
+            float *mData;
+            uint64_t mStepCounter;
+        };
+        // Timestamp from the sensors_event_t.
+        int64_t mTimestamp;
+        // HH:MM:SS local time at which this sensor event is read at SensorService. Useful
+        // for debugging.
+        int32_t mHour, mMin, mSec;
+
+        TrimmedSensorEvent(int sensorType);
+        static bool isSentinel(const TrimmedSensorEvent& event);
+
+        ~TrimmedSensorEvent() {
+            delete [] mData;
+        }
+    };
+
+    int mNextInd;
+    int mSensorType;
+    int mBufSize;
+    TrimmedSensorEvent ** mTrimmedSensorEventArr;
+};
+
+} // namespace android;
+
+#endif // ANDROID_MOST_RECENT_EVENT_LOGGER_H
+
diff --git a/services/sensorservice/SensorEventAckReceiver.h b/services/sensorservice/SensorEventAckReceiver.h
new file mode 100644 (file)
index 0000000..998597a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_EVENT_ACK_RECEIVER_H
+#define ANDROID_SENSOR_EVENT_ACK_RECEIVER_H
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+class SensorService::SensorEventAckReceiver : public Thread {
+    sp<SensorService> const mService;
+public:
+    virtual bool threadLoop();
+    SensorEventAckReceiver(const sp<SensorService>& service)
+            : mService(service) {
+    }
+};
+
+}
+
+#endif // ANDROID_SENSOR_EVNET_ACK_RECEIVER_H
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
new file mode 100644 (file)
index 0000000..ca26535
--- /dev/null
@@ -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
+
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
new file mode 100644 (file)
index 0000000..b796cc0
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_EVENT_CONNECTION_H
+#define ANDROID_SENSOR_EVENT_CONNECTION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Vector.h>
+#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 <utils/String8.h>
+
+#include <binder/BinderService.h>
+
+#include <gui/Sensor.h>
+#include <gui/BitTube.h>
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+class SensorService::SensorEventConnection:
+    public BnSensorEventConnection, public LooperCallback {
+
+    friend class SensorService;
+
+public:
+    SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
+                          bool isDataInjectionMode, const String16& opPackageName);
+
+    status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
+                        SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
+    bool hasSensor(int32_t handle) const;
+    bool hasAnySensor() const;
+    bool hasOneShotSensors() const;
+    bool addSensor(int32_t handle);
+    bool removeSensor(int32_t handle);
+    void setFirstFlushPending(int32_t handle, bool value);
+    void dump(String8& result);
+    bool needsWakeLock();
+    void resetWakeLockRefCount();
+    String8 getPackageName() const;
+
+    uid_t getUid() const { return mUid; }
+
+private:
+    virtual ~SensorEventConnection();
+    virtual void onFirstRef();
+    virtual sp<BitTube> getSensorChannel() const;
+    virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
+                                   nsecs_t maxBatchReportLatencyNs, int reservedFlags);
+    virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
+    virtual status_t flush();
+    // 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 const* scratch, int numEventsDropped);
+
+    // 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 writeToSocketFromCache();
+
+    // 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;
+
+    // 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.
+    virtual int handleEvent(int fd, int events, void* data);
+
+    // Increment mPendingFlushEventsToSend for the given sensor handle.
+    void incrementPendingFlushCount(int32_t handle);
+
+    // Add or remove the file descriptor associated with the BitTube to the looper. If mDead is set
+    // to true or there are no more sensors for this connection, the file descriptor is removed if
+    // it has been previously added to the Looper. Depending on the state of the connection FD may
+    // be added to the Looper. The flags to set are determined by the internal state of the
+    // connection. FDs are added to the looper when wake-up sensors are registered (to poll for
+    // acknowledgements) and when write fails on the socket when there are too many error and the
+    // other end hangs up or when this client unregisters for this connection.
+    void updateLooperRegistration(const sp<Looper>& looper); void
+            updateLooperRegistrationLocked(const sp<Looper>& looper);
+
+    sp<SensorService> const mService;
+    sp<BitTube> mChannel;
+    uid_t mUid;
+    mutable Mutex mConnectionLock;
+    // Number of events from wake up sensors which are still pending and haven't been delivered to
+    // the corresponding application. It is incremented by one unit for each write to the socket.
+    uint32_t mWakeLockRefCount;
+
+    // If this flag is set to true, it means that the file descriptor associated with the BitTube
+    // has been added to the Looper in SensorService. This flag is typically set when this
+    // connection has wake-up sensors associated with it or when write has failed on this connection
+    // and we're storing some events in the cache.
+    bool mHasLooperCallbacks;
+    // If there are any errors associated with the Looper this flag is set to true and
+    // mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if this
+    // flag is set.
+    bool mDead;
+
+    bool mDataInjectionMode;
+    struct FlushInfo {
+        // The number of flush complete events dropped for this sensor is stored here.  They are
+        // sent separately before the next batch of events.
+        int mPendingFlushEventsToSend;
+
+        // 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) {}
+    };
+    // protected by SensorService::mLock. Key for this vector is the sensor handle.
+    KeyedVector<int, FlushInfo> mSensorInfo;
+
+    sensors_event_t *mEventCache;
+    int mCacheSize, mMaxCacheSize;
+    String8 mPackageName;
+    const String16 mOpPackageName;
+#if DEBUG_CONNECTIONS
+    int mEventsReceived, mEventsSent, mEventsSentFromCache;
+    int mTotalAcksNeeded, mTotalAcksReceived;
+#endif
+
+};
+
+} // namepsace android
+
+#endif // ANDROID_SENSOR_EVENT_CONNECTION_H
+
diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp
new file mode 100644 (file)
index 0000000..644cfb0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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 "SensorRecord.h"
+
+#include "SensorEventConnection.h"
+
+namespace android {
+
+SensorService::SensorRecord::SensorRecord(
+        const sp<SensorEventConnection>& connection)
+{
+    mConnections.add(connection);
+}
+
+bool SensorService::SensorRecord::addConnection(
+        const sp<SensorEventConnection>& connection)
+{
+    if (mConnections.indexOf(connection) < 0) {
+        mConnections.add(connection);
+        return true;
+    }
+    return false;
+}
+
+bool SensorService::SensorRecord::removeConnection(
+        const wp<SensorEventConnection>& connection)
+{
+    ssize_t index = mConnections.indexOf(connection);
+    if (index >= 0) {
+        mConnections.removeItemsAt(index, 1);
+    }
+    // Remove this connections from the queue of flush() calls made on this sensor.
+    for (Vector< wp<SensorEventConnection> >::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<SensorEventConnection>& 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;
+}
+
+void SensorService::SensorRecord::clearAllPendingFlushConnections() {
+    mPendingFlushConnections.clear();
+}
+
+} // namespace android
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
new file mode 100644 (file)
index 0000000..29b970d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_RECORD_H
+#define ANDROID_SENSOR_RECORD_H
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+class SensorService::SensorRecord {
+public:
+    SensorRecord(const sp<SensorEventConnection>& connection);
+    bool addConnection(const sp<SensorEventConnection>& connection);
+    bool removeConnection(const wp<SensorEventConnection>& connection);
+    size_t getNumConnections() const { return mConnections.size(); }
+
+    void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+    void removeFirstPendingFlushConnection();
+    SensorEventConnection * getFirstPendingFlushConnection();
+    void clearAllPendingFlushConnections();
+private:
+    SortedVector< wp<SensorEventConnection> > mConnections;
+    // A queue of all flush() calls made on this sensor. Flush complete events
+    // will be sent in this order.
+    Vector< wp<SensorEventConnection> > mPendingFlushConnections;
+};
+
+}
+
+#endif // ANDROID_SENSOR_RECORD_H
diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h
new file mode 100644 (file)
index 0000000..54d815b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_REGISTRATION_INFO_H
+#define ANDROID_SENSOR_REGISTRATION_INFO_H
+
+namespace android {
+
+class SensorService;
+
+struct SensorService::SensorRegistrationInfo {
+    int32_t mSensorHandle;
+    String8 mPackageName;
+    bool mActivated;
+    int32_t mSamplingRateUs;
+    int32_t mMaxReportLatencyUs;
+    int32_t mHour, mMin, mSec;
+
+    SensorRegistrationInfo() : mPackageName() {
+        mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
+        mHour = mMin = mSec = INT32_MIN;
+        mActivated = false;
+    }
+
+    static bool isSentinel(const SensorRegistrationInfo& info) {
+       return (info.mHour == INT32_MIN &&
+               info.mMin == INT32_MIN &&
+               info.mSec == INT32_MIN);
+    }
+};
+
+} // namespace android;
+
+#endif // ANDROID_SENSOR_REGISTRATION_INFO_H
+
+
index b6a5d66..acad61c 100644 (file)
  * limitations under the License.
  */
 
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
 #include <cutils/properties.h>
 
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Singleton.h>
-#include <utils/String16.h>
-
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
 
-#include <gui/ISensorServer.h>
-#include <gui/ISensorEventConnection.h>
 #include <gui/SensorEventQueue.h>
 
 #include <hardware/sensors.h>
 #include "OrientationSensor.h"
 #include "RotationVectorSensor.h"
 #include "SensorFusion.h"
+
 #include "SensorService.h"
+#include "SensorEventConnection.h"
+#include "SensorEventAckReceiver.h"
+#include "SensorRecord.h"
+#include "SensorRegistrationInfo.h"
+#include "MostRecentEventLogger.h"
+
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -282,8 +277,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
 {
     String8 result;
     if (!PermissionCache::checkCallingPermission(sDump)) {
-        result.appendFormat("Permission Denial: "
-                "can't dump SensorService from pid=%d, uid=%d\n",
+        result.appendFormat("Permission Denial: can't dump SensorService from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
     } else {
@@ -396,7 +390,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& args)
 
                 int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
                 if (bufIndex >= 0) {
-                    const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex);
+                    const MostRecentEventLogger* buf = mLastEventSeen.valueAt(bufIndex);
                     if (buf != NULL && s.getRequiredPermission().isEmpty()) {
                         buf->printBuffer(result);
                     } else {
@@ -500,9 +494,9 @@ bool SensorService::threadLoop()
 {
     ALOGD("nuSensorService thread starting...");
 
-    // each virtual sensor could generate an event per "real" event, that's why we need
-    // to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.
-    // in practice, this is too aggressive, but guaranteed to be enough.
+    // each virtual sensor could generate an event per "real" event, that's why we need to size
+    // numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.  in practice, this is too
+    // aggressive, but guaranteed to be enough.
     const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
     const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
 
@@ -522,14 +516,15 @@ bool SensorService::threadLoop()
              mSensorEventBuffer[i].flags = 0;
         }
 
-        // Make a copy of the connection vector as some connections may be removed during the
-        // course of this loop (especially when one-shot sensor events are present in the
-        // sensor_event buffer). Promote all connections to StrongPointers before the lock is
-        // acquired. If the destructor of the sp gets called when the lock is acquired, it may
-        // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for
-        // cleanup. So copy all the strongPointers to a vector before the lock is acquired.
+        // Make a copy of the connection vector as some connections may be removed during the course
+        // of this loop (especially when one-shot sensor events are present in the sensor_event
+        // buffer). Promote all connections to StrongPointers before the lock is acquired. If the
+        // destructor of the sp gets called when the lock is acquired, it may result in a deadlock
+        // as ~SensorEventConnection() needs to acquire mLock again for cleanup. So copy all the
+        // strongPointers to a vector before the lock is acquired.
         SortedVector< sp<SensorEventConnection> > activeConnections;
         populateActiveConnections(&activeConnections);
+
         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,
@@ -598,10 +593,10 @@ bool SensorService::threadLoop()
             }
         }
 
-        // Map flush_complete_events in the buffer to SensorEventConnections which called
-        // flush on the hardware sensor. mapFlushEventsToConnections[i] will be the
-        // SensorEventConnection mapped to the corresponding flush_complete_event in
-        // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
+        // Map flush_complete_events in the buffer to SensorEventConnections which called flush on
+        // the hardware sensor. mapFlushEventsToConnections[i] will be the SensorEventConnection
+        // mapped to the corresponding flush_complete_event in mSensorEventBuffer[i] if such a
+        // mapping exists (NULL otherwise).
         for (int i = 0; i < count; ++i) {
             mMapFlushEventsToConnections[i] = NULL;
             if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
@@ -699,9 +694,9 @@ void SensorService::recordLastValueLocked(
         const sensors_event_t* buffer, size_t count) {
     for (size_t i = 0; i < count; i++) {
         if (buffer[i].type != SENSOR_TYPE_META_DATA) {
-            CircularBuffer* &circular_buf = mLastEventSeen.editValueFor(buffer[i].sensor);
+            MostRecentEventLogger* &circular_buf = mLastEventSeen.editValueFor(buffer[i].sensor);
             if (circular_buf == NULL) {
-                circular_buf = new CircularBuffer(buffer[i].type);
+                circular_buf = new MostRecentEventLogger(buffer[i].type);
             }
             circular_buf->addEvent(buffer[i]);
         }
@@ -900,7 +895,7 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
             if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
                 // 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.
-                CircularBuffer *circular_buf = mLastEventSeen.valueFor(handle);
+                MostRecentEventLogger *circular_buf = mLastEventSeen.valueFor(handle);
                 if (circular_buf) {
                     sensors_event_t event;
                     memset(&event, 0, sizeof(event));
@@ -1224,779 +1219,5 @@ int SensorService::getNumEventsForSensorType(int sensor_event_type) {
     }
 }
 
-// ---------------------------------------------------------------------------
-SensorService::SensorRecord::SensorRecord(
-        const sp<SensorEventConnection>& connection)
-{
-    mConnections.add(connection);
-}
-
-bool SensorService::SensorRecord::addConnection(
-        const sp<SensorEventConnection>& connection)
-{
-    if (mConnections.indexOf(connection) < 0) {
-        mConnections.add(connection);
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorRecord::removeConnection(
-        const wp<SensorEventConnection>& connection)
-{
-    ssize_t index = mConnections.indexOf(connection);
-    if (index >= 0) {
-        mConnections.removeItemsAt(index, 1);
-    }
-    // Remove this connections from the queue of flush() calls made on this sensor.
-    for (Vector< wp<SensorEventConnection> >::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<SensorEventConnection>& 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;
-}
-
-void SensorService::SensorRecord::clearAllPendingFlushConnections() {
-    mPendingFlushConnections.clear();
-}
-
-
-// ---------------------------------------------------------------------------
-SensorService::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
-    mTimestamp = -1;
-    const int numData = SensorService::getNumEventsForSensorType(sensorType);
-    if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
-        mStepCounter = 0;
-    } else {
-        mData = new float[numData];
-        for (int i = 0; i < numData; ++i) {
-            mData[i] = -1.0;
-        }
-    }
-    mHour = mMin = mSec = INT32_MIN;
-}
-
-bool SensorService::TrimmedSensorEvent::isSentinel(const TrimmedSensorEvent& event) {
-    return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
-}
-// --------------------------------------------------------------------------
-SensorService::CircularBuffer::CircularBuffer(int sensor_event_type) {
-    mNextInd = 0;
-    mBufSize = CIRCULAR_BUF_SIZE;
-    if (sensor_event_type == SENSOR_TYPE_STEP_COUNTER ||
-            sensor_event_type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
-            sensor_event_type == SENSOR_TYPE_ACCELEROMETER) {
-        mBufSize = CIRCULAR_BUF_SIZE * 5;
-    }
-    mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
-    mSensorType = sensor_event_type;
-    for (int i = 0; i < mBufSize; ++i) {
-        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
-    }
-}
-
-void SensorService::CircularBuffer::addEvent(const sensors_event_t& sensor_event) {
-    TrimmedSensorEvent *curr_event = mTrimmedSensorEventArr[mNextInd];
-    curr_event->mTimestamp = sensor_event.timestamp;
-    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-        curr_event->mStepCounter = sensor_event.u64.step_counter;
-    } else {
-        memcpy(curr_event->mData, sensor_event.data,
-                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
-    }
-    time_t rawtime = time(NULL);
-    struct tm * timeinfo = localtime(&rawtime);
-    curr_event->mHour = timeinfo->tm_hour;
-    curr_event->mMin = timeinfo->tm_min;
-    curr_event->mSec = timeinfo->tm_sec;
-    mNextInd = (mNextInd + 1) % mBufSize;
-}
-
-void SensorService::CircularBuffer::printBuffer(String8& result) const {
-    const int numData = SensorService::getNumEventsForSensorType(mSensorType);
-    int i = mNextInd, eventNum = 1;
-    result.appendFormat("last %d events = < ", mBufSize);
-    do {
-        if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
-            // Sentinel, ignore.
-            i = (i + 1) % mBufSize;
-            continue;
-        }
-        result.appendFormat("%d) ", eventNum++);
-        if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-            result.appendFormat("%" PRIu64 ",", mTrimmedSensorEventArr[i]->mStepCounter);
-        } else {
-            for (int j = 0; j < numData; ++j) {
-                result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]);
-            }
-        }
-        result.appendFormat("%" PRId64 " %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
-                mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
-                mTrimmedSensorEventArr[i]->mSec);
-        i = (i + 1) % mBufSize;
-    } while (i != mNextInd);
-    result.appendFormat(">\n");
-}
-
-bool SensorService::CircularBuffer::populateLastEvent(sensors_event_t *event) {
-    int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
-    // Check if the buffer is empty.
-    if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
-        return false;
-    }
-    event->version = sizeof(sensors_event_t);
-    event->type = mSensorType;
-    event->timestamp = mTrimmedSensorEventArr[lastEventInd]->mTimestamp;
-    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-          event->u64.step_counter = mTrimmedSensorEventArr[lastEventInd]->mStepCounter;
-    } else {
-        memcpy(event->data, mTrimmedSensorEventArr[lastEventInd]->mData,
-                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
-    }
-    return true;
-}
-
-SensorService::CircularBuffer::~CircularBuffer() {
-    for (int i = 0; i < mBufSize; ++i) {
-        delete mTrimmedSensorEventArr[i];
-    }
-    delete [] mTrimmedSensorEventArr;
-}
-
-// ---------------------------------------------------------------------------
-
-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
 
index 7d81d6e..080a550 100644 (file)
@@ -39,9 +39,8 @@
 #include "SensorInterface.h"
 
 #if __clang__
-// Clang warns about SensorEventConnection::dump hiding BBinder::dump
-// The cause isn't fixable without changing the API, so let's tell clang
-// this is indeed intentional.
+// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
+// without changing the API, so let's tell clang this is indeed intentional.
 #pragma clang diagnostic ignored "-Woverloaded-virtual"
 #endif
 
 // For older HALs which don't support batching, use a smaller socket buffer size.
 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
 
-#define CIRCULAR_BUF_SIZE 10
 #define SENSOR_REGISTRATIONS_BUF_SIZE 20
 
-struct sensors_poll_device_t;
-struct sensors_module_t;
-
 namespace android {
 // ---------------------------------------------------------------------------
 
@@ -67,21 +62,47 @@ class SensorService :
         public BnSensorServer,
         protected Thread
 {
+    // nested class/struct for internal use
+    class SensorEventConnection;
+
+public:
+    void cleanupConnection(SensorEventConnection* connection);
+
+    status_t enable(const sp<SensorEventConnection>& connection, int handle,
+                    nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags,
+                    const String16& opPackageName);
+
+    status_t disable(const sp<SensorEventConnection>& connection, int handle);
+
+    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns,
+                          const String16& opPackageName);
+
+    status_t flushSensor(const sp<SensorEventConnection>& connection,
+                         const String16& opPackageName);
+
+private:
     friend class BinderService<SensorService>;
 
+    // nested class/struct for internal use
+    class SensorRecord;
+    class SensorEventAckReceiver;
+    struct TrimmedSensorEvent;
+    class MostRecentEventLogger;
+    struct SensorRegistrationInfo;
+
     enum Mode {
        // The regular operating mode where any application can register/unregister/call flush on
        // sensors.
        NORMAL = 0,
-       // This mode is only used for testing purposes. Not all HALs support this mode. In this
-       // mode, the HAL ignores the sensor data provided by physical sensors and accepts the data
-       // that is injected from the SensorService as if it were the real sensor data. This mode
-       // is primarily used for testing various algorithms like vendor provided SensorFusion,
-       // Step Counter and Step Detector etc. Typically in this mode, there will be a client
-       // (a SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps
-       // can unregister and register for any sensor that supports injection. Registering to sensors
-       // that do not support injection will give an error.
-       // TODO(aakella) : Allow exactly one client to inject sensor data at a time.
+       // This mode is only used for testing purposes. Not all HALs support this mode. In this mode,
+       // the HAL ignores the sensor data provided by physical sensors and accepts the data that is
+       // injected from the SensorService as if it were the real sensor data. This mode is primarily
+       // used for testing various algorithms like vendor provided SensorFusion, Step Counter and
+       // Step Detector etc. Typically in this mode, there will be a client (a
+       // SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps can
+       // unregister and register for any sensor that supports injection. Registering to sensors
+       // that do not support injection will give an error.  TODO(aakella) : Allow exactly one
+       // client to inject sensor data at a time.
        DATA_INJECTION = 1,
        // This mode is used only for testing sensors. Each sensor can be tested in isolation with
        // the required sampling_rate and maxReportLatency parameters without having to think about
@@ -92,9 +113,8 @@ class SensorService :
        // these apps can register/unregister/call flush() on sensors. If SensorService switches to
        // NORMAL mode again, all sensors that were previously registered to are activated with the
        // corresponding paramaters if the application hasn't unregistered for sensors in the mean
-       // time.
-       // NOTE: Non whitelisted app whose sensors were previously deactivated may still receive
-       // events if a whitelisted app requests data from the same sensor.
+       // time.  NOTE: Non whitelisted app whose sensors were previously deactivated may still
+       // receive events if a whitelisted app requests data from the same sensor.
        RESTRICTED = 2
 
       // State Transitions supported.
@@ -104,14 +124,16 @@ class SensorService :
       // Shell commands to switch modes in SensorService.
       // 1) Put SensorService in RESTRICTED mode with packageName .cts. If it is already in
       // restricted mode it is treated as a NO_OP (and packageName is NOT changed).
-      // $ adb shell dumpsys sensorservice restrict .cts.
+      //
+      //     $ adb shell dumpsys sensorservice restrict .cts.
       //
       // 2) Put SensorService in DATA_INJECTION mode with packageName .xts. If it is already in
       // data_injection mode it is treated as a NO_OP (and packageName is NOT changed).
-      // $ adb shell dumpsys sensorservice data_injection .xts.
+      //
+      //     $ adb shell dumpsys sensorservice data_injection .xts.
       //
       // 3) Reset sensorservice back to NORMAL mode.
-      // $ adb shell dumpsys sensorservice enable
+      //     $ adb shell dumpsys sensorservice enable
     };
 
     static const char* WAKE_LOCK_NAME;
@@ -127,207 +149,12 @@ class SensorService :
 
     // ISensorServer interface
     virtual Vector<Sensor> getSensorList(const String16& opPackageName);
-    virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
-             int requestedMode, const String16& opPackageName);
+    virtual sp<ISensorEventConnection> createSensorEventConnection(
+            const String8& packageName,
+            int requestedMode, const String16& opPackageName);
     virtual int isDataInjectionEnabled();
     virtual status_t dump(int fd, const Vector<String16>& args);
 
-    class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
-        friend class SensorService;
-        virtual ~SensorEventConnection();
-        virtual void onFirstRef();
-        virtual sp<BitTube> getSensorChannel() const;
-        virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
-                                       nsecs_t maxBatchReportLatencyNs, int reservedFlags);
-        virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
-        virtual status_t flush();
-        // 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 const* scratch, int numEventsDropped);
-
-        // 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 writeToSocketFromCache();
-
-        // 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;
-
-        // 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.
-        virtual int handleEvent(int fd, int events, void* data);
-
-        // Increment mPendingFlushEventsToSend for the given sensor handle.
-        void incrementPendingFlushCount(int32_t handle);
-
-        // Add or remove the file descriptor associated with the BitTube to the looper. If mDead is
-        // set to true or there are no more sensors for this connection, the file descriptor is
-        // removed if it has been previously added to the Looper. Depending on the state of the
-        // connection FD may be added to the Looper. The flags to set are determined by the internal
-        // state of the connection. FDs are added to the looper when wake-up sensors are registered
-        // (to poll for acknowledgements) and when write fails on the socket when there are too many
-        // error and the other end hangs up or when this client unregisters for this connection.
-        void updateLooperRegistration(const sp<Looper>& looper);
-        void updateLooperRegistrationLocked(const sp<Looper>& looper);
-
-        sp<SensorService> const mService;
-        sp<BitTube> mChannel;
-        uid_t mUid;
-        mutable Mutex mConnectionLock;
-        // Number of events from wake up sensors which are still pending and haven't been delivered
-        // to the corresponding application. It is incremented by one unit for each write to the
-        // socket.
-        uint32_t mWakeLockRefCount;
-
-        // If this flag is set to true, it means that the file descriptor associated with the
-        // BitTube has been added to the Looper in SensorService. This flag is typically set when
-        // this connection has wake-up sensors associated with it or when write has failed on this
-        // connection and we're storing some events in the cache.
-        bool mHasLooperCallbacks;
-        // If there are any errors associated with the Looper this flag is set to true and
-        // mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if
-        // this flag is set.
-        bool mDead;
-
-        bool mDataInjectionMode;
-        struct FlushInfo {
-            // The number of flush complete events dropped for this sensor is stored here.
-            // They are sent separately before the next batch of events.
-            int mPendingFlushEventsToSend;
-            // 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) {}
-        };
-        // protected by SensorService::mLock. Key for this vector is the sensor handle.
-        KeyedVector<int, FlushInfo> mSensorInfo;
-        sensors_event_t *mEventCache;
-        int mCacheSize, mMaxCacheSize;
-        String8 mPackageName;
-        const String16 mOpPackageName;
-#if DEBUG_CONNECTIONS
-        int mEventsReceived, mEventsSent, mEventsSentFromCache;
-        int mTotalAcksNeeded, mTotalAcksReceived;
-#endif
-
-    public:
-        SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
-                 bool isDataInjectionMode, const String16& opPackageName);
-
-        status_t sendEvents(sensors_event_t const* buffer, size_t count,
-                sensors_event_t* scratch,
-                SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
-        bool hasSensor(int32_t handle) const;
-        bool hasAnySensor() const;
-        bool hasOneShotSensors() const;
-        bool addSensor(int32_t handle);
-        bool removeSensor(int32_t handle);
-        void setFirstFlushPending(int32_t handle, bool value);
-        void dump(String8& result);
-        bool needsWakeLock();
-        void resetWakeLockRefCount();
-        String8 getPackageName() const;
-
-        uid_t getUid() const { return mUid; }
-    };
-
-    class SensorRecord {
-        SortedVector< wp<SensorEventConnection> > mConnections;
-        // A queue of all flush() calls made on this sensor. Flush complete events will be
-        // sent in this order.
-        Vector< wp<SensorEventConnection> > mPendingFlushConnections;
-    public:
-        SensorRecord(const sp<SensorEventConnection>& connection);
-        bool addConnection(const sp<SensorEventConnection>& connection);
-        bool removeConnection(const wp<SensorEventConnection>& connection);
-        size_t getNumConnections() const { return mConnections.size(); }
-
-        void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
-        void removeFirstPendingFlushConnection();
-        SensorEventConnection * getFirstPendingFlushConnection();
-        void clearAllPendingFlushConnections();
-    };
-
-    class SensorEventAckReceiver : public Thread {
-        sp<SensorService> const mService;
-    public:
-        virtual bool threadLoop();
-        SensorEventAckReceiver(const sp<SensorService>& service): mService(service) {}
-    };
-
-    // sensor_event_t with only the data and the timestamp.
-    struct TrimmedSensorEvent {
-        union {
-            float *mData;
-            uint64_t mStepCounter;
-        };
-        // Timestamp from the sensor_event.
-        int64_t mTimestamp;
-        // HH:MM:SS local time at which this sensor event is read at SensorService. Useful
-        // for debugging.
-        int32_t mHour, mMin, mSec;
-
-        TrimmedSensorEvent(int sensorType);
-        static bool isSentinel(const TrimmedSensorEvent& event);
-
-        ~TrimmedSensorEvent() {
-            delete [] mData;
-        }
-    };
-
-    // A circular buffer of TrimmedSensorEvents. The size of this buffer is typically 10. The
-    // last N events generated from the sensor are stored in this buffer. The buffer is NOT
-    // cleared when the sensor unregisters and as a result one may see very old data in the
-    // dumpsys output but this is WAI.
-    class CircularBuffer {
-        int mNextInd;
-        int mSensorType;
-        int mBufSize;
-        TrimmedSensorEvent ** mTrimmedSensorEventArr;
-    public:
-        CircularBuffer(int sensor_event_type);
-        void addEvent(const sensors_event_t& sensor_event);
-        void printBuffer(String8& buffer) const;
-        bool populateLastEvent(sensors_event_t *event);
-        ~CircularBuffer();
-    };
-
-    struct SensorRegistrationInfo {
-        int32_t mSensorHandle;
-        String8 mPackageName;
-        bool mActivated;
-        int32_t mSamplingRateUs;
-        int32_t mMaxReportLatencyUs;
-        int32_t mHour, mMin, mSec;
-
-        SensorRegistrationInfo() : mPackageName() {
-            mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
-            mHour = mMin = mSec = INT32_MIN;
-            mActivated = false;
-        }
-
-        static bool isSentinel(const SensorRegistrationInfo& info) {
-           return (info.mHour == INT32_MIN && info.mMin == INT32_MIN && info.mSec == INT32_MIN);
-        }
-    };
 
     static int getNumEventsForSensorType(int sensor_event_type);
     String8 getSensorName(int handle) const;
@@ -338,10 +165,8 @@ class SensorService :
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
     Sensor registerSensor(SensorInterface* sensor);
     Sensor registerVirtualSensor(SensorInterface* sensor);
-    status_t cleanupWithoutDisable(
-            const sp<SensorEventConnection>& connection, int handle);
-    status_t cleanupWithoutDisableLocked(
-            const sp<SensorEventConnection>& connection, int handle);
+    status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
+    status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
     void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
             sensors_event_t const* buffer, const int count);
     static bool canAccessSensor(const Sensor& sensor, const char* operation,
@@ -363,8 +188,8 @@ class SensorService :
     // wake_up sensors.
     void resetAllWakeLockRefCounts();
 
-    // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to
-    // seconds and wake the looper.
+    // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to 5
+    // seconds and wake the looper.
     void setWakeLockAcquiredLocked(bool acquire);
 
     // Send events from the event cache for this particular connection.
@@ -372,7 +197,7 @@ class SensorService :
 
     // Promote all weak referecences in mActiveConnections vector to strong references and add them
     // to the output vector.
-    void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections);
+    void populateActiveConnections( SortedVector< sp<SensorEventConnection> >* activeConnections);
 
     // If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
     // allowed to register for or call flush on sensors. Typically only cts test packages are
@@ -390,11 +215,10 @@ class SensorService :
     DefaultKeyedVector<int, SensorInterface*> mSensorMap;
     Vector<SensorInterface *> mVirtualSensorList;
     status_t mInitCheck;
+
     // Socket buffersize used to initialize BitTube. This size depends on whether batching is
     // supported or not.
-    uint32_t mSocketBufferSize;
-    sp<Looper> mLooper;
-    sp<SensorEventAckReceiver> mAckReceiver;
+    uint32_t mSocketBufferSize; sp<Looper> mLooper; sp<SensorEventAckReceiver> mAckReceiver;
 
     // protected by mLock
     mutable Mutex mLock;
@@ -405,6 +229,7 @@ class SensorService :
     sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
     SensorEventConnection const **mMapFlushEventsToConnections;
     Mode mCurrentOperatingMode;
+
     // This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
     // applications with this packageName are allowed to activate/deactivate or call flush on
     // sensors. To run CTS this is can be set to ".cts." and only CTS tests will get access to
@@ -412,23 +237,11 @@ class SensorService :
     String8 mWhiteListedPackage;
 
     // The size of this vector is constant, only the items are mutable
-    KeyedVector<int32_t, CircularBuffer *> mLastEventSeen;
+    KeyedVector<int32_t, MostRecentEventLogger *> mLastEventSeen;
 
     int mNextSensorRegIndex;
     Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
-public:
-    void cleanupConnection(SensorEventConnection* connection);
-    status_t enable(const sp<SensorEventConnection>& connection, int handle,
-                    nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags,
-                    const String16& opPackageName);
-    status_t disable(const sp<SensorEventConnection>& connection, int handle);
-    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns,
-                          const String16& opPackageName);
-    status_t flushSensor(const sp<SensorEventConnection>& connection,
-                         const String16& opPackageName);
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
-
+} // namespace android
 #endif // ANDROID_SENSOR_SERVICE_H