SensorService fixes

i) Significant Motion multiple clients fix. Make a copy of
  mActiveConnections vector before cleaning up SensorEventConnections
  when one-shot sensors trigger.
  ii) Maintain a mapping between flush_complete_events and
  SensorEventConnections to accurately map flush() API calls and
  corresponding flush_complete_events
  iii) Remove all references to 1_1 and 1_2 HALs.
  iv) Dynamically allocate sensor_event buffers in SensorService main
  threadLoop.

Bug: 17412359
Change-Id: If3c3986197660cafef2d2e0b4dc7582e229cf1c4
This commit is contained in:
Aravind Akella 2014-09-08 15:45:47 -07:00
parent 9e691c1093
commit 8493b79e1c
4 changed files with 88 additions and 67 deletions

View File

@ -27,7 +27,7 @@
#include <gui/BitTube.h>
// ----------------------------------------------------------------------------
#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 30)
#define WAKE_UP_SENSOR_EVENT_NEEDS_ACK (1U << 31)
struct ALooper;
struct ASensorEvent;

View File

@ -56,7 +56,7 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
// Set fifo event count zero for older devices which do not support batching. Fused
// sensors also have their fifo counts set to zero.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
mFifoReservedEventCount = hwSensor->fifoReservedEventCount;
mFifoMaxEventCount = hwSensor->fifoMaxEventCount;
} else {
@ -206,10 +206,10 @@ Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
break;
default:
// Only pipe the stringType, requiredPermission and flags for custom sensors.
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->stringType) {
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->stringType) {
mStringType = hwSensor->stringType;
}
if (halVersion >= SENSORS_DEVICE_API_VERSION_1_2 && hwSensor->requiredPermission) {
if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->requiredPermission) {
mRequiredPermission = hwSensor->requiredPermission;
}

View File

@ -186,6 +186,11 @@ void SensorService::onFirstRef()
mWakeLockAcquired = false;
run("SensorService", PRIORITY_URGENT_DISPLAY);
mLooper = new Looper(false);
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
mInitCheck = NO_ERROR;
}
}
@ -350,6 +355,9 @@ void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnecti
sensors_event_t const* buffer, const int count) {
for (int i=0 ; i<count ; i++) {
int handle = buffer[i].sensor;
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
handle = buffer[i].meta_data.sensor;
}
if (connection->hasSensor(handle)) {
SensorInterface* sensor = mSensorMap.valueFor(handle);
// If this buffer has an event from a one_shot sensor and this connection is registered
@ -373,25 +381,22 @@ bool SensorService::threadLoop()
const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
sensors_event_t buffer[minBufferSize];
sensors_event_t scratch[minBufferSize];
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
SensorEventAckReceiver sender(this);
sender.run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
ssize_t count;
const int halVersion = device.getHalDeviceVersion();
do {
count = device.poll(buffer, numEventMax);
if (count<0) {
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
if (count < 0) {
ALOGE("sensor poll failed (%s)", strerror(-count));
break;
}
// Reset sensors_event_t.flags to zero for all events in the buffer.
for (int i = 0; i < count; i++) {
buffer[i].flags = 0;
mSensorEventBuffer[i].flags = 0;
}
Mutex::Autolock _l(mLock);
// Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
@ -401,7 +406,7 @@ bool SensorService::threadLoop()
// releasing the wakelock.
bool bufferHasWakeUpEvent = false;
for (int i = 0; i < count; i++) {
if (isWakeUpSensorEvent(buffer[i])) {
if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {
bufferHasWakeUpEvent = true;
break;
}
@ -412,11 +417,11 @@ bool SensorService::threadLoop()
mWakeLockAcquired = true;
ALOGD_IF(DEBUG_CONNECTIONS, "acquired wakelock %s", WAKE_LOCK_NAME);
}
recordLastValueLocked(buffer, count);
recordLastValueLocked(mSensorEventBuffer, count);
// handle virtual sensors
if (count && vcount) {
sensors_event_t const * const event = buffer;
sensors_event_t const * const event = mSensorEventBuffer;
const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
if (activeVirtualSensorCount) {
size_t k = 0;
@ -437,17 +442,17 @@ bool SensorService::threadLoop()
sensors_event_t out;
SensorInterface* si = mActiveVirtualSensors.valueAt(j);
if (si->process(&out, event[i])) {
buffer[count + k] = out;
mSensorEventBuffer[count + k] = out;
k++;
}
}
}
if (k) {
// record the last synthesized values
recordLastValueLocked(&buffer[count], k);
recordLastValueLocked(&mSensorEventBuffer[count], k);
count += k;
// sort the buffer by time-stamps
sortEventBuffer(buffer, count);
sortEventBuffer(mSensorEventBuffer, count);
}
}
}
@ -455,10 +460,26 @@ bool SensorService::threadLoop()
// handle backward compatibility for RotationVector sensor
if (halVersion < SENSORS_DEVICE_API_VERSION_1_0) {
for (int i = 0; i < count; i++) {
if (buffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {
if (mSensorEventBuffer[i].type == SENSOR_TYPE_ROTATION_VECTOR) {
// All the 4 components of the quaternion should be available
// No heading accuracy. Set it to -1
buffer[i].data[4] = -1;
mSensorEventBuffer[i].data[4] = -1;
}
}
}
// 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 int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);
if (rec != NULL) {
mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();
rec->removeFirstPendingFlushConnection();
}
}
}
@ -466,13 +487,22 @@ bool SensorService::threadLoop()
// Send our events to clients. Check the state of wake lock for each client and release the
// lock if none of the clients need it.
bool needsWakeLock = false;
for (size_t i=0 ; i < mActiveConnections.size(); i++) {
sp<SensorEventConnection> connection(mActiveConnections[i].promote());
// 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).
const SortedVector< wp<SensorEventConnection> > activeConnections(mActiveConnections);
size_t numConnections = activeConnections.size();
for (size_t i=0 ; i < numConnections; ++i) {
sp<SensorEventConnection> connection(activeConnections[i].promote());
if (connection != 0) {
connection->sendEvents(buffer, count, scratch);
connection->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,
mMapFlushEventsToConnections);
needsWakeLock |= connection->needsWakeLock();
// Some sensors need to be auto disabled after the trigger
cleanupAutoDisabledSensorLocked(connection, buffer, count);
// If the connection has one-shot sensors, it may be cleaned up after first trigger.
// Early check for one-shot sensors.
if (connection->hasOneShotSensors()) {
cleanupAutoDisabledSensorLocked(connection, mSensorEventBuffer, count);
}
}
}
@ -481,7 +511,7 @@ bool SensorService::threadLoop()
mWakeLockAcquired = false;
ALOGD_IF(DEBUG_CONNECTIONS, "released wakelock %s", WAKE_LOCK_NAME);
}
} while (count >= 0 || Thread::exitPending());
} while (!Thread::exitPending());
ALOGW("Exiting SensorService::threadLoop => aborting...");
abort();
@ -823,7 +853,7 @@ status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection)
continue;
}
SensorEventConnection::FlushInfo& flushInfo = connection->mSensorInfo.editValueFor(handle);
if (halVersion < SENSORS_DEVICE_API_VERSION_1_1 || isVirtualSensor(handle)) {
if (halVersion <= SENSORS_DEVICE_API_VERSION_1_0 || isVirtualSensor(handle)) {
// For older devices just increment pending flush count which will send a trivial
// flush complete event.
flushInfo.mPendingFlushEventsToSend++;
@ -1030,6 +1060,17 @@ bool SensorService::SensorEventConnection::hasAnySensor() const {
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;
}
void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
bool value) {
Mutex::Autolock _l(mConnectionLock);
@ -1042,19 +1083,14 @@ void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t* buffer, size_t numEvents,
sensors_event_t* scratch) {
sensors_event_t* scratch,
SensorEventConnection const * const * mapFlushEventsToConnections) {
// filter out events not for this connection
size_t count = 0;
Mutex::Autolock _l(mConnectionLock);
if (scratch) {
size_t i=0;
while (i<numEvents) {
// Flush complete events can be invalidated. If this event has been invalidated
// before, ignore and proceed to the next event.
if (buffer[i].flags & SENSOR_EVENT_INVALID_FLAG) {
++i;
continue;
}
int32_t sensor_handle = buffer[i].sensor;
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
@ -1073,20 +1109,14 @@ status_t SensorService::SensorEventConnection::sendEvents(
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) {
SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
if (rec && rec->getFirstPendingFlushConnection() == this) {
rec->removeFirstPendingFlushConnection();
if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
this == mapFlushEventsToConnections[i]) {
flushInfo.mFirstFlushPending = false;
// Invalidate this flush_complete_event so that it cannot be used by other
// connections.
buffer[i].flags |= SENSOR_EVENT_INVALID_FLAG;
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.
@ -1096,27 +1126,21 @@ status_t SensorService::SensorEventConnection::sendEvents(
}
do {
if (buffer[i].flags & SENSOR_EVENT_INVALID_FLAG) {
++i;
continue;
}
// 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) {
// Check if this connection has called flush() on this sensor. Only if
// a flush() has been explicitly called, send a flush_complete_event.
SensorService::SensorRecord *rec = mService->getSensorRecord(sensor_handle);
if (rec && rec->getFirstPendingFlushConnection() == this) {
rec->removeFirstPendingFlushConnection();
if (this == mapFlushEventsToConnections[i]) {
scratch[count++] = buffer[i];
// Invalidate this flush_complete_event so that it cannot be used by
// other connections.
buffer[i].flags |= SENSOR_EVENT_INVALID_FLAG;
}
++i;
} else {
// Regular sensor event, just copy it to the scratch buffer.
scratch[count++] = buffer[i++];
}
} while ((i<numEvents) && ((buffer[i].sensor == sensor_handle) ||
} 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)));
}

View File

@ -45,14 +45,6 @@
// For older HALs which don't support batching, use a smaller socket buffer size.
#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
// Flags for sensors_event_t.flag. Using only the most significant two bits for flags.
// MSB is to invalidate a sensor_event (typically a flush_complete_event) so that
// it won't be used by other connections.
// MSB 2nd bit is used to indicate whether the event needs to be acknowledged or not.
// This is typically used for WAKE_UP sensors. WAKE_UP_SENSOR_EVENT_NEEDS_ACK is defined
// in SensorEveneQueue.h
#define SENSOR_EVENT_INVALID_FLAG (1U << 31)
struct sensors_poll_device_t;
struct sensors_module_t;
@ -157,9 +149,11 @@ class SensorService :
SensorEventConnection(const sp<SensorService>& service, uid_t uid);
status_t sendEvents(sensors_event_t* buffer, size_t count,
sensors_event_t* scratch);
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);
@ -237,6 +231,9 @@ class SensorService :
DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
SortedVector< wp<SensorEventConnection> > mActiveConnections;
bool mWakeLockAcquired;
sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
SensorEventConnection const **mMapFlushEventsToConnections;
// The size of this vector is constant, only the items are mutable
KeyedVector<int32_t, sensors_event_t> mLastEventSeen;