+ sensor[s].event_count = 0;
+ sensor[s].meta_data_pending = 0;
+
+ if (!check_state_change(s, enabled, from_virtual))
+ return;
+ if (enabled) {
+ /* Enable all the base sensors for this virtual one */
+ for (i = 0; i < sensor[s].base_count; i++) {
+ base = sensor[s].base[i];
+ sensor_activate(base, enabled, 1);
+ sensor[base].ref_count++;
+ }
+ return;
+ }
+
+ /* Sensor disabled, lower report available flag */
+ sensor[s].report_pending = 0;
+
+ for (i = 0; i < sensor[s].base_count; i++) {
+ base = sensor[s].base[i];
+ sensor_activate(base, enabled, 1);
+ sensor[base].ref_count--;
+ }
+
+}
+
+
+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 int setup_delay_sysfs (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;
+ int32_t min_delay_us = sensor_desc[s].minDelay;
+ max_delay_t max_delay_us = sensor_desc[s].maxDelay;
+ float min_supported_rate = max_delay_us ? 1000000.0/max_delay_us : 1;
+ float max_supported_rate =
+ min_delay_us && min_delay_us != -1 ? 1000000.0/min_delay_us : 0;
+ char freqs_buf[100];
+ char* cursor;
+ int n;
+ float sr;
+ 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 < min_supported_rate) {
+ ALOGV("Sampling rate %g too low for %s, using %g instead\n",
+ arb_sampling_rate, sensor[s].friendly_name,
+ min_supported_rate);
+
+ arb_sampling_rate = min_supported_rate;
+ }
+
+ if (max_supported_rate && arb_sampling_rate > max_supported_rate) {
+ ALOGV("Sampling rate %g too high for %s, using %g instead\n",
+ arb_sampling_rate, sensor[s].friendly_name, max_supported_rate);
+ arb_sampling_rate = max_supported_rate;
+ }
+
+ sensor[s].sampling_rate = arb_sampling_rate;
+
+ /* If we're dealing with a poll-mode sensor */
+ if (!sensor[s].num_channels) {
+ /* Wake up thread so the new sampling rate gets used */
+ pthread_cond_signal(&thread_release_cond[s]);
+ 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;
+ }
+
+ /* 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(s) &&
+ sensor[n].sampling_rate > arb_sampling_rate)
+ arb_sampling_rate = sensor[n].sampling_rate;
+
+ /* 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 to counter 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 (max_supported_rate &&
+ arb_sampling_rate > max_supported_rate) {
+ arb_sampling_rate = max_supported_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;
+}
+
+
+/*
+ * We go through all the virtual sensors of the base - and the base itself
+ * in order to recompute the maximum requested delay of the group and setup the base
+ * at that specific delay.
+ */
+static int arbitrate_bases (int s)
+{
+ int i, vidx;
+
+ float arbitrated_rate = 0;
+
+ if (sensor[s].directly_enabled)
+ arbitrated_rate = sensor[s].requested_rate;
+
+ for (i = 0; i < sensor_count; i++) {
+ for (vidx = 0; vidx < sensor[i].base_count; vidx++)
+ /* If we have a virtual sensor depending on this one - handle it */
+ if (sensor[i].base[vidx] == s &&
+ sensor[i].directly_enabled &&
+ sensor[i].requested_rate > arbitrated_rate)
+ arbitrated_rate = sensor[i].requested_rate;
+ }
+
+ return setup_delay_sysfs(s, arbitrated_rate);
+}
+
+
+/*
+ * Re-assesment for delays. We need to re-asses delays for all related groups
+ * of sensors everytime a sensor enables / disables / changes frequency.
+ */
+int arbitrate_delays (int s)
+{
+ int i;