SensorService fixes

1) Limit maxEventsToWrite depending on the size of the socket
     buffer allocated (Fix for write failure on manta).
     2) Do not call flush() if the sensor is not activated (OEM issue).

Change-Id: I81ea78dbdef3a3773af505ca1c9a5e39492c0b48
This commit is contained in:
Aravind Akella 2014-08-22 16:11:10 -07:00
parent b1bbfc2d02
commit 5466c3d20d
2 changed files with 42 additions and 21 deletions

View File

@ -150,14 +150,33 @@ void SensorService::onFirstRef()
// debugging sensor list // debugging sensor list
mUserSensorListDebug = mSensorList; mUserSensorListDebug = mSensorList;
mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED; // Check if the device really supports batching by looking at the FIFO event
// counts for each sensor.
bool batchingSupported = false;
for (int i = 0; i < mSensorList.size(); ++i) {
if (mSensorList[i].getFifoMaxEventCount() > 0) {
batchingSupported = true;
break;
}
}
if (batchingSupported) {
// Increase socket buffer size to a max of 100 KB for batching capabilities.
mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
} else {
mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
}
// Compare the socketBufferSize value against the system limits and limit
// it to maxSystemSocketBufferSize if necessary.
FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r"); FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
char line[128]; char line[128];
if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) { if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
line[sizeof(line) - 1] = '\0'; line[sizeof(line) - 1] = '\0';
sscanf(line, "%zu", &mSocketBufferSize); size_t maxSystemSocketBufferSize;
if (mSocketBufferSize > MAX_SOCKET_BUFFER_SIZE_BATCHED) { sscanf(line, "%zu", &maxSystemSocketBufferSize);
mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED; if (mSocketBufferSize > maxSystemSocketBufferSize) {
mSocketBufferSize = maxSystemSocketBufferSize;
} }
} }
if (fp) { if (fp) {
@ -310,7 +329,7 @@ status_t SensorService::dump(int fd, const Vector<String16>& /*args*/)
mActiveSensors.valueAt(i)->getNumConnections()); mActiveSensors.valueAt(i)->getNumConnections());
} }
result.appendFormat("Max Socket Buffer size = %d events\n", result.appendFormat("Socket Buffer size = %d events\n",
mSocketBufferSize/sizeof(sensors_event_t)); mSocketBufferSize/sizeof(sensors_event_t));
result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held"); result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" : "not held");
result.appendFormat("%zd active connections\n", mActiveConnections.size()); result.appendFormat("%zd active connections\n", mActiveConnections.size());
@ -687,13 +706,18 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection,
status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs, status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs,
maxBatchReportLatencyNs); maxBatchReportLatencyNs);
if (err == NO_ERROR && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT) { // Call flush() before calling activate() on the sensor. Wait for a first flush complete
// event before sending events on this connection. Ignore one-shot sensors which don't
// support flush(). Also if this sensor isn't already active, don't call flush().
if (err == NO_ERROR && sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT &&
rec->getNumConnections() > 1) {
connection->setFirstFlushPending(handle, true);
status_t err_flush = sensor->flush(connection.get(), handle); status_t err_flush = sensor->flush(connection.get(), handle);
// Flush may return error if the sensor is not activated or the underlying h/w sensor does // Flush may return error if the underlying h/w sensor uses an older HAL.
// not support flush.
if (err_flush == NO_ERROR) { if (err_flush == NO_ERROR) {
connection->setFirstFlushPending(handle, true);
rec->addPendingFlushConnection(connection.get()); rec->addPendingFlushConnection(connection.get());
} else {
connection->setFirstFlushPending(handle, false);
} }
} }
@ -808,7 +832,6 @@ status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection,
return ret; return ret;
} }
bool SensorService::canAccessSensor(const Sensor& sensor) { bool SensorService::canAccessSensor(const Sensor& sensor) {
return (sensor.getRequiredPermission().isEmpty()) || return (sensor.getRequiredPermission().isEmpty()) ||
PermissionCache::checkCallingPermission(String16(sensor.getRequiredPermission())); PermissionCache::checkCallingPermission(String16(sensor.getRequiredPermission()));
@ -916,12 +939,7 @@ SensorService::SensorEventConnection::SensorEventConnection(
: mService(service), mUid(uid), mWakeLockRefCount(0), mEventCache(NULL), mCacheSize(0), : mService(service), mUid(uid), mWakeLockRefCount(0), mEventCache(NULL), mCacheSize(0),
mMaxCacheSize(0) { mMaxCacheSize(0) {
const SensorDevice& device(SensorDevice::getInstance()); const SensorDevice& device(SensorDevice::getInstance());
if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) { mChannel = new BitTube(mService->mSocketBufferSize);
// Increase socket buffer size to a max of 100 KB for batching capabilities.
mChannel = new BitTube(mService->mSocketBufferSize);
} else {
mChannel = new BitTube(SOCKET_BUFFER_SIZE_NON_BATCHED);
}
#if DEBUG_CONNECTIONS #if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0; mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
mTotalAcksNeeded = mTotalAcksReceived = 0; mTotalAcksNeeded = mTotalAcksReceived = 0;
@ -1211,13 +1229,14 @@ void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
} }
void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() { void SensorService::SensorEventConnection::writeToSocketFromCacheLocked() {
// At a time write at most half the size of the receiver buffer in SensorEventQueue. // At a time write at most half the size of the receiver buffer in SensorEventQueue OR
const int maxWriteSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2; // 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)));
// Send pending flush complete events (if any)
sendPendingFlushEventsLocked(); sendPendingFlushEventsLocked();
// Write "count" events at a time.
for (int numEventsSent = 0; numEventsSent < mCacheSize;) { for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
const int numEventsToWrite = (mCacheSize - numEventsSent) < maxWriteSize ? const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize);
mCacheSize - numEventsSent : maxWriteSize;
int index_wake_up_event = int index_wake_up_event =
findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite); findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
if (index_wake_up_event >= 0) { if (index_wake_up_event >= 0) {

View File

@ -218,6 +218,8 @@ class SensorService :
DefaultKeyedVector<int, SensorInterface*> mSensorMap; DefaultKeyedVector<int, SensorInterface*> mSensorMap;
Vector<SensorInterface *> mVirtualSensorList; Vector<SensorInterface *> mVirtualSensorList;
status_t mInitCheck; status_t mInitCheck;
// Socket buffersize used to initialize BitTube. This size depends on whether batching is
// supported or not.
size_t mSocketBufferSize; size_t mSocketBufferSize;
sp<Looper> mLooper; sp<Looper> mLooper;