Merge "Audio HAL: Add latency mode APIs"
diff --git a/include/hardware/sensors-base.h b/include/hardware/sensors-base.h
index 7dc42a0..dbf99f5 100644
--- a/include/hardware/sensors-base.h
+++ b/include/hardware/sensors-base.h
@@ -57,6 +57,7 @@
     SENSOR_TYPE_GYROSCOPE_LIMITED_AXES = 39,
     SENSOR_TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED = 40,
     SENSOR_TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED = 41,
+    SENSOR_TYPE_HEADING = 42,
     SENSOR_TYPE_DEVICE_PRIVATE_BASE = 65536 /* 0x10000 */,
 };
 
diff --git a/include/hardware/sensors.h b/include/hardware/sensors.h
index 589aba0..6f4baf8 100644
--- a/include/hardware/sensors.h
+++ b/include/hardware/sensors.h
@@ -191,6 +191,7 @@
 #define SENSOR_STRING_TYPE_GYROSCOPE_LIMITED_AXES       "android.sensor.gyroscope_limited_axes"
 #define SENSOR_STRING_TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED "android.sensor.accelerometer_limited_axes_uncalibrated"
 #define SENSOR_STRING_TYPE_GYROSCOPE_LIMITED_AXES_UNCALIBRATED "android.sensor.gyroscope_limited_axes_uncalibrated"
+#define SENSOR_STRING_TYPE_HEADING                      "android.sensor.heading"
 
 /**
  * Values returned by the accelerometer in various locations in the universe.
@@ -359,6 +360,14 @@
 } limited_axes_imu_uncalibrated_event_t;
 
 /**
+ * Heading event data
+ */
+typedef struct {
+  float heading;
+  float accuracy;
+} heading_event_t;
+
+/**
  * Union of the various types of sensor data
  * that can be returned.
  */
@@ -452,6 +461,9 @@
              * SENSOR_TYPE_ACCELEROMETER_LIMITED_AXES_UNCALIBRATED for details.
              */
             limited_axes_imu_uncalibrated_event_t limited_axes_imu_uncalibrated;
+
+            /* heading data containing value in degrees and its accuracy */
+            heading_event_t heading;
         };
 
         union {
diff --git a/modules/sensors/dynamic_sensor/HidRawSensor.cpp b/modules/sensors/dynamic_sensor/HidRawSensor.cpp
index 6654228..4520dda 100644
--- a/modules/sensors/dynamic_sensor/HidRawSensor.cpp
+++ b/modules/sensors/dynamic_sensor/HidRawSensor.cpp
@@ -635,8 +635,8 @@
         return false;
     }
 
-    mFeatureInfo.type = SENSOR_TYPE_DEVICE_PRIVATE_BASE;
-    mFeatureInfo.typeString = CUSTOM_TYPE_PREFIX + "headtracker";
+    mFeatureInfo.type = SENSOR_TYPE_HEAD_TRACKER;
+    mFeatureInfo.typeString = SENSOR_STRING_TYPE_HEAD_TRACKER;
     mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE;
     mFeatureInfo.permission = "";
     mFeatureInfo.isWakeUp = false;
@@ -1011,6 +1011,50 @@
         .type = mSensor.type
     };
     bool valid = true;
+
+    switch (mFeatureInfo.type) {
+        case SENSOR_TYPE_HEAD_TRACKER:
+            valid = getHeadTrackerEventData(message, &event);
+            break;
+        default:
+            valid = getSensorEventData(message, &event);
+            break;
+    }
+    if (!valid) {
+        LOG_E << "Invalid data observed in decoding, discard" << LOG_ENDL;
+        return;
+    }
+    event.timestamp = -1;
+    generateEvent(event);
+}
+
+bool HidRawSensor::getHeadTrackerEventData(const std::vector<uint8_t> &message,
+                                           sensors_event_t *event) {
+    head_tracker_event_t *head_tracker;
+
+    head_tracker = &(event->head_tracker);
+    if (!getReportFieldValue(message, &(mTranslateTable[0]),
+                             &(head_tracker->rx))
+            || !getReportFieldValue(message, &(mTranslateTable[1]),
+                                    &(head_tracker->ry))
+            || !getReportFieldValue(message, &(mTranslateTable[2]),
+                                    &(head_tracker->rz))
+            || !getReportFieldValue(message, &(mTranslateTable[3]),
+                                    &(head_tracker->vx))
+            || !getReportFieldValue(message, &(mTranslateTable[4]),
+                                    &(head_tracker->vy))
+            || !getReportFieldValue(message, &(mTranslateTable[5]),
+                                    &(head_tracker->vz))
+            || !getReportFieldValue(message, &(mTranslateTable[6]),
+                                    &(head_tracker->discontinuity_count))) {
+        return false;
+    }
+
+    return true;
+}
+
+bool HidRawSensor::getSensorEventData(const std::vector<uint8_t> &message,
+                                      sensors_event_t *event) {
     for (const auto &rec : mTranslateTable) {
         int64_t v = (message[rec.byteOffset + rec.byteSize - 1] & 0x80) ? -1 : 0;
         for (int i = static_cast<int>(rec.byteSize) - 1; i >= 0; --i) {
@@ -1020,26 +1064,23 @@
         switch (rec.type) {
             case TYPE_FLOAT:
                 if (v > rec.maxValue || v < rec.minValue) {
-                    valid = false;
+                    return false;
                 }
-                event.data[rec.index] = rec.a * (v + rec.b);
+                event->data[rec.index] = rec.a * (v + rec.b);
                 break;
             case TYPE_INT64:
                 if (v > rec.maxValue || v < rec.minValue) {
-                    valid = false;
+                    return false;
                 }
-                event.u64.data[rec.index] = v + rec.b;
+                event->u64.data[rec.index] = v + rec.b;
                 break;
             case TYPE_ACCURACY:
-                event.magnetic.status = (v & 0xFF) + rec.b;
+                event->magnetic.status = (v & 0xFF) + rec.b;
                 break;
         }
     }
-    if (!valid) {
-        LOG_V << "Range error observed in decoding, discard" << LOG_ENDL;
-    }
-    event.timestamp = -1;
-    generateEvent(event);
+
+    return true;
 }
 
 std::string HidRawSensor::dump() const {
diff --git a/modules/sensors/dynamic_sensor/HidRawSensor.h b/modules/sensors/dynamic_sensor/HidRawSensor.h
index f6d13b5..66843fc 100644
--- a/modules/sensors/dynamic_sensor/HidRawSensor.h
+++ b/modules/sensors/dynamic_sensor/HidRawSensor.h
@@ -46,6 +46,14 @@
     // handle input report received
     void handleInput(uint8_t id, const std::vector<uint8_t> &message);
 
+    // get head tracker sensor event data
+    bool getHeadTrackerEventData(const std::vector<uint8_t> &message,
+                                 sensors_event_t *event);
+
+    // get generic sensor event data
+    bool getSensorEventData(const std::vector<uint8_t> &message,
+                            sensors_event_t *event);
+
     // indicate if the HidRawSensor is a valid one
     bool isValid() const { return mValid; };
 
@@ -141,6 +149,33 @@
     // process HID snesor spec defined orientation(quaternion) sensor usages.
     bool processQuaternionUsage(const std::vector<HidParser::ReportPacket> &packets);
 
+    // get the value of a report field
+    template<typename ValueType>
+    bool getReportFieldValue(const std::vector<uint8_t> &message,
+                             ReportTranslateRecord* rec, ValueType* value) {
+        bool valid = true;
+        int64_t v;
+
+        v = (message[rec->byteOffset + rec->byteSize - 1] & 0x80) ? -1 : 0;
+        for (int i = static_cast<int>(rec->byteSize) - 1; i >= 0; --i) {
+            v = (v << 8) | message[rec->byteOffset + i]; // HID is little endian
+        }
+        if (v > rec->maxValue || v < rec->minValue) {
+            valid = false;
+        }
+
+        switch (rec->type) {
+            case TYPE_FLOAT:
+                *value = rec->a * (v + rec->b);
+                break;
+            case TYPE_INT64:
+                *value = v + rec->b;
+                break;
+        }
+
+        return valid;
+    }
+
     // dump data for test/debug purpose
     std::string dump() const;