summaryrefslogtreecommitdiffstats
path: root/services/sensorservice/SensorDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/sensorservice/SensorDevice.cpp')
-rw-r--r--services/sensorservice/SensorDevice.cpp268
1 files changed, 203 insertions, 65 deletions
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 2fa5dbd..19caa5c 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -47,7 +47,7 @@ SensorDevice::SensorDevice()
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if (mSensorModule) {
- err = sensors_open(&mSensorModule->common, &mSensorDevice);
+ err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
ALOGE_IF(err, "couldn't open device for module %s (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
@@ -59,7 +59,9 @@ SensorDevice::SensorDevice()
Info model;
for (size_t i=0 ; i<size_t(count) ; i++) {
mActivationCount.add(list[i].handle, model);
- mSensorDevice->activate(mSensorDevice, list[i].handle, 0);
+ mSensorDevice->activate(
+ reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
+ list[i].handle, 0);
}
}
}
@@ -76,15 +78,23 @@ void SensorDevice::dump(String8& result)
Mutex::Autolock _l(mLock);
for (size_t i=0 ; i<size_t(count) ; i++) {
const Info& info = mActivationCount.valueFor(list[i].handle);
- result.appendFormat("handle=0x%08x, active-count=%d, rates(ms)={ ",
- list[i].handle,
- info.rates.size());
- for (size_t j=0 ; j<info.rates.size() ; j++) {
- result.appendFormat("%4.1f%s",
- info.rates.valueAt(j) / 1e6f,
- j<info.rates.size()-1 ? ", " : "");
+ result.appendFormat("handle=0x%08x, active-count=%d, batch_period(ms)={ ", list[i].handle,
+ info.batchParams.size());
+ for (size_t j = 0; j < info.batchParams.size(); j++) {
+ BatchParams params = info.batchParams.valueAt(j);
+ result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
+ j < info.batchParams.size() - 1 ? ", " : "");
}
- result.appendFormat(" }, selected=%4.1f ms\n", info.delay / 1e6f);
+ result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchDelay / 1e6f);
+
+ result.appendFormat("handle=0x%08x, active-count=%d, batch_timeout(ms)={ ", list[i].handle,
+ info.batchParams.size());
+ for (size_t j = 0; j < info.batchParams.size(); j++) {
+ BatchParams params = info.batchParams.valueAt(j);
+ result.appendFormat("%4.1f%s", params.batchTimeout / 1e6f,
+ j < info.batchParams.size() - 1 ? ", " : "");
+ }
+ result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
}
}
@@ -102,7 +112,8 @@ ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
if (!mSensorDevice) return NO_INIT;
ssize_t c;
do {
- c = mSensorDevice->poll(mSensorDevice, buffer, count);
+ c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice),
+ buffer, count);
} while (c == -EINTR);
return c;
}
@@ -110,7 +121,7 @@ ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) {
void SensorDevice::autoDisable(void *ident, int handle) {
Info& info( mActivationCount.editValueFor(handle) );
Mutex::Autolock _l(mLock);
- info.rates.removeItem(ident);
+ info.removeBatchParamsForIdent(ident);
}
status_t SensorDevice::activate(void* ident, int handle, int enabled)
@@ -119,35 +130,46 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled)
status_t err(NO_ERROR);
bool actuateHardware = false;
+ Mutex::Autolock _l(mLock);
Info& info( mActivationCount.editValueFor(handle) );
-
ALOGD_IF(DEBUG_CONNECTIONS,
- "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
- ident, handle, enabled, info.rates.size());
+ "SensorDevice::activate: ident=%p, handle=0x%08x, enabled=%d, count=%d",
+ ident, handle, enabled, info.batchParams.size());
if (enabled) {
- Mutex::Autolock _l(mLock);
- ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
- info.rates.indexOfKey(ident));
+ ALOGD_IF(DEBUG_CONNECTIONS, "enable index=%d", info.batchParams.indexOfKey(ident));
- if (info.rates.indexOfKey(ident) < 0) {
- info.rates.add(ident, DEFAULT_EVENTS_PERIOD);
- if (info.rates.size() == 1) {
- actuateHardware = true;
- }
+ if (info.batchParams.indexOfKey(ident) >= 0) {
+ if (info.batchParams.size() == 1) {
+ // This is the first connection, we need to activate the underlying h/w sensor.
+ actuateHardware = true;
+ }
} else {
- // sensor was already activated for this ident
+ // Log error. Every activate call should be preceded by a batch() call.
+ ALOGE("\t >>>ERROR: activate called without batch");
}
} else {
- Mutex::Autolock _l(mLock);
- ALOGD_IF(DEBUG_CONNECTIONS, "... index=%ld",
- info.rates.indexOfKey(ident));
+ ALOGD_IF(DEBUG_CONNECTIONS, "disable index=%d", info.batchParams.indexOfKey(ident));
- ssize_t idx = info.rates.removeItem(ident);
- if (idx >= 0) {
- if (info.rates.size() == 0) {
+ if (info.removeBatchParamsForIdent(ident) >= 0) {
+ if (info.batchParams.size() == 0) {
+ // This is the last connection, we need to de-activate the underlying h/w sensor.
actuateHardware = true;
+ } else {
+ const int halVersion = getHalDeviceVersion();
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
+ // Call batch for this sensor with the previously calculated best effort
+ // batch_rate and timeout. One of the apps has unregistered for sensor
+ // events, and the best effort batch parameters might have changed.
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "\t>>> actuating h/w batch %d %d %lld %lld ", handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ mSensorDevice->batch(mSensorDevice, handle,info.bestBatchParams.flags,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ }
}
} else {
// sensor wasn't enabled for this ident
@@ -155,41 +177,130 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled)
}
if (actuateHardware) {
- ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w");
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w activate handle=%d enabled=%d", handle, enabled);
+ err = mSensorDevice->activate(
+ reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), handle, enabled);
+ ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle,
+ strerror(-err));
+
+ if (err != NO_ERROR && enabled) {
+ // Failure when enabling the sensor. Clean up on failure.
+ info.removeBatchParamsForIdent(ident);
+ }
+ }
- err = mSensorDevice->activate(mSensorDevice, handle, enabled);
- ALOGE_IF(err, "Error %s sensor %d (%s)",
- enabled ? "activating" : "disabling",
- handle, strerror(-err));
+ // On older devices which do not support batch, call setDelay().
+ if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1 && info.batchParams.size() > 0) {
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w setDelay %d %lld ", handle,
+ info.bestBatchParams.batchDelay);
+ mSensorDevice->setDelay(
+ reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
+ handle, info.bestBatchParams.batchDelay);
+ }
+ return err;
+}
- if (err != NO_ERROR) {
- // clean-up on failure
- if (enabled) {
- // failure when enabling the sensor
- Mutex::Autolock _l(mLock);
- info.rates.removeItem(ident);
+status_t SensorDevice::batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs) {
+ if (!mSensorDevice) return NO_INIT;
+
+ if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
+ samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
+ }
+
+ const int halVersion = getHalDeviceVersion();
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
+ if (flags & SENSORS_BATCH_DRY_RUN) {
+ return mSensorDevice->batch(mSensorDevice, handle, flags, samplingPeriodNs,
+ maxBatchReportLatencyNs);
+ } else {
+ // Call h/w with dry run to see if the given parameters are feasible or not. Return if
+ // there is an error.
+ status_t errDryRun(NO_ERROR);
+ errDryRun = mSensorDevice->batch(mSensorDevice, handle, flags | SENSORS_BATCH_DRY_RUN,
+ samplingPeriodNs, maxBatchReportLatencyNs);
+ if (errDryRun != NO_ERROR) {
+ ALOGD_IF(DEBUG_CONNECTIONS, "SensorDevice::batch dry run error %s",
+ strerror(-errDryRun));
+ return errDryRun;
}
}
+ } else if (maxBatchReportLatencyNs != 0) {
+ // Batch is not supported on older devices.
+ return INVALID_OPERATION;
}
- { // scope for the lock
- Mutex::Autolock _l(mLock);
- nsecs_t ns = info.selectDelay();
- mSensorDevice->setDelay(mSensorDevice, handle, ns);
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "SensorDevice::batch: ident=%p, handle=0x%08x, flags=%d, period_ns=%lld timeout=%lld",
+ ident, handle, flags, samplingPeriodNs, maxBatchReportLatencyNs);
+
+ Mutex::Autolock _l(mLock);
+ Info& info(mActivationCount.editValueFor(handle));
+
+ if (info.batchParams.indexOfKey(ident) < 0) {
+ BatchParams params(flags, samplingPeriodNs, maxBatchReportLatencyNs);
+ info.batchParams.add(ident, params);
+ } else {
+ // A batch has already been called with this ident. Update the batch parameters.
+ info.setBatchParamsForIdent(ident, flags, samplingPeriodNs, maxBatchReportLatencyNs);
}
+ BatchParams prevBestBatchParams = info.bestBatchParams;
+ // Find the minimum of all timeouts and batch_rates for this sensor.
+ info.selectBatchParams();
+
+ ALOGD_IF(DEBUG_CONNECTIONS,
+ "\t>>> curr_period=%lld min_period=%lld curr_timeout=%lld min_timeout=%lld",
+ prevBestBatchParams.batchDelay, info.bestBatchParams.batchDelay,
+ prevBestBatchParams.batchTimeout, info.bestBatchParams.batchTimeout);
+
+ status_t err(NO_ERROR);
+ // If the min period or min timeout has changed since the last batch call, call batch.
+ if (prevBestBatchParams != info.bestBatchParams) {
+ if (halVersion >= SENSORS_DEVICE_API_VERSION_1_1) {
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w BATCH %d %d %lld %lld ", handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ err = mSensorDevice->batch(mSensorDevice, handle, info.bestBatchParams.flags,
+ info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout);
+ } else {
+ // For older devices which do not support batch, call setDelay() after activate() is
+ // called. Some older devices may not support calling setDelay before activate(), so
+ // call setDelay in SensorDevice::activate() method.
+ }
+ if (err != NO_ERROR) {
+ ALOGE("sensor batch failed %p %d %d %lld %lld err=%s", mSensorDevice, handle,
+ info.bestBatchParams.flags, info.bestBatchParams.batchDelay,
+ info.bestBatchParams.batchTimeout, strerror(-err));
+ info.removeBatchParamsForIdent(ident);
+ }
+ }
return err;
}
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
+status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
{
if (!mSensorDevice) return NO_INIT;
+ if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
+ samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
+ }
Mutex::Autolock _l(mLock);
Info& info( mActivationCount.editValueFor(handle) );
- status_t err = info.setDelayForIdent(ident, ns);
- if (err < 0) return err;
- ns = info.selectDelay();
- return mSensorDevice->setDelay(mSensorDevice, handle, ns);
+ // If the underlying sensor is NOT in continuous mode, setDelay() should return an error.
+ // Calling setDelay() in batch mode is an invalid operation.
+ if (info.bestBatchParams.batchTimeout != 0) {
+ return INVALID_OPERATION;
+ }
+ ssize_t index = info.batchParams.indexOfKey(ident);
+ if (index < 0) {
+ return BAD_INDEX;
+ }
+ BatchParams& params = info.batchParams.editValueAt(index);
+ params.batchDelay = samplingPeriodNs;
+ info.selectBatchParams();
+ return mSensorDevice->setDelay(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice),
+ handle, info.bestBatchParams.batchDelay);
}
int SensorDevice::getHalDeviceVersion() const {
@@ -198,31 +309,58 @@ int SensorDevice::getHalDeviceVersion() const {
return mSensorDevice->common.version;
}
+status_t SensorDevice::flush(void* ident, int handle) {
+ if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_1) {
+ return INVALID_OPERATION;
+ }
+ ALOGD_IF(DEBUG_CONNECTIONS, "\t>>> actuating h/w flush %d", handle);
+ return mSensorDevice->flush(mSensorDevice, handle);
+}
+
// ---------------------------------------------------------------------------
-status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
-{
- ssize_t index = rates.indexOfKey(ident);
+status_t SensorDevice::Info::setBatchParamsForIdent(void* ident, int flags,
+ int64_t samplingPeriodNs,
+ int64_t maxBatchReportLatencyNs) {
+ ssize_t index = batchParams.indexOfKey(ident);
if (index < 0) {
- ALOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)",
- ident, ns, strerror(-index));
+ ALOGE("Info::setBatchParamsForIdent(ident=%p, period_ns=%lld timeout=%lld) failed (%s)",
+ ident, samplingPeriodNs, maxBatchReportLatencyNs, strerror(-index));
return BAD_INDEX;
}
- rates.editValueAt(index) = ns;
+ BatchParams& params = batchParams.editValueAt(index);
+ params.flags = flags;
+ params.batchDelay = samplingPeriodNs;
+ params.batchTimeout = maxBatchReportLatencyNs;
return NO_ERROR;
}
-nsecs_t SensorDevice::Info::selectDelay()
-{
- nsecs_t ns = rates.valueAt(0);
- for (size_t i=1 ; i<rates.size() ; i++) {
- nsecs_t cur = rates.valueAt(i);
- if (cur < ns) {
- ns = cur;
+void SensorDevice::Info::selectBatchParams() {
+ BatchParams bestParams(-1, -1, -1);
+
+ if (batchParams.size() > 0) {
+ BatchParams params = batchParams.valueAt(0);
+ bestParams = params;
+ }
+
+ for (size_t i = 1; i < batchParams.size(); ++i) {
+ BatchParams params = batchParams.valueAt(i);
+ if (params.batchDelay < bestParams.batchDelay) {
+ bestParams.batchDelay = params.batchDelay;
+ }
+ if (params.batchTimeout < bestParams.batchTimeout) {
+ bestParams.batchTimeout = params.batchTimeout;
}
}
- delay = ns;
- return ns;
+ bestBatchParams = bestParams;
+}
+
+ssize_t SensorDevice::Info::removeBatchParamsForIdent(void* ident) {
+ ssize_t idx = batchParams.removeItem(ident);
+ if (idx >= 0) {
+ selectBatchParams();
+ }
+ return idx;
}
// ---------------------------------------------------------------------------