+static int is_fast_accelerometer (int s)
+{
+ /*
+ * Some games don't react well to accelerometers using any-motion
+ * triggers. Even very low thresholds seem to trip them, and they tend
+ * to request fairly high event rates. Favor continuous triggers if the
+ * sensor is an accelerometer and uses a sampling rate of at least 25.
+ */
+
+ if (sensor_info[s].type != SENSOR_TYPE_ACCELEROMETER)
+ return 0;
+
+ if (sensor_info[s].sampling_rate < 25)
+ return 0;
+
+ return 1;
+}
+
+
+static void enable_motion_trigger (int dev_num)
+{
+ /*
+ * In the ideal case, we enumerate two triggers per iio device ; the
+ * default (periodically firing) trigger, and another one (the motion
+ * trigger) that only fires up when motion is detected. This second one
+ * allows for lesser energy consumption, but requires periodic sample
+ * duplication at the HAL level for sensors that Android defines as
+ * continuous. This "duplicate last sample" logic can only be engaged
+ * once we got a first sample for the driver, so we start with the
+ * default trigger when an iio device is first opened, then adjust the
+ * trigger when we got events for all active sensors. Unfortunately in
+ * the general case several sensors can be associated to a given iio
+ * device, they can independently be controlled, and we have to adjust
+ * the trigger in use at the iio device level depending on whether or
+ * not appropriate conditions are met at the sensor level.
+ */
+
+ int s;
+ int i;
+ int active_sensors = trig_sensors_per_dev[dev_num];
+ int candidate[MAX_SENSORS];
+ int candidate_count = 0;
+
+ if (!active_sensors)
+ return;
+
+ /* Check that all active sensors are ready to switch */
+
+ for (s=0; s<MAX_SENSORS; s++)
+ if (sensor_info[s].dev_num == dev_num &&
+ sensor_info[s].enable_count &&
+ sensor_info[s].num_channels &&
+ (!sensor_info[s].motion_trigger_name[0] ||
+ !sensor_info[s].report_initialized ||
+ is_fast_accelerometer(s) ||
+ (sensor_info[s].quirks & QUIRK_FORCE_CONTINUOUS))
+ )
+ return; /* Nope */
+
+ /* Record which particular sensors need to switch */
+
+ for (s=0; s<MAX_SENSORS; s++)
+ if (sensor_info[s].dev_num == dev_num &&
+ sensor_info[s].enable_count &&
+ sensor_info[s].num_channels &&
+ sensor_info[s].selected_trigger !=
+ sensor_info[s].motion_trigger_name)
+ candidate[candidate_count++] = s;
+
+ if (!candidate_count)
+ return;
+
+ /* Now engage the motion trigger for sensors which aren't using it */
+
+ enable_buffer(dev_num, 0);
+
+ for (i=0; i<candidate_count; i++) {
+ s = candidate[i];
+ setup_trigger(s, sensor_info[s].motion_trigger_name);
+ }
+
+ enable_buffer(dev_num, 1);
+}
+
+/* CTS acceptable thresholds:
+ * EventGapVerification.java: (th <= 1.8)
+ * FrequencyVerification.java: (0.9)*(expected freq) => (th <= 1.1111)
+ */
+#define THRESHOLD 1.10
+void set_report_ts(int s, int64_t ts)
+{
+ int64_t maxTs, period;
+ int catalog_index = sensor_info[s].catalog_index;
+ int is_accel = (sensor_catalog[catalog_index].type == SENSOR_TYPE_ACCELEROMETER);
+
+ /*
+ * A bit of a hack to please a bunch of cts tests. They
+ * expect the timestamp to be exacly according to the set-up
+ * frequency but if we're simply getting the timestamp at hal level
+ * this may not be the case. Perhaps we'll get rid of this when
+ * we'll be reading the timestamp from the iio channel for all sensors
+ */
+ if (sensor_info[s].report_ts && sensor_info[s].sampling_rate &&
+ REPORTING_MODE(sensor_desc[s].flags) == SENSOR_FLAG_CONTINUOUS_MODE)
+ {
+ period = (int64_t) (1000000000LL / sensor_info[s].sampling_rate);
+ maxTs = sensor_info[s].report_ts + (is_accel ? 1 : THRESHOLD) * period;
+ sensor_info[s].report_ts = (ts < maxTs ? ts : maxTs);
+ } else {
+ sensor_info[s].report_ts = ts;
+ }
+}
+
+static int integrate_device_report (int dev_num)