Merge "Factor the client/server Library Out" into rvc-qpr-dev
diff --git a/hal/sensors/2.0/Android.bp b/hal/sensors/2.0/Android.bp
index 0ed62a1..e30e632 100644
--- a/hal/sensors/2.0/Android.bp
+++ b/hal/sensors/2.0/Android.bp
@@ -53,6 +53,23 @@
}
cc_test_host {
+ name: "android.hardware.sensors@2.0-Google-IIO-Subhal_test",
+ srcs: [
+ "iio_utils.cpp",
+ "tests/IioUtilsTest.cpp",
+ ],
+ static_libs: [
+ "libgtest",
+ "android.hardware.sensors@1.0",
+ "android.hardware.sensors@2.0",
+ ],
+ shared_libs: [
+ "libbase",
+ "liblog",
+ ],
+}
+
+cc_test_host {
name: "android.hardware.sensors@2.0-Google-IIO-Subhal_test-MultiPoll",
srcs: [
"MultiPoll.cpp",
@@ -68,3 +85,4 @@
"liblog",
],
}
+
diff --git a/hal/sensors/2.0/Sensor.cpp b/hal/sensors/2.0/Sensor.cpp
index a5338ad..1d2ea80 100644
--- a/hal/sensors/2.0/Sensor.cpp
+++ b/hal/sensors/2.0/Sensor.cpp
@@ -456,10 +456,9 @@
std::string buffer_path;
mSensorInfo.flags |= SensorFlagBits::CONTINUOUS_MODE;
mSensorInfo.name = data.name;
- mSensorInfo.resolution = data.resolution;
+ mSensorInfo.resolution = data.resolution * data.scale;
mSensorInfo.maxRange = data.max_range * data.scale;
- mSensorInfo.power =
- (data.power_microwatts / 1000.f) / SENSOR_VOLTAGE_DEFAULT; // converting uW to mA
+ mSensorInfo.power = 0;
mIioData = data;
setOrientation(config);
status_t ret = setAdditionalInfoFrames(config);
diff --git a/hal/sensors/2.0/SensorsSubHal.cpp b/hal/sensors/2.0/SensorsSubHal.cpp
index 4d80d9f..4a615af 100644
--- a/hal/sensors/2.0/SensorsSubHal.cpp
+++ b/hal/sensors/2.0/SensorsSubHal.cpp
@@ -42,9 +42,6 @@
using ::sensor::hal::configuration::V1_0::Sensor;
using ::sensor::hal::configuration::V1_0::SensorHalConfiguration;
-#define SENSOR_SUPPORTED(SENSOR_NAME, SENSOR_TYPE) \
- { .name = SENSOR_NAME, .type = SENSOR_TYPE, }
-
#define SENSOR_XML_CONFIG_FILE_NAME "sensor_hal_configuration.xml"
static const char* gSensorConfigLocationList[] = {"/odm/etc/sensors/", "/vendor/etc/sensors/"};
static const int gSensorConfigLocationListSize =
@@ -52,11 +49,6 @@
#define MODULE_NAME "android.hardware.sensors@2.0-Google-IIO-Subhal"
-static const std::vector<sensors_supported_hal> sensors_supported = {
- SENSOR_SUPPORTED("scmi.iio.accel", SensorType::ACCELEROMETER),
- SENSOR_SUPPORTED("scmi.iio.gyro", SensorType::GYROSCOPE),
-};
-
static std::optional<std::vector<Sensor>> readSensorsConfigFromXml() {
for (int i = 0; i < gSensorConfigLocationListSize; i++) {
const auto sensor_config_file =
@@ -86,11 +78,31 @@
return std::nullopt;
}
+static bool isSensorSupported(iio_device_data* sensor) {
+#define SENSOR_SUPPORTED(SENSOR_NAME, SENSOR_TYPE) \
+ { .name = SENSOR_NAME, .type = SENSOR_TYPE, }
+ static const std::vector<sensors_supported_hal> supported_sensors = {
+ SENSOR_SUPPORTED("scmi.iio.accel", SensorType::ACCELEROMETER),
+ SENSOR_SUPPORTED("scmi.iio.gyro", SensorType::GYROSCOPE),
+ };
+#undef SENSOR_SUPPORTED
+
+ if (!sensor) return false;
+
+ auto iter = std::find_if(
+ supported_sensors.begin(), supported_sensors.end(),
+ [&sensor](const auto& candidate) -> bool { return candidate.name == sensor->name; });
+ if (iter == supported_sensors.end()) return false;
+
+ sensor->type = iter->type;
+ return true;
+}
+
SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {
int err;
std::vector<iio_device_data> iio_devices;
const auto sensors_config_list = readSensorsConfigFromXml();
- err = load_iio_devices(&iio_devices, sensors_supported);
+ err = load_iio_devices(DEFAULT_IIO_DIR, &iio_devices, isSensorSupported);
if (err == 0) {
for (auto& iio_device : iio_devices) {
err = scan_elements(iio_device.sysfspath, &iio_device);
diff --git a/hal/sensors/2.0/iio_utils.cpp b/hal/sensors/2.0/iio_utils.cpp
index abd5d3c..84360b2 100644
--- a/hal/sensors/2.0/iio_utils.cpp
+++ b/hal/sensors/2.0/iio_utils.cpp
@@ -29,15 +29,13 @@
#include <memory>
static const char* IIO_DEVICE_BASE = "iio:device";
-static const char* DEVICE_IIO_DIR = "/sys/bus/iio/devices/";
static const char* IIO_SCAN_ELEMENTS_EN = "_en";
static const char* IIO_SFA_FILENAME = "sampling_frequency_available";
static const char* IIO_SCALE_FILENAME = "_scale";
static const char* IIO_SAMPLING_FREQUENCY = "_sampling_frequency";
static const char* IIO_BUFFER_ENABLE = "buffer/enable";
-static const char* IIO_POWER_FILENAME = "sensor_power";
-static const char* IIO_MAX_RANGE_FILENAME = "sensor_max_range";
-static const char* IIO_RESOLUTION_FILENAME = "sensor_resolution";
+static const char* IIO_NAME_FILENAME = "name";
+static const char* IIO_RANGE_AVAIL_FILENAME = "raw_available";
namespace android {
namespace hardware {
@@ -46,6 +44,8 @@
namespace subhal {
namespace implementation {
+const char* DEFAULT_IIO_DIR = "/sys/bus/iio/devices/";
+
using DirPtr = std::unique_ptr<DIR, decltype(&closedir)>;
using FilePtr = std::unique_ptr<FILE, decltype(&fclose)>;
@@ -126,18 +126,10 @@
return sysfs_read_val(file, "%hhu\n", val);
}
-static int sysfs_read_uint(const std::string& file, unsigned int* val) {
- return sysfs_read_val(file, "%u\n", val);
-}
-
static int sysfs_read_float(const std::string& file, float* val) {
return sysfs_read_val(file, "%f\n", val);
}
-static int sysfs_read_int64(const std::string& file, int64_t* val) {
- return sysfs_read_val(file, "%lld\n", val);
-}
-
static int sysfs_read_str(const std::string& file, std::string* str) {
std::ifstream infile(file);
if (!infile.is_open()) return -EINVAL;
@@ -170,30 +162,64 @@
int ret = 0;
char* rest;
std::string line;
+ DirPtr dp(nullptr, closedir);
+ const struct dirent* ent;
- const std::string filename = device_dir + "/" + IIO_SFA_FILENAME;
-
- ret = sysfs_read_str(filename, &line);
- if (ret < 0) return ret;
- char* pch = strtok_r(const_cast<char*>(line.c_str()), " ,", &rest);
- while (pch != nullptr) {
- sfa->push_back(atof(pch));
- pch = strtok_r(nullptr, " ,", &rest);
+ ret = sysfs_opendir(device_dir, &dp);
+ if (ret) return ret;
+ while (ent = readdir(dp.get()), ent != nullptr) {
+ if (str_has_suffix(ent->d_name, IIO_SFA_FILENAME)) {
+ std::string filename = device_dir;
+ filename += "/";
+ filename += ent->d_name;
+ ret = sysfs_read_str(filename, &line);
+ if (ret < 0) return ret;
+ char* pch = strtok_r(const_cast<char*>(line.c_str()), " ,", &rest);
+ while (pch != nullptr) {
+ sfa->push_back(atof(pch));
+ pch = strtok_r(nullptr, " ,", &rest);
+ }
+ }
}
return ret < 0 ? ret : 0;
}
-static int get_sensor_power(const std::string& device_dir, unsigned int* power) {
- const std::string filename = device_dir + "/" + IIO_POWER_FILENAME;
+static int get_sensor_range(const std::string& device_dir, float* resolution, int64_t* max_range) {
+ int ret = 0;
+ char* rest;
+ std::string line;
+ DirPtr dp(nullptr, closedir);
+ const struct dirent* ent;
- return sysfs_read_uint(filename, power);
+ ret = sysfs_opendir(device_dir, &dp);
+ if (ret) return ret;
+ while (ent = readdir(dp.get()), ent != nullptr) {
+ if (str_has_suffix(ent->d_name, IIO_RANGE_AVAIL_FILENAME)) {
+ std::string filename = device_dir;
+ filename += "/";
+ filename += ent->d_name;
+
+ ret = sysfs_read_str(filename, &line);
+ if (ret < 0) return ret;
+ char* pch = strtok_r(const_cast<char*>(line.c_str()), " ", &rest);
+ std::vector<std::string> range_avail;
+ while (pch != nullptr) {
+ range_avail.push_back(pch);
+ pch = strtok_r(nullptr, " ", &rest);
+ }
+ *resolution = atof(range_avail[1].c_str());
+ *max_range = atoll(range_avail[2].c_str());
+ }
+ }
+
+ return ret < 0 ? ret : 0;
}
-static int get_sensor_max_range(const std::string& device_dir, int64_t* max_range) {
- const std::string filename = device_dir + "/" + IIO_MAX_RANGE_FILENAME;
+static int get_sensor_name(const std::string& device_dir, std::string* name) {
+ const std::string filename = device_dir + "/" + IIO_NAME_FILENAME;
- return sysfs_read_int64(filename, max_range);
+ return sysfs_read_str(filename, name);
}
int set_sampling_frequency(const std::string& device_dir, const double frequency) {
@@ -234,54 +260,35 @@
return err;
}
-static int get_sensor_resolution(const std::string& device_dir, float* resolution) {
- const std::string filename = device_dir + "/" + IIO_RESOLUTION_FILENAME;
-
- return sysfs_read_float(filename, resolution);
-}
-
-static bool is_supported_sensor(const std::string& path,
- const std::vector<sensors_supported_hal>& supported_sensors,
- std::string* name, sensors_supported_hal* sensor) {
- std::string name_file = path + "/name";
- std::ifstream iio_file(name_file.c_str());
- if (!iio_file) return false;
- std::string iio_name;
- std::getline(iio_file, iio_name);
- auto iter = std::find_if(
- supported_sensors.begin(), supported_sensors.end(),
- [&iio_name](const auto& candidate) -> bool { return candidate.name == iio_name; });
- if (iter == supported_sensors.end()) return false;
- *sensor = *iter;
- *name = iio_name;
- return true;
-}
-
-int load_iio_devices(std::vector<iio_device_data>* iio_data,
- const std::vector<sensors_supported_hal>& supported_sensors) {
+int load_iio_devices(std::string iio_dir, std::vector<iio_device_data>* iio_data,
+ DeviceFilterFunction filter) {
DirPtr dp(nullptr, closedir);
const struct dirent* ent;
int err;
+ if (!iio_dir.empty() && iio_dir.back() != '/') iio_dir += '/';
+
std::ifstream iio_file;
const auto iio_base_len = strlen(IIO_DEVICE_BASE);
- err = sysfs_opendir(DEVICE_IIO_DIR, &dp);
+ err = sysfs_opendir(iio_dir, &dp);
if (err) return err;
while (ent = readdir(dp.get()), ent != nullptr) {
if (!str_has_prefix(ent->d_name, IIO_DEVICE_BASE)) continue;
- std::string path_device = DEVICE_IIO_DIR;
+ std::string path_device = iio_dir;
path_device += ent->d_name;
- sensors_supported_hal sensor_match;
- std::string iio_name;
- if (!is_supported_sensor(path_device, supported_sensors, &iio_name, &sensor_match))
- continue;
- ALOGI("found sensor %s at path %s", iio_name.c_str(), path_device.c_str());
iio_device_data iio_dev_data;
- iio_dev_data.name = iio_name;
- iio_dev_data.type = sensor_match.type;
- iio_dev_data.sysfspath.append(path_device, 0, strlen(DEVICE_IIO_DIR) + strlen(ent->d_name));
+ iio_dev_data.sysfspath.append(path_device, 0, iio_dir.size() + strlen(ent->d_name));
+ err = get_sensor_name(iio_dev_data.sysfspath, &iio_dev_data.name);
+ if (err) {
+ ALOGE("get_sensor_name for %s returned error %d", path_device.c_str(), err);
+ continue;
+ }
+
+ if (!filter(&iio_dev_data)) continue;
+
+ ALOGI("found sensor %s at path %s", iio_dev_data.name.c_str(), path_device.c_str());
err = get_sampling_frequency_available(iio_dev_data.sysfspath,
&iio_dev_data.sampling_freq_avl);
if (err) {
@@ -296,19 +303,10 @@
ALOGE("get_sensor_scale for %s returned error %d", path_device.c_str(), err);
continue;
}
- err = get_sensor_power(iio_dev_data.sysfspath, &iio_dev_data.power_microwatts);
+ err = get_sensor_range(iio_dev_data.sysfspath, &iio_dev_data.resolution,
+ &iio_dev_data.max_range);
if (err) {
- ALOGE("get_sensor_power for %s returned error %d", path_device.c_str(), err);
- continue;
- }
- err = get_sensor_max_range(iio_dev_data.sysfspath, &iio_dev_data.max_range);
- if (err) {
- ALOGE("get_sensor_max_range for %s returned error %d", path_device.c_str(), err);
- continue;
- }
- err = get_sensor_resolution(iio_dev_data.sysfspath, &iio_dev_data.resolution);
- if (err) {
- ALOGE("get_sensor_resolution for %s returned error %d", path_device.c_str(), err);
+ ALOGE("get_sensor_range for %s returned error %d", path_device.c_str(), err);
continue;
}
diff --git a/hal/sensors/2.0/iio_utils.h b/hal/sensors/2.0/iio_utils.h
index 1beb5d4..a84d369 100644
--- a/hal/sensors/2.0/iio_utils.h
+++ b/hal/sensors/2.0/iio_utils.h
@@ -22,6 +22,7 @@
#include <linux/types.h>
#include <stdint.h>
#include <sys/ioctl.h>
+#include <functional>
namespace android {
namespace hardware {
@@ -32,6 +33,8 @@
using ::android::hardware::sensors::V1_0::SensorType;
+extern const char* DEFAULT_IIO_DIR;
+
static constexpr auto DEFAULT_IIO_BUFFER_LEN = 2;
static constexpr auto DISABLE_CHANNEL = 0;
static constexpr auto ENABLE_CHANNEL = 1;
@@ -60,12 +63,13 @@
std::vector<iio_info_channel> channelInfo;
std::vector<double> sampling_freq_avl;
uint8_t iio_dev_num;
- unsigned int power_microwatts;
int64_t max_range;
};
-int load_iio_devices(std::vector<iio_device_data>* iio_data,
- const std::vector<sensors_supported_hal>& supported_sensors);
+using DeviceFilterFunction = std::function<bool(iio_device_data*)>;
+
+int load_iio_devices(std::string iio_dir, std::vector<iio_device_data>* iio_data,
+ DeviceFilterFunction filter);
int scan_elements(const std::string& device_dir, struct iio_device_data* iio_data);
int enable_sensor(const std::string& name, const bool flag);
int set_sampling_frequency(const std::string& name, const double frequency);
diff --git a/hal/sensors/2.0/tests/IioUtilsTest.cpp b/hal/sensors/2.0/tests/IioUtilsTest.cpp
new file mode 100644
index 0000000..034a6b8
--- /dev/null
+++ b/hal/sensors/2.0/tests/IioUtilsTest.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android/hardware/sensors/2.0/types.h>
+#include <gtest/gtest.h>
+#include <sys/stat.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+#include <sstream>
+
+#include "iio_utils.h"
+
+using ::android::hardware::sensors::V1_0::SensorType;
+using android::hardware::sensors::V2_0::subhal::implementation::iio_device_data;
+using android::hardware::sensors::V2_0::subhal::implementation::load_iio_devices;
+using android::hardware::sensors::V2_0::subhal::implementation::sensors_supported_hal;
+
+static bool sensorFilter(iio_device_data* dev) {
+ static std::map<std::string, SensorType> KNOWN_SENSORS = {
+ {"scmi.iio.accel", SensorType::ACCELEROMETER},
+ };
+
+ if (!dev) return false;
+
+ const auto iter = KNOWN_SENSORS.find(dev->name);
+ if (iter == KNOWN_SENSORS.end()) return false;
+
+ dev->type = iter->second;
+ return true;
+}
+
+TEST(IIoUtilsTest, ScanEmptyDirectory) {
+ TemporaryDir td;
+ std::vector<iio_device_data> iio_devices;
+ const auto err = load_iio_devices(td.path, &iio_devices, sensorFilter);
+ ASSERT_EQ(0, err);
+ ASSERT_EQ(0, iio_devices.size());
+}
+
+static std::string concatPaths(const std::string& a, const std::string& b) {
+ std::stringstream ss;
+ ss << a << '/' << b;
+ return ss.str();
+}
+
+template <typename T>
+static bool writeFile(const std::string& path, const T& content, bool nl = true) {
+ std::stringstream ss;
+ ss << content;
+
+ std::ofstream f;
+ f.open(path);
+ if (!f) return false;
+ f << ss.str();
+ if (nl) f << '\n';
+ f.close();
+ return true;
+}
+
+template <typename U>
+static bool writeFile(const std::string& path, const std::vector<U>& content, bool nl = true) {
+ std::stringstream ss;
+ bool first = true;
+ for (const auto& item : content) {
+ if (!first) ss << ' ';
+ ss << item;
+ if (first) first = false;
+ }
+
+ return writeFile(path, ss.str(), nl);
+}
+
+static bool writeAccelDevice(const std::string& td_path, const iio_device_data& dev) {
+ std::stringstream ss;
+ ss << concatPaths(td_path, "iio:device") << std::to_string(dev.iio_dev_num);
+ const std::string dev_path(ss.str());
+
+ int err = mkdir(dev_path.c_str(), 0777);
+ if (err != 0) return false;
+
+ if (!writeFile(concatPaths(dev_path, "name"), dev.name)) return false;
+ if (!writeFile(concatPaths(dev_path, "in_accel_x_scale"), dev.scale)) return false;
+ if (!writeFile(concatPaths(dev_path, "in_accel_y_scale"), dev.scale)) return false;
+ if (!writeFile(concatPaths(dev_path, "in_accel_z_scale"), dev.scale)) return false;
+ if (!writeFile(concatPaths(dev_path, "in_accel_raw_available"),
+ "[-78381056.000000000 2392.000000000 78378664.000000000]"))
+ return false;
+ if (!writeFile(concatPaths(dev_path, "in_accel_sampling_frequency_available"),
+ dev.sampling_freq_avl))
+ return false;
+
+ return true;
+}
+
+// sets up a new iio:device<id> device with default parameters for an accelerometer
+static iio_device_data createDefaultAccelerometerDevice(int id) {
+ iio_device_data dev;
+ dev.type = SensorType::ACCELEROMETER;
+ dev.iio_dev_num = id;
+ dev.name = "scmi.iio.accel";
+ dev.sampling_freq_avl = {12.500000, 26.000364, 52.002080, 104.004160, 208.003993};
+ dev.resolution = 2392;
+ dev.scale = 0.000001000f;
+ dev.max_range = 78378664;
+
+ return dev;
+}
+
+TEST(IioUtilsTest, LoadValidSensor) {
+ TemporaryDir td;
+ const std::string td_path(td.path);
+ const auto dev_model = createDefaultAccelerometerDevice(0);
+ bool ok = writeAccelDevice(td_path, dev_model);
+ ASSERT_TRUE(ok);
+
+ std::vector<iio_device_data> iio_devices;
+ const auto err = load_iio_devices(td_path, &iio_devices, sensorFilter);
+ ASSERT_EQ(0, err);
+ ASSERT_EQ(1, iio_devices.size());
+
+ const auto& accel(iio_devices[0]);
+
+ EXPECT_EQ(SensorType::ACCELEROMETER, accel.type);
+ EXPECT_EQ("scmi.iio.accel", accel.name);
+ EXPECT_EQ(0, accel.iio_dev_num);
+
+ EXPECT_NEAR(dev_model.resolution, accel.resolution, 0.0002);
+ EXPECT_NEAR(dev_model.scale, accel.scale, 0.0002);
+ EXPECT_EQ(dev_model.max_range, accel.max_range);
+
+ EXPECT_EQ(dev_model.sampling_freq_avl.size(), accel.sampling_freq_avl.size());
+ for (size_t i = 0; i < dev_model.sampling_freq_avl.size(); ++i) {
+ if (i >= accel.sampling_freq_avl.size()) break;
+ EXPECT_NEAR(dev_model.sampling_freq_avl[i], accel.sampling_freq_avl[i], 0.0002);
+ }
+}