Merge "Sensor changes." into jb-mr2-dev
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index a1de3c5..dd698c5 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -20,6 +20,7 @@
 LOCAL_SHARED_LIBRARIES := \
 	libcutils \
 	libhardware \
+	libhardware_legacy \
 	libutils \
 	liblog \
 	libbinder \
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index a9e3ef4..b256cce 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -181,6 +181,12 @@
     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..b423f40 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -52,6 +52,7 @@
 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);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index e3dcd02..9ca6b45 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 @@
  *
  */
 
+const char* SensorService::WAKE_LOCK_NAME = "SensorService";
+
 SensorService::SensorService()
     : mInitCheck(NO_INIT)
 {
@@ -237,6 +240,18 @@
     return NO_ERROR;
 }
 
+void SensorService::cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
+        sensors_event_t const* buffer, const int count) {
+    for (int i=0 ; i<count ; i++) {
+        int handle = buffer[i].sensor;
+        if (getSensorType(handle) == SENSOR_TYPE_SIGNIFICANT_MOTION) {
+            if (connection->hasSensor(handle)) {
+                cleanupWithoutDisable(connection, handle);
+            }
+        }
+    }
+}
+
 bool SensorService::threadLoop()
 {
     ALOGD("nuSensorService thread starting...");
@@ -249,6 +264,8 @@
     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 +273,17 @@
             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 +326,17 @@
             }
         }
 
+        // 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 +346,14 @@
                     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 +417,18 @@
     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];
@@ -433,44 +490,48 @@
 
     Mutex::Autolock _l(mLock);
     SensorInterface* sensor = mSensorMap.valueFor(handle);
+    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 (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 ? 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 (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 {
-                ALOGW("sensor %08x already enabled in connection %p (ignoring)",
-                        handle, connection.get());
-            }
-        }
+
+    if (err != NO_ERROR) {
+        // enable has failed, reset our state.
+        cleanupWithoutDisable(connection, handle);
     }
     return err;
 }
@@ -481,7 +542,16 @@
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    status_t err = NO_ERROR;
+    status_t err = cleanupWithoutDisable(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);
     SensorRecord* rec = mActiveSensors.valueFor(handle);
     if (rec) {
@@ -498,10 +568,9 @@
             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..25e5f76 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -53,6 +53,7 @@
    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,15 @@
     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);
+    void cleanupAutoDisabledSensor(const sp<SensorEventConnection>& connection,
+        sensors_event_t const* buffer, const int count);
 
     // constants
     Vector<Sensor> mSensorList;