+ sensor[s].acquisition_thread = -1;
+
+ /* Delete condition variable and mutex */
+ pthread_cond_destroy(&thread_release_cond[s]);
+ pthread_mutex_destroy(&thread_release_mutex[s]);
+}
+
+
+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[s].type != SENSOR_TYPE_ACCELEROMETER)
+ return 0;
+
+ if (sensor[s].sampling_rate < 25)
+ return 0;
+
+ return 1;
+}
+
+
+static void tentative_switch_trigger (int s)
+{
+ /*
+ * Under certain situations it may be beneficial to use an alternate trigger:
+ *
+ * - for applications using the accelerometer with high sampling rates, prefer the continuous trigger over the any-motion one, to avoid
+ * jumps related to motion thresholds
+ */
+
+ if (is_fast_accelerometer(s) && !(sensor[s].quirks & QUIRK_TERSE_DRIVER) && sensor[s].selected_trigger == sensor[s].motion_trigger_name)
+ setup_trigger(s, sensor[s].init_trigger_name);
+}
+
+
+static float get_group_max_sampling_rate (int s)
+{
+ /* Review the sampling rates of linked sensors and return the maximum */
+
+ int i, vi;
+
+ float arbitrated_rate = 0;
+
+ if (is_enabled(s))
+ arbitrated_rate = sensor[s].requested_rate;
+
+ /* If any of the currently active sensors built on top of this one need a higher sampling rate, switch to this rate */
+ for (i = 0; i < sensor_count; i++)
+ for (vi = 0; vi < sensor[i].base_count; vi++)
+ if (sensor[i].base[vi] == s && is_enabled(i) && sensor[i].requested_rate > arbitrated_rate) /* If sensor i depends on sensor s */
+ arbitrated_rate = sensor[i].requested_rate;
+
+ /* If any of the currently active sensors we rely on is using a higher sampling rate, switch to this rate */
+ for (vi = 0; vi < sensor[s].base_count; vi++) {
+ i = sensor[s].base[vi];
+ if (is_enabled(i) && sensor[i].requested_rate > arbitrated_rate)
+ arbitrated_rate = sensor[i].requested_rate;
+ }
+
+ return arbitrated_rate;
+}
+
+
+static int sensor_set_rate (int s, float requested_rate)
+{
+ /* Set the rate at which a specific sensor should report events. See Android sensors.h for indication on sensor trigger modes */
+
+ char sysfs_path[PATH_MAX];
+ char avail_sysfs_path[PATH_MAX];
+ int dev_num = sensor[s].dev_num;
+ int i = sensor[s].catalog_index;
+ const char *prefix = sensor_catalog[i].tag;
+ int per_sensor_sampling_rate;
+ int per_device_sampling_rate;
+ char freqs_buf[100];
+ char* cursor;
+ int n;
+ float sr;
+ float group_max_sampling_rate;
+ float cur_sampling_rate; /* Currently used sampling rate */
+ float arb_sampling_rate; /* Granted sampling rate after arbitration */
+
+ ALOGV("Sampling rate %g requested on sensor %d (%s)\n", requested_rate, s, sensor[s].friendly_name);
+
+ sensor[s].requested_rate = requested_rate;
+
+ arb_sampling_rate = requested_rate;
+
+ if (arb_sampling_rate < sensor[s].min_supported_rate) {
+ ALOGV("Sampling rate %g too low for %s, using %g instead\n", arb_sampling_rate, sensor[s].friendly_name, sensor[s].min_supported_rate);
+ arb_sampling_rate = sensor[s].min_supported_rate;
+ }
+
+ /* If one of the linked sensors uses a higher rate, adopt it */
+ group_max_sampling_rate = get_group_max_sampling_rate(s);
+
+ if (arb_sampling_rate < group_max_sampling_rate) {
+ ALOGV("Using %s sampling rate to %g too due to dependency\n", sensor[s].friendly_name, arb_sampling_rate);
+ arb_sampling_rate = group_max_sampling_rate;
+ }
+
+ if (sensor[s].max_supported_rate && arb_sampling_rate > sensor[s].max_supported_rate) {
+ ALOGV("Sampling rate %g too high for %s, using %g instead\n", arb_sampling_rate, sensor[s].friendly_name, sensor[s].max_supported_rate);
+ arb_sampling_rate = sensor[s].max_supported_rate;
+ }
+
+ sensor[s].sampling_rate = arb_sampling_rate;
+
+ /* If the sensor is virtual, we're done */
+ if (sensor[s].is_virtual)
+ return 0;
+
+ /* If we're dealing with a poll-mode sensor */
+ if (sensor[s].mode == MODE_POLL) {
+ if (is_enabled(s))
+ pthread_cond_signal(&thread_release_cond[s]); /* Wake up thread so the new sampling rate gets used */
+ return 0;
+ }
+
+ sprintf(sysfs_path, SENSOR_SAMPLING_PATH, dev_num, prefix);
+
+ if (sysfs_read_float(sysfs_path, &cur_sampling_rate) != -1) {
+ per_sensor_sampling_rate = 1;
+ per_device_sampling_rate = 0;
+ } else {
+ per_sensor_sampling_rate = 0;
+
+ sprintf(sysfs_path, DEVICE_SAMPLING_PATH, dev_num);
+
+ if (sysfs_read_float(sysfs_path, &cur_sampling_rate) != -1)
+ per_device_sampling_rate = 1;
+ else
+ per_device_sampling_rate = 0;
+ }
+
+ if (!per_sensor_sampling_rate && !per_device_sampling_rate) {
+ ALOGE("No way to adjust sampling rate on sensor %d\n", s);
+ return -ENOSYS;
+ }
+
+ /* Check if we have contraints on allowed sampling rates */
+
+ sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
+
+ if (sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) > 0) {
+ cursor = freqs_buf;
+
+ /* Decode allowed sampling rates string, ex: "10 20 50 100" */
+
+ /* While we're not at the end of the string */
+ while (*cursor && cursor[0]) {
+
+ /* Decode a single value */
+ sr = strtod(cursor, NULL);
+
+ /* If this matches the selected rate, we're happy. Have some tolerance for rounding errors and avoid needless jumps to higher rates */
+ if (fabs(arb_sampling_rate - sr) <= 0.001) {
+ arb_sampling_rate = sr;
+ break;
+ }
+
+ /*
+ * If we reached a higher value than the desired rate, adjust selected rate so it matches the first higher available one and
+ * stop parsing - this makes the assumption that rates are sorted by increasing value in the allowed frequencies string.
+ */
+ if (sr > arb_sampling_rate) {
+ arb_sampling_rate = sr;
+ break;
+ }
+
+ /* Skip digits */
+ while (cursor[0] && !isspace(cursor[0]))
+ cursor++;
+
+ /* Skip spaces */
+ while (cursor[0] && isspace(cursor[0]))
+ cursor++;
+ }
+ }
+
+ if (sensor[s].max_supported_rate &&
+ arb_sampling_rate > sensor[s].max_supported_rate) {
+ arb_sampling_rate = sensor[s].max_supported_rate;
+ }
+
+ /* Record the rate that was agreed upon with the sensor taken in isolation ; this avoid uncontrolled ripple effects between colocated sensor rates */
+ sensor[s].semi_arbitrated_rate = arb_sampling_rate;
+
+ /* Coordinate with others active sensors on the same device, if any */
+ if (per_device_sampling_rate)
+ for (n=0; n<sensor_count; n++)
+ if (n != s && sensor[n].dev_num == dev_num && sensor[n].num_channels && is_enabled(n) &&
+ sensor[n].semi_arbitrated_rate > arb_sampling_rate) {
+ ALOGV("Sampling rate shared between %s and %s, using %g instead of %g\n", sensor[s].friendly_name, sensor[n].friendly_name,
+ sensor[n].semi_arbitrated_rate, arb_sampling_rate);
+ arb_sampling_rate = sensor[n].semi_arbitrated_rate;
+ }
+
+ sensor[s].sampling_rate = arb_sampling_rate;
+
+ /* Update actual sampling rate field for this sensor and others which may be sharing the same sampling rate */
+ if (per_device_sampling_rate)
+ for (n=0; n<sensor_count; n++)
+ if (sensor[n].dev_num == dev_num && n != s && sensor[n].num_channels)
+ sensor[n].sampling_rate = arb_sampling_rate;
+
+ /* If the desired rate is already active we're all set */
+ if (arb_sampling_rate == cur_sampling_rate)
+ return 0;
+
+ ALOGI("Sensor %d (%s) sampling rate set to %g\n", s, sensor[s].friendly_name, arb_sampling_rate);
+
+ if (trig_sensors_per_dev[dev_num])
+ enable_buffer(dev_num, 0);
+
+ sysfs_write_float(sysfs_path, arb_sampling_rate);
+
+ /* Check if it makes sense to use an alternate trigger */
+ tentative_switch_trigger(s);
+
+ if (trig_sensors_per_dev[dev_num])
+ enable_buffer(dev_num, 1);
+
+ return 0;
+}
+
+
+static void reapply_sampling_rates (int s)
+{
+ /*
+ * The specified sensor was either enabled or disabled. Other sensors in the same group may have constraints related to this sensor
+ * sampling rate on their own sampling rate, so reevaluate them by retrying to use their requested sampling rate, rather than the one
+ * that ended up being used after arbitration.
+ */
+
+ int i, j, base;
+
+ if (sensor[s].is_virtual) {
+ /* Take care of downwards dependencies */
+ for (i=0; i<sensor[s].base_count; i++) {
+ base = sensor[s].base[i];
+ sensor_set_rate(base, sensor[base].requested_rate);
+ }
+ return;
+ }
+
+ /* Upwards too */
+ for (i=0; i<sensor_count; i++)
+ for (j=0; j<sensor[i].base_count; j++)
+ if (sensor[i].base[j] == s) /* If sensor i depends on sensor s */
+ sensor_set_rate(i, sensor[i].requested_rate);
+}
+
+
+static int sensor_activate_virtual (int s, int enabled, int from_virtual)
+{
+ int i, base;
+
+ sensor[s].event_count = 0;
+ sensor[s].meta_data_pending = 0;
+
+ if (!check_state_change(s, enabled, from_virtual))
+ return 0; /* The state of the sensor remains the same ; we're done */
+
+ if (enabled)
+ ALOGI("Enabling sensor %d (%s)\n", s, sensor[s].friendly_name);
+ else
+ ALOGI("Disabling sensor %d (%s)\n", s, sensor[s].friendly_name);
+
+ sensor[s].report_pending = 0;
+
+ for (i=0; i<sensor[s].base_count; i++) {
+
+ base = sensor[s].base[i];
+ sensor_activate(base, enabled, 1);
+
+ if (enabled)
+ sensor[base].ref_count++;
+ else
+ sensor[base].ref_count--;
+ }