1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android-base/file.h>
18 #include <android/hardware/sensors/2.0/types.h>
19 #include <gtest/gtest.h>
20 #include <sys/stat.h>
21 #include <fstream>
22 #include <iostream>
23 #include <map>
24 #include <sstream>
25
26 #include "iio_utils.h"
27
28 using ::android::hardware::sensors::V1_0::SensorType;
29 using android::hardware::sensors::V2_0::subhal::implementation::iio_device_data;
30 using android::hardware::sensors::V2_0::subhal::implementation::load_iio_devices;
31 using android::hardware::sensors::V2_0::subhal::implementation::sensors_supported_hal;
32
sensorFilter(iio_device_data * dev)33 static bool sensorFilter(iio_device_data* dev) {
34 static std::map<std::string, SensorType> KNOWN_SENSORS = {
35 {"scmi.iio.accel", SensorType::ACCELEROMETER},
36 };
37
38 if (!dev) return false;
39
40 const auto iter = KNOWN_SENSORS.find(dev->name);
41 if (iter == KNOWN_SENSORS.end()) return false;
42
43 dev->type = iter->second;
44 return true;
45 }
46
TEST(IIoUtilsTest,ScanEmptyDirectory)47 TEST(IIoUtilsTest, ScanEmptyDirectory) {
48 TemporaryDir td;
49 std::vector<iio_device_data> iio_devices;
50 const auto err = load_iio_devices(td.path, &iio_devices, sensorFilter);
51 ASSERT_EQ(0, err);
52 ASSERT_EQ(0, iio_devices.size());
53 }
54
concatPaths(const std::string & a,const std::string & b)55 static std::string concatPaths(const std::string& a, const std::string& b) {
56 std::stringstream ss;
57 ss << a << '/' << b;
58 return ss.str();
59 }
60
61 template <typename T>
writeFile(const std::string & path,const T & content,bool nl=true)62 static bool writeFile(const std::string& path, const T& content, bool nl = true) {
63 std::stringstream ss;
64 ss << content;
65
66 std::ofstream f;
67 f.open(path);
68 if (!f) return false;
69 f << ss.str();
70 if (nl) f << '\n';
71 f.close();
72 return true;
73 }
74
75 template <typename U>
writeFile(const std::string & path,const std::vector<U> & content,bool nl=true)76 static bool writeFile(const std::string& path, const std::vector<U>& content, bool nl = true) {
77 std::stringstream ss;
78 bool first = true;
79 for (const auto& item : content) {
80 if (!first) ss << ' ';
81 ss << item;
82 if (first) first = false;
83 }
84
85 return writeFile(path, ss.str(), nl);
86 }
87
writeAccelDevice(const std::string & td_path,const iio_device_data & dev)88 static bool writeAccelDevice(const std::string& td_path, const iio_device_data& dev) {
89 std::stringstream ss;
90 ss << concatPaths(td_path, "iio:device") << std::to_string(dev.iio_dev_num);
91 const std::string dev_path(ss.str());
92
93 int err = mkdir(dev_path.c_str(), 0777);
94 if (err != 0) return false;
95
96 if (!writeFile(concatPaths(dev_path, "name"), dev.name)) return false;
97 if (!writeFile(concatPaths(dev_path, "in_accel_x_scale"), dev.scale)) return false;
98 if (!writeFile(concatPaths(dev_path, "in_accel_y_scale"), dev.scale)) return false;
99 if (!writeFile(concatPaths(dev_path, "in_accel_z_scale"), dev.scale)) return false;
100 if (!writeFile(concatPaths(dev_path, "in_accel_raw_available"),
101 "[-78381056.000000000 2392.000000000 78378664.000000000]"))
102 return false;
103 if (!writeFile(concatPaths(dev_path, "in_accel_sampling_frequency_available"),
104 dev.sampling_freq_avl))
105 return false;
106
107 return true;
108 }
109
110 // sets up a new iio:device<id> device with default parameters for an accelerometer
createDefaultAccelerometerDevice(int id)111 static iio_device_data createDefaultAccelerometerDevice(int id) {
112 iio_device_data dev;
113 dev.type = SensorType::ACCELEROMETER;
114 dev.iio_dev_num = id;
115 dev.name = "scmi.iio.accel";
116 dev.sampling_freq_avl = {12.500000, 26.000364, 52.002080, 104.004160, 208.003993};
117 dev.resolution = 2392;
118 dev.scale = 0.000001000f;
119 dev.max_range = 78378664;
120
121 return dev;
122 }
123
TEST(IioUtilsTest,LoadValidSensor)124 TEST(IioUtilsTest, LoadValidSensor) {
125 TemporaryDir td;
126 const std::string td_path(td.path);
127 const auto dev_model = createDefaultAccelerometerDevice(0);
128 bool ok = writeAccelDevice(td_path, dev_model);
129 ASSERT_TRUE(ok);
130
131 std::vector<iio_device_data> iio_devices;
132 const auto err = load_iio_devices(td_path, &iio_devices, sensorFilter);
133 ASSERT_EQ(0, err);
134 ASSERT_EQ(1, iio_devices.size());
135
136 const auto& accel(iio_devices[0]);
137
138 EXPECT_EQ(SensorType::ACCELEROMETER, accel.type);
139 EXPECT_EQ("scmi.iio.accel", accel.name);
140 EXPECT_EQ(0, accel.iio_dev_num);
141
142 EXPECT_NEAR(dev_model.resolution, accel.resolution, 0.0002);
143 EXPECT_NEAR(dev_model.scale, accel.scale, 0.0002);
144 EXPECT_EQ(dev_model.max_range, accel.max_range);
145
146 EXPECT_EQ(dev_model.sampling_freq_avl.size(), accel.sampling_freq_avl.size());
147 for (size_t i = 0; i < dev_model.sampling_freq_avl.size(); ++i) {
148 if (i >= accel.sampling_freq_avl.size()) break;
149 EXPECT_NEAR(dev_model.sampling_freq_avl[i], accel.sampling_freq_avl[i], 0.0002);
150 }
151 }
152