diff options
Diffstat (limited to 'services/sensorservice')
-rw-r--r-- | services/sensorservice/Android.mk | 2 | ||||
-rw-r--r-- | services/sensorservice/Fusion.cpp | 65 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.cpp | 21 | ||||
-rw-r--r-- | services/sensorservice/SensorDevice.h | 2 | ||||
-rw-r--r-- | services/sensorservice/SensorInterface.cpp | 4 | ||||
-rw-r--r-- | services/sensorservice/SensorInterface.h | 2 | ||||
-rw-r--r-- | services/sensorservice/SensorService.cpp | 161 | ||||
-rw-r--r-- | services/sensorservice/SensorService.h | 8 |
8 files changed, 217 insertions, 48 deletions
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk index e0cfaa6..dd698c5 100644 --- a/services/sensorservice/Android.mk +++ b/services/sensorservice/Android.mk @@ -20,7 +20,9 @@ LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\" LOCAL_SHARED_LIBRARIES := \ libcutils \ libhardware \ + libhardware_legacy \ libutils \ + liblog \ libbinder \ libui \ libgui diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp index b88a647..93d6127 100644 --- a/services/sensorservice/Fusion.cpp +++ b/services/sensorservice/Fusion.cpp @@ -201,15 +201,15 @@ void Fusion::initFusion(const vec4_t& q, float dT) // q11 = su^2.dt // - // variance of integrated output at 1/dT Hz - // (random drift) - const float q00 = gyroVAR * dT; + const float dT2 = dT*dT; + const float dT3 = dT2*dT; + + // variance of integrated output at 1/dT Hz (random drift) + const float q00 = gyroVAR * dT + 0.33333f * biasVAR * dT3; // variance of drift rate ramp const float q11 = biasVAR * dT; - - const float u = q11 / dT; - const float q10 = 0.5f*u*dT*dT; + const float q10 = 0.5f * biasVAR * dT2; const float q01 = q10; GQGt[0][0] = q00; // rad^2 @@ -220,6 +220,22 @@ 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 { @@ -357,6 +373,11 @@ mat33_t Fusion::getRotationMatrix() const { mat34_t Fusion::getF(const vec4_t& q) { mat34_t F; + + // This is used to compute the derivative of q + // F = | [q.xyz]x | + // | -q.xyz | + F[0].x = q.w; F[1].x =-q.z; F[2].x = q.y; F[0].y = q.z; F[1].y = q.w; F[2].y =-q.x; F[0].z =-q.y; F[1].z = q.x; F[2].z = q.w; @@ -368,10 +389,18 @@ void Fusion::predict(const vec3_t& w, float dT) { const vec4_t q = x0; const vec3_t b = x1; const vec3_t we = w - b; - const vec4_t dq = getF(q)*((0.5f*dT)*we); - x0 = normalize_quat(q + dq); + // q(k+1) = O(we)*q(k) + // -------------------- + // + // O(w) = | cos(0.5*||w||*dT)*I33 - [psi]x psi | + // | -psi' cos(0.5*||w||*dT) | + // + // psi = sin(0.5*||w||*dT)*w / ||w|| + // + // // P(k+1) = Phi(k)*P(k)*Phi(k)' + G*Q(k)*G' + // ---------------------------------------- // // G = | -I33 0 | // | 0 I33 | @@ -392,13 +421,26 @@ void Fusion::predict(const vec3_t& w, float dT) { const mat33_t wx(crossMatrix(we, 0)); const mat33_t wx2(wx*wx); const float lwedT = length(we)*dT; + const float hlwedT = 0.5f*lwedT; const float ilwe = 1/length(we); const float k0 = (1-cosf(lwedT))*(ilwe*ilwe); const float k1 = sinf(lwedT); + const float k2 = cosf(hlwedT); + const vec3_t psi(sinf(hlwedT)*ilwe*we); + const mat33_t O33(crossMatrix(-psi, k2)); + mat44_t O; + O[0].xyz = O33[0]; O[0].w = -psi.x; + O[1].xyz = O33[1]; O[1].w = -psi.y; + O[2].xyz = O33[2]; O[2].w = -psi.z; + O[3].xyz = psi; O[3].w = k2; Phi[0][0] = I33 - wx*(k1*ilwe) + wx2*k0; Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1); + x0 = O*q; + if (x0.w < 0) + x0 = -x0; + P = Phi*P*transpose(Phi) + GQGt; checkState(); @@ -425,7 +467,12 @@ void Fusion::update(const vec3_t& z, const vec3_t& Bi, float sigma) { K[1] = transpose(P[1][0])*LtSi; // update... - // P -= K*H*P; + // P = (I-K*H) * P + // P -= K*H*P + // | K0 | * | L 0 | * P = | K0*L 0 | * | P00 P10 | = | K0*L*P00 K0*L*P10 | + // | K1 | | K1*L 0 | | P01 P11 | | K1*L*P00 K1*L*P10 | + // Note: the Joseph form is numerically more stable and given by: + // P = (I-KH) * P * (I-KH)' + K*R*R' const mat33_t K0L(K[0] * L); const mat33_t K1L(K[1] * L); P[0][0] -= K0L*P[0][0]; diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp index a9e3ef4..a12529e 100644 --- a/services/sensorservice/SensorDevice.cpp +++ b/services/sensorservice/SensorDevice.cpp @@ -111,6 +111,12 @@ ssize_t SensorDevice::poll(sensors_event_t* buffer, size_t count) { return c; } +void SensorDevice::autoDisable(void *ident, int handle) { + Info& info( mActivationCount.editValueFor(handle) ); + Mutex::Autolock _l(mLock); + info.rates.removeItem(ident); +} + status_t SensorDevice::activate(void* ident, int handle, int enabled) { if (!mSensorDevice) return NO_INIT; @@ -159,6 +165,15 @@ status_t SensorDevice::activate(void* ident, int handle, int enabled) ALOGE_IF(err, "Error %s sensor %d (%s)", enabled ? "activating" : "disabling", handle, strerror(-err)); + + if (err != NO_ERROR) { + // clean-up on failure + if (enabled) { + // failure when enabling the sensor + Mutex::Autolock _l(mLock); + info.rates.removeItem(ident); + } + } } { // scope for the lock @@ -181,6 +196,12 @@ status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns) return mSensorDevice->setDelay(mSensorDevice, handle, ns); } +int SensorDevice::getHalDeviceVersion() const { + if (!mSensorDevice) return -1; + + return mSensorDevice->common.version; +} + // --------------------------------------------------------------------------- status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns) diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h index 728b6cb..227dab6 100644 --- a/services/sensorservice/SensorDevice.h +++ b/services/sensorservice/SensorDevice.h @@ -52,9 +52,11 @@ class SensorDevice : public Singleton<SensorDevice> { public: ssize_t getSensorList(sensor_t const** list); status_t initCheck() const; + int getHalDeviceVersion() const; ssize_t poll(sensors_event_t* buffer, size_t count); status_t activate(void* ident, int handle, int enabled); status_t setDelay(void* ident, int handle, int64_t ns); + void autoDisable(void *ident, int handle); void dump(String8& result, char* buffer, size_t SIZE); }; diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp index 468aa61..b483b75 100644 --- a/services/sensorservice/SensorInterface.cpp +++ b/services/sensorservice/SensorInterface.cpp @@ -54,6 +54,10 @@ status_t HardwareSensor::setDelay(void* ident, int handle, int64_t ns) { return mSensorDevice.setDelay(ident, handle, ns); } +void HardwareSensor::autoDisable(void *ident, int handle) { + mSensorDevice.autoDisable(ident, handle); +} + Sensor HardwareSensor::getSensor() const { return mSensor; } diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h index fb357d7..2e14e57 100644 --- a/services/sensorservice/SensorInterface.h +++ b/services/sensorservice/SensorInterface.h @@ -40,6 +40,7 @@ public: virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0; virtual Sensor getSensor() const = 0; virtual bool isVirtual() const = 0; + virtual void autoDisable(void *ident, int handle) { } }; // --------------------------------------------------------------------------- @@ -61,6 +62,7 @@ public: virtual status_t setDelay(void* ident, int handle, int64_t ns); 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 e3dcd02..6481584 100644 --- a/services/sensorservice/SensorService.cpp +++ b/services/sensorservice/SensorService.cpp @@ -38,6 +38,7 @@ #include <gui/SensorEventQueue.h> #include <hardware/sensors.h> +#include <hardware_legacy/power.h> #include "BatteryService.h" #include "CorrectedGyroSensor.h" @@ -60,6 +61,8 @@ namespace android { * */ +const char* SensorService::WAKE_LOCK_NAME = "SensorService"; + SensorService::SensorService() : mInitCheck(NO_INIT) { @@ -237,6 +240,24 @@ status_t SensorService::dump(int fd, const Vector<String16>& args) return NO_ERROR; } +void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection, + sensors_event_t const* buffer, const int count) { + SensorInterface* sensor; + status_t err = NO_ERROR; + for (int i=0 ; i<count ; i++) { + int handle = buffer[i].sensor; + if (getSensorType(handle) == SENSOR_TYPE_SIGNIFICANT_MOTION) { + if (connection->hasSensor(handle)) { + sensor = mSensorMap.valueFor(handle); + if (sensor != NULL) { + sensor->autoDisable(connection.get(), handle); + } + cleanupWithoutDisable(connection, handle); + } + } + } +} + bool SensorService::threadLoop() { ALOGD("nuSensorService thread starting..."); @@ -249,6 +270,8 @@ bool SensorService::threadLoop() const size_t vcount = mVirtualSensorList.size(); ssize_t count; + bool wakeLockAcquired = false; + const int halVersion = device.getHalDeviceVersion(); do { count = device.poll(buffer, numEventMax); if (count<0) { @@ -256,6 +279,17 @@ bool SensorService::threadLoop() break; } + // Poll has returned. Hold a wakelock. + // 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) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME); + wakeLockAcquired = true; + break; + } + } + recordLastValue(buffer, count); // handle virtual sensors @@ -298,6 +332,17 @@ 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) { + // All the 4 components of the quaternion should be available + // No heading accuracy. Set it to -1 + buffer[i].data[4] = -1; + } + } + } + // send our events to clients... const SortedVector< wp<SensorEventConnection> > activeConnections( getActiveConnections()); @@ -307,8 +352,14 @@ bool SensorService::threadLoop() activeConnections[i].promote()); if (connection != 0) { connection->sendEvents(buffer, count, scratch); + // Some sensors need to be auto disabled after the trigger + cleanupAutoDisabledSensor(connection, buffer, count); } } + + // 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..."); @@ -372,6 +423,18 @@ 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]; @@ -431,47 +494,53 @@ status_t SensorService::enable(const sp<SensorEventConnection>& connection, if (mInitCheck != NO_ERROR) return mInitCheck; - Mutex::Autolock _l(mLock); SensorInterface* sensor = mSensorMap.valueFor(handle); - status_t err = sensor ? sensor->activate(connection.get(), true) : status_t(BAD_VALUE); - if (err == NO_ERROR) { - SensorRecord* rec = mActiveSensors.valueFor(handle); - if (rec == 0) { - rec = new SensorRecord(connection); - mActiveSensors.add(handle, rec); - if (sensor->isVirtual()) { - mActiveVirtualSensors.add(handle, sensor); - } - } else { - if (rec->addConnection(connection)) { - // this sensor is already activated, but we are adding a - // connection that uses it. Immediately send down the last - // known value of the requested sensor if it's not a - // "continuous" sensor. - if (sensor->getSensor().getMinDelay() == 0) { - sensors_event_t scratch; - sensors_event_t& event(mLastEventSeen.editValueFor(handle)); - if (event.version == sizeof(sensors_event_t)) { - connection->sendEvents(&event, 1); - } - } - } + if (sensor == NULL) { + return BAD_VALUE; + } + + Mutex::Autolock _l(mLock); + SensorRecord* rec = mActiveSensors.valueFor(handle); + if (rec == 0) { + rec = new SensorRecord(connection); + mActiveSensors.add(handle, rec); + if (sensor->isVirtual()) { + mActiveVirtualSensors.add(handle, sensor); } - if (err == NO_ERROR) { - // connection now active - if (connection->addSensor(handle)) { - BatteryService::enableSensor(connection->getUid(), handle); - // the sensor was added (which means it wasn't already there) - // so, see if this connection becomes active - if (mActiveConnections.indexOf(connection) < 0) { - mActiveConnections.add(connection); + } else { + if (rec->addConnection(connection)) { + // this sensor is already activated, but we are adding a + // connection that uses it. Immediately send down the last + // known value of the requested sensor if it's not a + // "continuous" sensor. + if (sensor->getSensor().getMinDelay() == 0) { + sensors_event_t scratch; + sensors_event_t& event(mLastEventSeen.editValueFor(handle)); + if (event.version == sizeof(sensors_event_t)) { + connection->sendEvents(&event, 1); } - } else { - ALOGW("sensor %08x already enabled in connection %p (ignoring)", - handle, connection.get()); } } } + + if (connection->addSensor(handle)) { + BatteryService::enableSensor(connection->getUid(), handle); + // the sensor was added (which means it wasn't already there) + // so, see if this connection becomes active + if (mActiveConnections.indexOf(connection) < 0) { + mActiveConnections.add(connection); + } + } else { + ALOGW("sensor %08x already enabled in connection %p (ignoring)", + handle, connection.get()); + } + + // we are setup, now enable the sensor. + status_t err = sensor->activate(connection.get(), true); + if (err != NO_ERROR) { + // enable has failed, reset our state. + cleanupWithoutDisableLocked(connection, handle); + } return err; } @@ -481,8 +550,23 @@ status_t SensorService::disable(const sp<SensorEventConnection>& connection, if (mInitCheck != NO_ERROR) return mInitCheck; - status_t err = NO_ERROR; Mutex::Autolock _l(mLock); + status_t err = cleanupWithoutDisableLocked(connection, handle); + if (err == NO_ERROR) { + SensorInterface* sensor = mSensorMap.valueFor(handle); + err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE); + } + return err; +} + +status_t SensorService::cleanupWithoutDisable( + const sp<SensorEventConnection>& connection, int handle) { + Mutex::Autolock _l(mLock); + return cleanupWithoutDisableLocked(connection, handle); +} + +status_t SensorService::cleanupWithoutDisableLocked( + const sp<SensorEventConnection>& connection, int handle) { SensorRecord* rec = mActiveSensors.valueFor(handle); if (rec) { // see if this connection becomes inactive @@ -498,10 +582,9 @@ status_t SensorService::disable(const sp<SensorEventConnection>& connection, mActiveVirtualSensors.removeItem(handle); delete rec; } - SensorInterface* sensor = mSensorMap.valueFor(handle); - err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE); + return NO_ERROR; } - return err; + return BAD_VALUE; } status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection, diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h index 18591bf..fcdbc7d 100644 --- a/services/sensorservice/SensorService.h +++ b/services/sensorservice/SensorService.h @@ -53,6 +53,7 @@ class SensorService : friend class BinderService<SensorService>; static const nsecs_t MINIMUM_EVENTS_PERIOD = 1000000; // 1000 Hz + static const char* WAKE_LOCK_NAME; SensorService(); virtual ~SensorService(); @@ -109,10 +110,17 @@ 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); + 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); // constants Vector<Sensor> mSensorList; |