SensorDevice.cpp \
SensorFusion.cpp \
SensorInterface.cpp \
- SensorService.cpp
+ SensorService.cpp \
+ SensorEventConnection.cpp \
+ MostRecentEventLogger.cpp \
+ SensorRecord.cpp \
+
LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
+
+
* 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 {
// ---------------------------------------------------------------------------
{
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 {
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 {
{
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());
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,
}
}
- // 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) {
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]);
}
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));
}
}
-// ---------------------------------------------------------------------------
-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
#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 {
// ---------------------------------------------------------------------------
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
// 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.
// 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;
// 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;
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,
// wake_up sensors.
void resetAllWakeLockRefCounts();
- // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to
- // 5 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.
// 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
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;
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
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