diff options
Diffstat (limited to 'services/sensorservice')
-rw-r--r-- | services/sensorservice/Android.mk | 25 | ||||
-rw-r--r-- | services/sensorservice/BatteryService.cpp | 2 | ||||
-rw-r--r-- | services/sensorservice/CorrectedGyroSensor.cpp | 10 | ||||
-rw-r--r-- | services/sensorservice/Fusion.cpp | 16 | ||||
-rw-r--r-- | services/sensorservice/GravitySensor.cpp | 6 | ||||
-rw-r--r-- | services/sensorservice/LinearAccelerationSensor.cpp | 6 | ||||
-rw-r--r-- | services/sensorservice/OrientationSensor.cpp | 9 | ||||
-rw-r--r-- | services/sensorservice/RotationVectorSensor.cpp | 12 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.cpp | 276 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.h | 54 | ||||
-rw-r--r-- | services/sensorservice/SensorFusion.cpp | 41 | ||||
-rw-r--r-- | services/sensorservice/SensorFusion.h | 7 | ||||
-rw-r--r-- | services/sensorservice/SensorInterface.cpp | 12 | ||||
-rw-r--r-- | services/sensorservice/SensorInterface.h | 17 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 398 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 52 | ||||
-rw-r--r-- | services/sensorservice/main_sensorservice.cpp | 25 |
17 files changed, 713 insertions, 255 deletions
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk index dd698c5..4f24ddc 100644 --- a/services/sensorservice/Android.mk +++ b/services/sensorservice/Android.mk @@ -12,11 +12,12 @@ LOCAL_SRC_FILES:= \ SensorDevice.cpp \ SensorFusion.cpp \ SensorInterface.cpp \ - SensorService.cpp \ - + SensorService.cpp LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\" +LOCAL_CFLAGS += -fvisibility=hidden + LOCAL_SHARED_LIBRARIES := \ libcutils \ libhardware \ @@ -27,8 +28,24 @@ LOCAL_SHARED_LIBRARIES := \ libui \ libgui - - LOCAL_MODULE:= libsensorservice include $(BUILD_SHARED_LIBRARY) + +##################################################################### +# build executable +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + main_sensorservice.cpp + +LOCAL_SHARED_LIBRARIES := \ + libsensorservice \ + libbinder \ + libutils + +LOCAL_MODULE_TAGS := optional + +LOCAL_MODULE:= sensorservice + +include $(BUILD_EXECUTABLE) diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp index 70b65ab..38dc749 100644 --- a/services/sensorservice/BatteryService.cpp +++ b/services/sensorservice/BatteryService.cpp @@ -33,7 +33,7 @@ namespace android { BatteryService::BatteryService() { const sp<IServiceManager> sm(defaultServiceManager()); if (sm != NULL) { - const String16 name("batteryinfo"); + const String16 name("batterystats"); mBatteryStatService = sm->getService(name); } } diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp index 1857443..31487a7 100644 --- a/services/sensorservice/CorrectedGyroSensor.cpp +++ b/services/sensorservice/CorrectedGyroSensor.cpp @@ -57,19 +57,19 @@ bool CorrectedGyroSensor::process(sensors_event_t* outEvent, } status_t CorrectedGyroSensor::activate(void* ident, bool enabled) { - mSensorDevice.activate(this, mGyro.getHandle(), enabled); - return mSensorFusion.activate(this, enabled); + mSensorDevice.activate(ident, mGyro.getHandle(), enabled); + return mSensorFusion.activate(ident, enabled); } status_t CorrectedGyroSensor::setDelay(void* ident, int handle, int64_t ns) { - mSensorDevice.setDelay(this, mGyro.getHandle(), ns); - return mSensorFusion.setDelay(this, ns); + mSensorDevice.setDelay(ident, mGyro.getHandle(), ns); + return mSensorFusion.setDelay(ident, ns); } Sensor CorrectedGyroSensor::getSensor() const { sensor_t hwSensor; hwSensor.name = "Corrected Gyroscope Sensor"; - hwSensor.vendor = "Google Inc."; + hwSensor.vendor = "AOSP"; hwSensor.version = 1; hwSensor.handle = '_cgy'; hwSensor.type = SENSOR_TYPE_GYROSCOPE; diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp index 93d6127..4f63c31 100644 --- a/services/sensorservice/Fusion.cpp +++ b/services/sensorservice/Fusion.cpp @@ -220,22 +220,6 @@ void Fusion::initFusion(const vec4_t& q, float dT) // initial covariance: Var{ x(t0) } // TODO: initialize P correctly P = 0; - - // it is unclear how to set the initial covariance. It does affect - // how quickly the fusion converges. Experimentally it would take - // about 10 seconds at 200 Hz to estimate the gyro-drift with an - // initial covariance of 0, and about a second with an initial covariance - // of about 1 deg/s. - const float covv = 0; - const float covu = 0.5f * (float(M_PI) / 180); - mat33_t& Pv = P[0][0]; - Pv[0][0] = covv; - Pv[1][1] = covv; - Pv[2][2] = covv; - mat33_t& Pu = P[1][1]; - Pu[0][0] = covu; - Pu[1][1] = covu; - Pu[2][2] = covu; } bool Fusion::hasEstimate() const { diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp index c57715f..dd1f650 100644 --- a/services/sensorservice/GravitySensor.cpp +++ b/services/sensorservice/GravitySensor.cpp @@ -67,17 +67,17 @@ bool GravitySensor::process(sensors_event_t* outEvent, } status_t GravitySensor::activate(void* ident, bool enabled) { - return mSensorFusion.activate(this, enabled); + return mSensorFusion.activate(ident, enabled); } status_t GravitySensor::setDelay(void* ident, int handle, int64_t ns) { - return mSensorFusion.setDelay(this, ns); + return mSensorFusion.setDelay(ident, ns); } Sensor GravitySensor::getSensor() const { sensor_t hwSensor; hwSensor.name = "Gravity Sensor"; - hwSensor.vendor = "Google Inc."; + hwSensor.vendor = "AOSP"; hwSensor.version = 3; hwSensor.handle = '_grv'; hwSensor.type = SENSOR_TYPE_GRAVITY; diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp index f0054f2..d5f20d2 100644 --- a/services/sensorservice/LinearAccelerationSensor.cpp +++ b/services/sensorservice/LinearAccelerationSensor.cpp @@ -51,18 +51,18 @@ bool LinearAccelerationSensor::process(sensors_event_t* outEvent, } status_t LinearAccelerationSensor::activate(void* ident, bool enabled) { - return mGravitySensor.activate(this, enabled); + return mGravitySensor.activate(ident, enabled); } status_t LinearAccelerationSensor::setDelay(void* ident, int handle, int64_t ns) { - return mGravitySensor.setDelay(this, handle, ns); + return mGravitySensor.setDelay(ident, handle, ns); } Sensor LinearAccelerationSensor::getSensor() const { Sensor gsensor(mGravitySensor.getSensor()); sensor_t hwSensor; hwSensor.name = "Linear Acceleration Sensor"; - hwSensor.vendor = "Google Inc."; + hwSensor.vendor = "AOSP"; hwSensor.version = gsensor.getVersion(); hwSensor.handle = '_lin'; hwSensor.type = SENSOR_TYPE_LINEAR_ACCELERATION; diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp index 037adaa..10b391c 100644 --- a/services/sensorservice/OrientationSensor.cpp +++ b/services/sensorservice/OrientationSensor.cpp @@ -33,6 +33,9 @@ OrientationSensor::OrientationSensor() : mSensorDevice(SensorDevice::getInstance()), mSensorFusion(SensorFusion::getInstance()) { + // FIXME: instead of using the SensorFusion code, we should use + // the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the + // HAL's implementation. } bool OrientationSensor::process(sensors_event_t* outEvent, @@ -63,17 +66,17 @@ bool OrientationSensor::process(sensors_event_t* outEvent, } status_t OrientationSensor::activate(void* ident, bool enabled) { - return mSensorFusion.activate(this, enabled); + return mSensorFusion.activate(ident, enabled); } status_t OrientationSensor::setDelay(void* ident, int handle, int64_t ns) { - return mSensorFusion.setDelay(this, ns); + return mSensorFusion.setDelay(ident, ns); } Sensor OrientationSensor::getSensor() const { sensor_t hwSensor; hwSensor.name = "Orientation Sensor"; - hwSensor.vendor = "Google Inc."; + hwSensor.vendor = "AOSP"; hwSensor.version = 1; hwSensor.handle = '_ypr'; hwSensor.type = SENSOR_TYPE_ORIENTATION; diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp index 5ea9568..a2157b4 100644 --- a/services/sensorservice/RotationVectorSensor.cpp +++ b/services/sensorservice/RotationVectorSensor.cpp @@ -53,17 +53,17 @@ bool RotationVectorSensor::process(sensors_event_t* outEvent, } status_t RotationVectorSensor::activate(void* ident, bool enabled) { - return mSensorFusion.activate(this, enabled); + return mSensorFusion.activate(ident, enabled); } status_t RotationVectorSensor::setDelay(void* ident, int handle, int64_t ns) { - return mSensorFusion.setDelay(this, ns); + return mSensorFusion.setDelay(ident, ns); } Sensor RotationVectorSensor::getSensor() const { sensor_t hwSensor; hwSensor.name = "Rotation Vector Sensor"; - hwSensor.vendor = "Google Inc."; + hwSensor.vendor = "AOSP"; hwSensor.version = 3; hwSensor.handle = '_rov'; hwSensor.type = SENSOR_TYPE_ROTATION_VECTOR; @@ -102,17 +102,17 @@ bool GyroDriftSensor::process(sensors_event_t* outEvent, } status_t GyroDriftSensor::activate(void* ident, bool enabled) { - return mSensorFusion.activate(this, enabled); + return mSensorFusion.activate(ident, enabled); } status_t GyroDriftSensor::setDelay(void* ident, int handle, int64_t ns) { - return mSensorFusion.setDelay(this, ns); + return mSensorFusion.setDelay(ident, ns); } Sensor GyroDriftSensor::getSensor() const { sensor_t hwSensor; hwSensor.name = "Gyroscope Bias (debug)"; - hwSensor.vendor = "Google Inc."; + hwSensor.vendor = "AOSP"; hwSensor.version = 1; hwSensor.handle = '_gbs'; hwSensor.type = SENSOR_TYPE_ACCELEROMETER; diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index a12529e..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,36 +59,42 @@ 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); } } } } -void SensorDevice::dump(String8& result, char* buffer, size_t SIZE) +void SensorDevice::dump(String8& result) { if (!mSensorModule) return; sensor_t const* list; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); - snprintf(buffer, SIZE, "%d h/w sensors:\n", int(count)); - result.append(buffer); + result.appendFormat("%d h/w sensors:\n", int(count)); Mutex::Autolock _l(mLock); for (size_t i=0 ; i<size_t(count) ; i++) { const Info& info = mActivationCount.valueFor(list[i].handle); - snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ", - list[i].handle, - info.rates.size()); - result.append(buffer); - for (size_t j=0 ; j<info.rates.size() ; j++) { - snprintf(buffer, SIZE, "%4.1f%s", - info.rates.valueAt(j) / 1e6f, - j<info.rates.size()-1 ? ", " : ""); - result.append(buffer); + 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 ? ", " : ""); } - snprintf(buffer, SIZE, " }, selected=%4.1f ms\n", info.delay / 1e6f); - result.append(buffer); + 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); } } @@ -106,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; } @@ -114,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) @@ -123,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 @@ -159,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 { @@ -202,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; } // --------------------------------------------------------------------------- diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index 227dab6..761b48c 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -31,20 +31,50 @@ namespace android { // --------------------------------------------------------------------------- -static const nsecs_t DEFAULT_EVENTS_PERIOD = 200000000; // 5 Hz - class SensorDevice : public Singleton<SensorDevice> { friend class Singleton<SensorDevice>; - struct sensors_poll_device_t* mSensorDevice; + sensors_poll_device_1_t* mSensorDevice; struct sensors_module_t* mSensorModule; - mutable Mutex mLock; // protect mActivationCount[].rates + static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz + mutable Mutex mLock; // protect mActivationCount[].batchParams // fixed-size array after construction + + // Struct to store all the parameters(samplingPeriod, maxBatchReportLatency and flags) from + // batch call. For continous mode clients, maxBatchReportLatency is set to zero. + struct BatchParams { + int flags; + nsecs_t batchDelay, batchTimeout; + BatchParams() : flags(0), batchDelay(0), batchTimeout(0) {} + BatchParams(int flag, nsecs_t delay, nsecs_t timeout): flags(flag), batchDelay(delay), + batchTimeout(timeout) { } + bool operator != (const BatchParams& other) { + return other.batchDelay != batchDelay || other.batchTimeout != batchTimeout || + other.flags != flags; + } + }; + + // Store batch parameters in the KeyedVector and the optimal batch_rate and timeout in + // bestBatchParams. For every batch() call corresponding params are stored in batchParams + // vector. A continuous mode request is batch(... timeout=0 ..) followed by activate(). A batch + // mode request is batch(... timeout > 0 ...) followed by activate(). + // Info is a per-sensor data structure which contains the batch parameters for each client that + // has registered for this sensor. struct Info { - Info() : delay(0) { } - KeyedVector<void*, nsecs_t> rates; - nsecs_t delay; - status_t setDelayForIdent(void* ident, int64_t ns); - nsecs_t selectDelay(); + BatchParams bestBatchParams; + // Key is the unique identifier(ident) for each client, value is the batch parameters + // requested by the client. + KeyedVector<void*, BatchParams> batchParams; + + Info() : bestBatchParams(-1, -1, -1) {} + // Sets batch parameters for this ident. Returns error if this ident is not already present + // in the KeyedVector above. + status_t setBatchParamsForIdent(void* ident, int flags, int64_t samplingPeriodNs, + int64_t maxBatchReportLatencyNs); + // Finds the optimal parameters for batching and stores them in bestBatchParams variable. + void selectBatchParams(); + // Removes batchParams for an ident and re-computes bestBatchParams. Returns the index of + // the removed ident. If index >=0, ident is present and successfully removed. + ssize_t removeBatchParamsForIdent(void* ident); }; DefaultKeyedVector<int, Info> mActivationCount; @@ -55,9 +85,13 @@ public: int getHalDeviceVersion() const; ssize_t poll(sensors_event_t* buffer, size_t count); status_t activate(void* ident, int handle, int enabled); + status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs, + int64_t maxBatchReportLatencyNs); + // Call batch with timeout zero instead of calling setDelay() for newer devices. status_t setDelay(void* ident, int handle, int64_t ns); + status_t flush(void* ident, int handle); void autoDisable(void *ident, int handle); - void dump(String8& result, char* buffer, size_t SIZE); + void dump(String8& result); }; // --------------------------------------------------------------------------- diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp index d23906d..03f94be 100644 --- a/services/sensorservice/SensorFusion.cpp +++ b/services/sensorservice/SensorFusion.cpp @@ -28,6 +28,7 @@ SensorFusion::SensorFusion() mEnabled(false), mGyroTime(0) { sensor_t const* list; + Sensor uncalibratedGyro; ssize_t count = mSensorDevice.getSensorList(&list); if (count > 0) { for (size_t i=0 ; i<size_t(count) ; i++) { @@ -39,28 +40,38 @@ SensorFusion::SensorFusion() } if (list[i].type == SENSOR_TYPE_GYROSCOPE) { mGyro = Sensor(list + i); - // 200 Hz for gyro events is a good compromise between precision - // and power/cpu usage. - mGyroRate = 200; - mTargetDelayNs = 1000000000LL/mGyroRate; } + if (list[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) { + uncalibratedGyro = Sensor(list + i); + } + } + + // Use the uncalibrated gyroscope for sensor fusion when available + if (uncalibratedGyro.getType() == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) { + mGyro = uncalibratedGyro; } + + // 200 Hz for gyro events is a good compromise between precision + // and power/cpu usage. + mEstimatedGyroRate = 200; + mTargetDelayNs = 1000000000LL/mEstimatedGyroRate; mFusion.init(); } } void SensorFusion::process(const sensors_event_t& event) { - if (event.type == SENSOR_TYPE_GYROSCOPE) { + if (event.type == mGyro.getType()) { if (mGyroTime != 0) { const float dT = (event.timestamp - mGyroTime) / 1000000000.0f; + mFusion.handleGyro(vec3_t(event.data), dT); + // here we estimate the gyro rate (useful for debugging) const float freq = 1 / dT; if (freq >= 100 && freq<1000) { // filter values obviously wrong const float alpha = 1 / (1 + dT); // 1s time-constant - mGyroRate = freq + (mGyroRate - freq)*alpha; + mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha; } } mGyroTime = event.timestamp; - mFusion.handleGyro(vec3_t(event.data), 1.0f/mGyroRate); } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) { const vec3_t mag(event.data); mFusion.handleMag(mag); @@ -91,6 +102,15 @@ status_t SensorFusion::activate(void* ident, bool enabled) { } } + if (enabled) { + ALOGD_IF(DEBUG_CONNECTIONS, "SensorFusion calling batch ident=%p ", ident); + // Activating a sensor in continuous mode is equivalent to calling batch with the default + // period and timeout equal to ZERO, followed by a call to activate. + mSensorDevice.batch(ident, mAcc.getHandle(), 0, DEFAULT_EVENTS_PERIOD, 0); + mSensorDevice.batch(ident, mMag.getHandle(), 0, DEFAULT_EVENTS_PERIOD, 0); + mSensorDevice.batch(ident, mGyro.getHandle(), 0, DEFAULT_EVENTS_PERIOD, 0); + } + mSensorDevice.activate(ident, mAcc.getHandle(), enabled); mSensorDevice.activate(ident, mMag.getHandle(), enabled); mSensorDevice.activate(ident, mGyro.getHandle(), enabled); @@ -125,14 +145,14 @@ int32_t SensorFusion::getMinDelay() const { return mAcc.getMinDelay(); } -void SensorFusion::dump(String8& result, char* buffer, size_t SIZE) { +void SensorFusion::dump(String8& result) { const Fusion& fusion(mFusion); - snprintf(buffer, SIZE, "9-axis fusion %s (%d clients), gyro-rate=%7.2fHz, " + result.appendFormat("9-axis fusion %s (%d clients), gyro-rate=%7.2fHz, " "q=< %g, %g, %g, %g > (%g), " "b=< %g, %g, %g >\n", mEnabled ? "enabled" : "disabled", mClients.size(), - mGyroRate, + mEstimatedGyroRate, fusion.getAttitude().x, fusion.getAttitude().y, fusion.getAttitude().z, @@ -141,7 +161,6 @@ void SensorFusion::dump(String8& result, char* buffer, size_t SIZE) { fusion.getBias().x, fusion.getBias().y, fusion.getBias().z); - result.append(buffer); } // --------------------------------------------------------------------------- diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h index 4c99bcb..b8f360f 100644 --- a/services/sensorservice/SensorFusion.h +++ b/services/sensorservice/SensorFusion.h @@ -37,6 +37,7 @@ class SensorDevice; class SensorFusion : public Singleton<SensorFusion> { friend class Singleton<SensorFusion>; + static const nsecs_t DEFAULT_EVENTS_PERIOD = 200000000; // 5 Hz SensorDevice& mSensorDevice; Sensor mAcc; @@ -44,7 +45,7 @@ class SensorFusion : public Singleton<SensorFusion> { Sensor mGyro; Fusion mFusion; bool mEnabled; - float mGyroRate; + float mEstimatedGyroRate; nsecs_t mTargetDelayNs; nsecs_t mGyroTime; vec4_t mAttitude; @@ -60,7 +61,7 @@ public: mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); } vec4_t getAttitude() const { return mAttitude; } vec3_t getGyroBias() const { return mFusion.getBias(); } - float getEstimatedRate() const { return mGyroRate; } + float getEstimatedRate() const { return mEstimatedGyroRate; } status_t activate(void* ident, bool enabled); status_t setDelay(void* ident, int64_t ns); @@ -68,7 +69,7 @@ public: float getPowerUsage() const; int32_t getMinDelay() const; - void dump(String8& result, char* buffer, size_t SIZE); + void dump(String8& result); }; diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp index b483b75..f1d1663 100644 --- a/services/sensorservice/SensorInterface.cpp +++ b/services/sensorservice/SensorInterface.cpp @@ -32,7 +32,7 @@ SensorInterface::~SensorInterface() HardwareSensor::HardwareSensor(const sensor_t& sensor) : mSensorDevice(SensorDevice::getInstance()), - mSensor(&sensor) + mSensor(&sensor, mSensorDevice.getHalDeviceVersion()) { ALOGI("%s", sensor.name); } @@ -50,6 +50,16 @@ status_t HardwareSensor::activate(void* ident, bool enabled) { return mSensorDevice.activate(ident, mSensor.getHandle(), enabled); } +status_t HardwareSensor::batch(void* ident, int handle, int flags, + int64_t samplingPeriodNs, int64_t maxBatchReportLatencyNs) { + return mSensorDevice.batch(ident, mSensor.getHandle(), flags, samplingPeriodNs, + maxBatchReportLatencyNs); +} + +status_t HardwareSensor::flush(void* ident, int handle) { + return mSensorDevice.flush(ident, handle); +} + status_t HardwareSensor::setDelay(void* ident, int handle, int64_t ns) { return mSensorDevice.setDelay(ident, handle, ns); } diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h index 2e14e57..c295e22 100644 --- a/services/sensorservice/SensorInterface.h +++ b/services/sensorservice/SensorInterface.h @@ -38,6 +38,20 @@ public: virtual status_t activate(void* ident, bool enabled) = 0; virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0; + + // Not all sensors need to support batching. + virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs, + int64_t maxBatchReportLatencyNs) { + if (maxBatchReportLatencyNs == 0) { + return setDelay(ident, handle, samplingPeriodNs); + } + return -EINVAL; + } + + virtual status_t flush(void* ident, int handle) { + return -EINVAL; + } + virtual Sensor getSensor() const = 0; virtual bool isVirtual() const = 0; virtual void autoDisable(void *ident, int handle) { } @@ -59,7 +73,10 @@ public: const sensors_event_t& event); virtual status_t activate(void* ident, bool enabled); + virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs, + int64_t maxBatchReportLatencyNs); virtual status_t setDelay(void* ident, int handle, int64_t ns); + virtual status_t flush(void* ident, int handle); virtual Sensor getSensor() const; virtual bool isVirtual() const { return false; } virtual void autoDisable(void *ident, int handle); diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp index 6481584..555d843 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -93,6 +93,7 @@ void SensorService::onFirstRef() orientationIndex = i; break; case SENSOR_TYPE_GYROSCOPE: + case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: hasGyro = true; break; case SENSOR_TYPE_GRAVITY: @@ -108,54 +109,59 @@ void SensorService::onFirstRef() // registered) const SensorFusion& fusion(SensorFusion::getInstance()); + // build the sensor list returned to users + mUserSensorList = mSensorList; + if (hasGyro) { - // Always instantiate Android's virtual sensors. Since they are - // instantiated behind sensors from the HAL, they won't - // interfere with applications, unless they looks specifically - // for them (by name). + Sensor aSensor; - registerVirtualSensor( new RotationVectorSensor() ); - registerVirtualSensor( new GravitySensor(list, count) ); - registerVirtualSensor( new LinearAccelerationSensor(list, count) ); + // Add Android virtual sensors if they're not already + // available in the HAL - // these are optional - registerVirtualSensor( new OrientationSensor() ); - registerVirtualSensor( new CorrectedGyroSensor(list, count) ); - } + aSensor = registerVirtualSensor( new RotationVectorSensor() ); + if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { + mUserSensorList.add(aSensor); + } - // build the sensor list returned to users - mUserSensorList = mSensorList; + aSensor = registerVirtualSensor( new GravitySensor(list, count) ); + if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) { + mUserSensorList.add(aSensor); + } - if (hasGyro) { - // virtual debugging sensors are not added to mUserSensorList - registerVirtualSensor( new GyroDriftSensor() ); - } + aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) ); + if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) { + mUserSensorList.add(aSensor); + } - if (hasGyro && - (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) { - // if we have the fancy sensor fusion, and it's not provided by the - // HAL, use our own (fused) orientation sensor by removing the - // HAL supplied one form the user list. - if (orientationIndex >= 0) { - mUserSensorList.removeItemsAt(orientationIndex); + aSensor = registerVirtualSensor( new OrientationSensor() ); + if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) { + // if we are doing our own rotation-vector, also add + // the orientation sensor and remove the HAL provided one. + mUserSensorList.replaceAt(aSensor, orientationIndex); } + + // virtual debugging sensors are not added to mUserSensorList + registerVirtualSensor( new CorrectedGyroSensor(list, count) ); + registerVirtualSensor( new GyroDriftSensor() ); } // debugging sensor list - for (size_t i=0 ; i<mSensorList.size() ; i++) { - switch (mSensorList[i].getType()) { - case SENSOR_TYPE_GRAVITY: - case SENSOR_TYPE_LINEAR_ACCELERATION: - case SENSOR_TYPE_ROTATION_VECTOR: - if (strstr(mSensorList[i].getVendor().string(), "Google")) { - mUserSensorListDebug.add(mSensorList[i]); - } - break; - default: - mUserSensorListDebug.add(mSensorList[i]); - break; + mUserSensorListDebug = mSensorList; + + mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED; + FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r"); + char line[128]; + if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) { + line[sizeof(line) - 1] = '\0'; + sscanf(line, "%u", &mSocketBufferSize); + if (mSocketBufferSize > MAX_SOCKET_BUFFER_SIZE_BATCHED) { + mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED; } } + ALOGD("Max socket buffer size %u", mSocketBufferSize); + if (fp) { + fclose(fp); + } run("SensorService", PRIORITY_URGENT_DISPLAY); mInitCheck = NO_ERROR; @@ -163,7 +169,7 @@ void SensorService::onFirstRef() } } -void SensorService::registerSensor(SensorInterface* s) +Sensor SensorService::registerSensor(SensorInterface* s) { sensors_event_t event; memset(&event, 0, sizeof(event)); @@ -175,12 +181,15 @@ void SensorService::registerSensor(SensorInterface* s) mSensorMap.add(sensor.getHandle(), s); // create an entry in the mLastEventSeen array mLastEventSeen.add(sensor.getHandle(), event); + + return sensor; } -void SensorService::registerVirtualSensor(SensorInterface* s) +Sensor SensorService::registerVirtualSensor(SensorInterface* s) { - registerSensor(s); + Sensor sensor = registerSensor(s); mVirtualSensorList.add( s ); + return sensor; } SensorService::~SensorService() @@ -193,47 +202,92 @@ static const String16 sDump("android.permission.DUMP"); status_t SensorService::dump(int fd, const Vector<String16>& args) { - const size_t SIZE = 1024; - char buffer[SIZE]; String8 result; if (!PermissionCache::checkCallingPermission(sDump)) { - snprintf(buffer, SIZE, "Permission Denial: " + result.appendFormat("Permission Denial: " "can't dump SurfaceFlinger from pid=%d, uid=%d\n", IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid()); - result.append(buffer); } else { Mutex::Autolock _l(mLock); - snprintf(buffer, SIZE, "Sensor List:\n"); - result.append(buffer); + result.append("Sensor List:\n"); for (size_t i=0 ; i<mSensorList.size() ; i++) { const Sensor& s(mSensorList[i]); const sensors_event_t& e(mLastEventSeen.valueFor(s.getHandle())); - snprintf(buffer, SIZE, - "%-48s| %-32s | 0x%08x | maxRate=%7.2fHz | " - "last=<%5.1f,%5.1f,%5.1f>\n", + result.appendFormat( + "%-48s| %-32s | 0x%08x | ", s.getName().string(), s.getVendor().string(), - s.getHandle(), - s.getMinDelay() ? (1000000.0f / s.getMinDelay()) : 0.0f, - e.data[0], e.data[1], e.data[2]); - result.append(buffer); + s.getHandle()); + + if (s.getMinDelay() > 0) { + result.appendFormat( + "maxRate=%7.2fHz | ", 1e6f / s.getMinDelay()); + } else { + result.append(s.getMinDelay() == 0 + ? "on-demand | " + : "one-shot | "); + } + if (s.getFifoMaxEventCount() > 0) { + result.appendFormat("getFifoMaxEventCount=%d events | ", s.getFifoMaxEventCount()); + } else { + result.append("no batching support | "); + } + + switch (s.getType()) { + case SENSOR_TYPE_ROTATION_VECTOR: + case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR: + result.appendFormat( + "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n", + e.data[0], e.data[1], e.data[2], e.data[3], e.data[4]); + break; + case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED: + case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED: + result.appendFormat( + "last=<%5.1f,%5.1f,%5.1f,%5.1f,%5.1f,%5.1f>\n", + e.data[0], e.data[1], e.data[2], e.data[3], e.data[4], e.data[5]); + break; + case SENSOR_TYPE_GAME_ROTATION_VECTOR: + result.appendFormat( + "last=<%5.1f,%5.1f,%5.1f,%5.1f>\n", + e.data[0], e.data[1], e.data[2], e.data[3]); + break; + case SENSOR_TYPE_SIGNIFICANT_MOTION: + case SENSOR_TYPE_STEP_DETECTOR: + result.appendFormat( "last=<%f>\n", e.data[0]); + break; + case SENSOR_TYPE_STEP_COUNTER: + result.appendFormat( "last=<%llu>\n", e.u64.step_counter); + break; + default: + // default to 3 values + result.appendFormat( + "last=<%5.1f,%5.1f,%5.1f>\n", + e.data[0], e.data[1], e.data[2]); + break; + } } - SensorFusion::getInstance().dump(result, buffer, SIZE); - SensorDevice::getInstance().dump(result, buffer, SIZE); - - snprintf(buffer, SIZE, "%d active connections\n", - mActiveConnections.size()); - result.append(buffer); - snprintf(buffer, SIZE, "Active sensors:\n"); - result.append(buffer); + SensorFusion::getInstance().dump(result); + SensorDevice::getInstance().dump(result); + + result.append("Active sensors:\n"); for (size_t i=0 ; i<mActiveSensors.size() ; i++) { int handle = mActiveSensors.keyAt(i); - snprintf(buffer, SIZE, "%s (handle=0x%08x, connections=%d)\n", + result.appendFormat("%s (handle=0x%08x, connections=%d)\n", getSensorName(handle).string(), handle, mActiveSensors.valueAt(i)->getNumConnections()); - result.append(buffer); + } + + result.appendFormat("%u Max Socket Buffer size\n", mSocketBufferSize); + result.appendFormat("%d active connections\n", mActiveConnections.size()); + + for (size_t i=0 ; i < mActiveConnections.size() ; i++) { + sp<SensorEventConnection> connection(mActiveConnections[i].promote()); + if (connection != 0) { + result.appendFormat("Connection Number: %d \n", i); + connection->dump(result); + } } } write(fd, result.string(), result.size()); @@ -246,7 +300,8 @@ void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& c status_t err = NO_ERROR; for (int i=0 ; i<count ; i++) { int handle = buffer[i].sensor; - if (getSensorType(handle) == SENSOR_TYPE_SIGNIFICANT_MOTION) { + int type = buffer[i].type; + if (type == SENSOR_TYPE_SIGNIFICANT_MOTION) { if (connection->hasSensor(handle)) { sensor = mSensorMap.valueFor(handle); if (sensor != NULL) { @@ -262,8 +317,12 @@ bool SensorService::threadLoop() { ALOGD("nuSensorService thread starting..."); - const size_t numEventMax = 16; - const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size(); + // 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()); + sensors_event_t buffer[minBufferSize]; sensors_event_t scratch[minBufferSize]; SensorDevice& device(SensorDevice::getInstance()); @@ -283,7 +342,7 @@ bool SensorService::threadLoop() // Todo(): add a flag to the sensors definitions to indicate // the sensors which can wake up the AP for (int i = 0; i < count; i++) { - if (getSensorType(buffer[i].sensor) == SENSOR_TYPE_SIGNIFICANT_MOTION) { + if (buffer[i].type == SENSOR_TYPE_SIGNIFICANT_MOTION) { acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); wakeLockAcquired = true; break; @@ -335,7 +394,7 @@ 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 (getSensorType(buffer[i].sensor) == SENSOR_TYPE_ROTATION_VECTOR) { + if (buffer[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; @@ -359,7 +418,6 @@ bool SensorService::threadLoop() // We have read the data, upper layers should hold the wakelock. if (wakeLockAcquired) release_wake_lock(WAKE_LOCK_NAME); - } while (count >= 0 || Thread::exitPending()); ALOGW("Exiting SensorService::threadLoop => aborting..."); @@ -371,7 +429,6 @@ void SensorService::recordLastValue( sensors_event_t const * buffer, size_t count) { Mutex::Autolock _l(mLock); - // record the last event for each sensor int32_t prev = buffer[0].sensor; for (size_t i=1 ; i<count ; i++) { @@ -423,18 +480,6 @@ String8 SensorService::getSensorName(int handle) const { return result; } -int SensorService::getSensorType(int handle) const { - size_t count = mUserSensorList.size(); - for (size_t i=0 ; i<count ; i++) { - const Sensor& sensor(mUserSensorList[i]); - if (sensor.getHandle() == handle) { - return sensor.getType(); - } - } - return -1; -} - - Vector<Sensor> SensorService::getSensorList() { char value[PROPERTY_VALUE_MAX]; @@ -489,7 +534,7 @@ void SensorService::cleanupConnection(SensorEventConnection* c) } status_t SensorService::enable(const sp<SensorEventConnection>& connection, - int handle) + int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags) { if (mInitCheck != NO_ERROR) return mInitCheck; @@ -498,7 +543,6 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (sensor == NULL) { return BAD_VALUE; } - Mutex::Autolock _l(mLock); SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec == 0) { @@ -535,10 +579,33 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, handle, connection.get()); } - // we are setup, now enable the sensor. - status_t err = sensor->activate(connection.get(), true); + nsecs_t minDelayNs = sensor->getSensor().getMinDelayNs(); + if (samplingPeriodNs < minDelayNs) { + samplingPeriodNs = minDelayNs; + } + + ALOGD_IF(DEBUG_CONNECTIONS, "Calling batch handle==%d flags=%d rate=%lld timeout== %lld", + handle, reservedFlags, samplingPeriodNs, maxBatchReportLatencyNs); + + status_t err = sensor->batch(connection.get(), handle, reservedFlags, samplingPeriodNs, + maxBatchReportLatencyNs); + if (err == NO_ERROR) { + connection->setFirstFlushPending(handle, true); + 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 + // not support flush. + if (err_flush != NO_ERROR) { + connection->setFirstFlushPending(handle, false); + } + } + + if (err == NO_ERROR) { + ALOGD_IF(DEBUG_CONNECTIONS, "Calling activate on %d", handle); + err = sensor->activate(connection.get(), true); + } + if (err != NO_ERROR) { - // enable has failed, reset our state. + // batch/activate has failed, reset our state. cleanupWithoutDisableLocked(connection, handle); } return err; @@ -605,12 +672,22 @@ status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection ns = minDelayNs; } - if (ns < MINIMUM_EVENTS_PERIOD) - ns = MINIMUM_EVENTS_PERIOD; - return sensor->setDelay(connection.get(), handle, ns); } +status_t SensorService::flushSensor(const sp<SensorEventConnection>& connection, + int handle) { + if (mInitCheck != NO_ERROR) return mInitCheck; + SensorInterface* sensor = mSensorMap.valueFor(handle); + if (sensor == NULL) { + return BAD_VALUE; + } + if (sensor->getSensor().getType() == SENSOR_TYPE_SIGNIFICANT_MOTION) { + ALOGE("flush called on Significant Motion sensor"); + return INVALID_OPERATION; + } + return sensor->flush(connection.get(), handle); +} // --------------------------------------------------------------------------- SensorService::SensorRecord::SensorRecord( @@ -643,8 +720,15 @@ bool SensorService::SensorRecord::removeConnection( SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service, uid_t uid) - : mService(service), mChannel(new BitTube()), mUid(uid) + : mService(service), mUid(uid) { + const SensorDevice& device(SensorDevice::getInstance()); + if (device.getHalDeviceVersion() >= SENSORS_DEVICE_API_VERSION_1_1) { + // Increase socket buffer size to 1MB for batching capabilities. + mChannel = new BitTube(service->mSocketBufferSize); + } else { + mChannel = new BitTube(SOCKET_BUFFER_SIZE_NON_BATCHED); + } } SensorService::SensorEventConnection::~SensorEventConnection() @@ -657,10 +741,22 @@ void SensorService::SensorEventConnection::onFirstRef() { } +void SensorService::SensorEventConnection::dump(String8& result) { + Mutex::Autolock _l(mConnectionLock); + for (size_t i = 0; i < mSensorInfo.size(); ++i) { + const FlushInfo& flushInfo = mSensorInfo.valueAt(i); + result.appendFormat("\t %s | status: %s | pending flush events %d\n", + mService->getSensorName(mSensorInfo.keyAt(i)).string(), + flushInfo.mFirstFlushPending ? "First flush pending" : + "active", + flushInfo.mPendingFlushEventsToSend); + } +} + bool SensorService::SensorEventConnection::addSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); - if (mSensorInfo.indexOf(handle) < 0) { - mSensorInfo.add(handle); + if (mSensorInfo.indexOfKey(handle) < 0) { + mSensorInfo.add(handle, FlushInfo()); return true; } return false; @@ -668,7 +764,7 @@ bool SensorService::SensorEventConnection::addSensor(int32_t handle) { bool SensorService::SensorEventConnection::removeSensor(int32_t handle) { Mutex::Autolock _l(mConnectionLock); - if (mSensorInfo.remove(handle) >= 0) { + if (mSensorInfo.removeItem(handle) >= 0) { return true; } return false; @@ -676,7 +772,7 @@ bool SensorService::SensorEventConnection::removeSensor(int32_t handle) { bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const { Mutex::Autolock _l(mConnectionLock); - return mSensorInfo.indexOf(handle) >= 0; + return mSensorInfo.indexOfKey(handle) >= 0; } bool SensorService::SensorEventConnection::hasAnySensor() const { @@ -684,21 +780,50 @@ bool SensorService::SensorEventConnection::hasAnySensor() const { return mSensorInfo.size() ? true : false; } +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; + } +} + status_t SensorService::SensorEventConnection::sendEvents( sensors_event_t const* buffer, size_t numEvents, sensors_event_t* scratch) { // filter out events not for this connection size_t count = 0; + if (scratch) { Mutex::Autolock _l(mConnectionLock); size_t i=0; while (i<numEvents) { - const int32_t curr = buffer[i].sensor; - if (mSensorInfo.indexOf(curr) >= 0) { + int32_t curr = 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 curr to the correct sensor to ensure the sensor events per connection are + // filtered correctly. buffer[i].sensor is zero for meta_data events. + curr = buffer[i].meta_data.sensor; + } + ssize_t index = mSensorInfo.indexOfKey(curr); + if (index >= 0 && mSensorInfo[index].mFirstFlushPending == true && + buffer[i].type == SENSOR_TYPE_META_DATA) { + // This is the first flush before activate is called. Events can now be sent for + // this sensor on this connection. + ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ", + buffer[i].meta_data.sensor); + mSensorInfo.editValueAt(index).mFirstFlushPending = false; + } + if (index >= 0 && mSensorInfo[index].mFirstFlushPending == false) { do { scratch[count++] = buffer[i++]; - } while ((i<numEvents) && (buffer[i].sensor == curr)); + } while ((i<numEvents) && ((buffer[i].sensor == curr) || + (buffer[i].type == SENSOR_TYPE_META_DATA && + buffer[i].meta_data.sensor == curr))); } else { i++; } @@ -708,30 +833,75 @@ status_t SensorService::SensorEventConnection::sendEvents( count = numEvents; } + // Send pending flush events (if any) before sending events from the cache. + { + ASensorEvent flushCompleteEvent; + flushCompleteEvent.type = SENSOR_TYPE_META_DATA; + flushCompleteEvent.sensor = 0; + Mutex::Autolock _l(mConnectionLock); + // 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) { + flushCompleteEvent.meta_data.sensor = mSensorInfo.keyAt(i); + ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1); + if (size < 0) { + // ALOGW("dropping %d events on the floor", count); + countFlushCompleteEventsLocked(scratch, count); + return size; + } + ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ", + flushCompleteEvent.meta_data.sensor); + flushInfo.mPendingFlushEventsToSend--; + } + } + } + // NOTE: ASensorEvent and sensors_event_t are the same type ssize_t size = SensorEventQueue::write(mChannel, reinterpret_cast<ASensorEvent const*>(scratch), count); if (size == -EAGAIN) { // the destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor. - //ALOGW("dropping %d events on the floor", count); + // ALOGW("dropping %d events on the floor", count); + Mutex::Autolock _l(mConnectionLock); + countFlushCompleteEventsLocked(scratch, count); return size; } return size < 0 ? status_t(size) : status_t(NO_ERROR); } +void SensorService::SensorEventConnection::countFlushCompleteEventsLocked( + sensors_event_t* 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; +} + sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const { return mChannel; } status_t SensorService::SensorEventConnection::enableDisable( - int handle, bool enabled) + int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, + int reservedFlags) { status_t err; if (enabled) { - err = mService->enable(this, handle); + err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs, + reservedFlags); } else { err = mService->disable(this, handle); } @@ -739,9 +909,33 @@ status_t SensorService::SensorEventConnection::enableDisable( } status_t SensorService::SensorEventConnection::setEventRate( - int handle, nsecs_t ns) + int handle, nsecs_t samplingPeriodNs) { - return mService->setEventRate(this, handle, ns); + return mService->setEventRate(this, handle, samplingPeriodNs); +} + +status_t SensorService::SensorEventConnection::flush() { + SensorDevice& dev(SensorDevice::getInstance()); + const int halVersion = dev.getHalDeviceVersion(); + Mutex::Autolock _l(mConnectionLock); + status_t err(NO_ERROR); + // Loop through all sensors for this connection and call flush on each of them. + for (size_t i = 0; i < mSensorInfo.size(); ++i) { + const int handle = mSensorInfo.keyAt(i); + if (halVersion < SENSORS_DEVICE_API_VERSION_1_1) { + // For older devices just increment pending flush count which will send a trivial + // flush complete event. + FlushInfo& flushInfo = mSensorInfo.editValueFor(handle); + flushInfo.mPendingFlushEventsToSend++; + } else { + status_t err_flush = mService->flushSensor(this, handle); + if (err_flush != NO_ERROR) { + ALOGE("Flush error handle=%d %s", handle, strerror(-err_flush)); + } + err = (err_flush != NO_ERROR) ? err_flush : err; + } + } + return err; } // --------------------------------------------------------------------------- diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index fcdbc7d..6c1691a 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -38,6 +38,9 @@ // --------------------------------------------------------------------------- #define DEBUG_CONNECTIONS false +// Max size is 1 MB which is enough to accept a batch of about 10k events. +#define MAX_SOCKET_BUFFER_SIZE_BATCHED 1024 * 1024 +#define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024 struct sensors_poll_device_t; struct sensors_module_t; @@ -50,12 +53,12 @@ class SensorService : public BnSensorServer, protected Thread { - friend class BinderService<SensorService>; + friend class BinderService<SensorService>; - static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz - static const char* WAKE_LOCK_NAME; + static const char* WAKE_LOCK_NAME; - SensorService(); + static char const* getServiceName() ANDROID_API { return "sensorservice"; } + SensorService() ANDROID_API; virtual ~SensorService(); virtual void onFirstRef(); @@ -73,16 +76,31 @@ class SensorService : virtual ~SensorEventConnection(); virtual void onFirstRef(); virtual sp<BitTube> getSensorChannel() const; - virtual status_t enableDisable(int handle, bool enabled); - virtual status_t setEventRate(int handle, nsecs_t ns); + 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* scratch, int numEventsDropped); sp<SensorService> const mService; - sp<BitTube> const mChannel; + sp<BitTube> mChannel; uid_t mUid; mutable Mutex mConnectionLock; - // protected by SensorService::mLock - SortedVector<int> mSensorInfo; + 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; public: SensorEventConnection(const sp<SensorService>& service, uid_t uid); @@ -93,6 +111,8 @@ class SensorService : bool hasAnySensor() const; bool addSensor(int32_t handle); bool removeSensor(int32_t handle); + void setFirstFlushPending(int32_t handle, bool value); + void dump(String8& result); uid_t getUid() const { return mUid; } }; @@ -110,17 +130,16 @@ class SensorService : DefaultKeyedVector<int, SensorInterface*> getActiveVirtualSensors() const; String8 getSensorName(int handle) const; - int getSensorType(int handle) const; void recordLastValue(sensors_event_t const * buffer, size_t count); static void sortEventBuffer(sensors_event_t* buffer, size_t count); - void registerSensor(SensorInterface* sensor); - void registerVirtualSensor(SensorInterface* sensor); + 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); void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, - sensors_event_t const* buffer, const int count); + sensors_event_t const* buffer, const int count); // constants Vector<Sensor> mSensorList; @@ -129,6 +148,7 @@ class SensorService : DefaultKeyedVector<int, SensorInterface*> mSensorMap; Vector<SensorInterface *> mVirtualSensorList; status_t mInitCheck; + size_t mSocketBufferSize; // protected by mLock mutable Mutex mLock; @@ -140,12 +160,12 @@ class SensorService : KeyedVector<int32_t, sensors_event_t> mLastEventSeen; public: - static char const* getServiceName() { return "sensorservice"; } - void cleanupConnection(SensorEventConnection* connection); - status_t enable(const sp<SensorEventConnection>& connection, int handle); + status_t enable(const sp<SensorEventConnection>& connection, int handle, + nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags); status_t disable(const sp<SensorEventConnection>& connection, int handle); status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns); + status_t flushSensor(const sp<SensorEventConnection>& connection, int handle); }; // --------------------------------------------------------------------------- diff --git a/services/sensorservice/main_sensorservice.cpp b/services/sensorservice/main_sensorservice.cpp new file mode 100644 index 0000000..303b65f --- /dev/null +++ b/services/sensorservice/main_sensorservice.cpp @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 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 <binder/BinderService.h> +#include "SensorService.h" + +using namespace android; + +int main(int argc, char** argv) { + SensorService::publishAndJoinThreadPool(); + return 0; +} |