1 /*
2 * Copyright (C) 2016 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 #define LOG_TAG "sensor_manager_hidl_hal_test"
18 #include <android-base/logging.h>
19
20 #include <sys/mman.h>
21
22 #include <chrono>
23 #include <thread>
24
25 #include <android-base/result.h>
26 #include <android/frameworks/sensorservice/1.0/ISensorManager.h>
27 #include <android/frameworks/sensorservice/1.0/types.h>
28 #include <android/hardware/sensors/1.0/types.h>
29 #include <android/hidl/allocator/1.0/IAllocator.h>
30 #include <android/sensor.h>
31 #include <gmock/gmock.h>
32 #include <gtest/gtest.h>
33 #include <hidl/GtestPrinter.h>
34 #include <hidl/ServiceManagement.h>
35 #include <sensors/convert.h>
36
37 using ::android::sp;
38 using ::android::frameworks::sensorservice::V1_0::ISensorManager;
39 using ::android::frameworks::sensorservice::V1_0::Result;
40 using ::android::hardware::hidl_memory;
41 using ::android::hardware::Return;
42 using ::android::hardware::Void;
43 using ::android::hardware::sensors::V1_0::Event;
44 using ::android::hardware::sensors::V1_0::RateLevel;
45 using ::android::hardware::sensors::V1_0::SensorFlagBits;
46 using ::android::hardware::sensors::V1_0::SensorFlagShift;
47 using ::android::hardware::sensors::V1_0::SensorInfo;
48 using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
49 using ::android::hardware::sensors::V1_0::SensorType;
50 using ::android::hardware::sensors::V1_0::toString;
51 using ::android::hidl::allocator::V1_0::IAllocator;
52 using ::testing::Contains;
53
54 template <typename T>
isOk(const Return<T> & ret)55 static inline ::testing::AssertionResult isOk(const Return<T> &ret) {
56 return (ret.isOk()
57 ? ::testing::AssertionSuccess()
58 : ::testing::AssertionFailure()) << ret.description();
59 }
60
61 template <>
62 __attribute__((__unused__))
isOk(const Return<Result> & ret)63 inline ::testing::AssertionResult isOk(const Return<Result> &ret) {
64 return ((ret.isOk() && ret == Result::OK)
65 ? ::testing::AssertionSuccess()
66 : ::testing::AssertionFailure())
67 << ret.description() << ", "
68 << (ret.isOk() ? toString(static_cast<Result>(ret)) : "");
69 }
70
isOk(Result result)71 static inline ::testing::AssertionResult isOk(Result result) {
72 using ::android::frameworks::sensorservice::V1_0::toString;
73 return (result == Result::OK
74 ? ::testing::AssertionSuccess()
75 : ::testing::AssertionFailure()) << toString(result);
76 }
77
78 template<typename I, typename F>
isIncreasing(I begin,I end,F getField)79 static ::testing::AssertionResult isIncreasing(I begin, I end, F getField) {
80 typename std::iterator_traits<I>::pointer lastValue = nullptr;
81 I iter;
82 size_t pos;
83 for (iter = begin, pos = 0; iter != end; ++iter, ++pos) {
84 if (iter == begin) {
85 lastValue = &(*iter);
86 continue;
87 }
88 if (getField(*iter) < getField(*lastValue)) {
89 return ::testing::AssertionFailure() << "Not an increasing sequence, pos = "
90 << pos << ", " << getField(*iter) << " < " << getField(*lastValue);
91 }
92 }
93 return ::testing::AssertionSuccess();
94 }
95
96 #define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
97 #define ASSERT_OK(__ret__) ASSERT_TRUE(isOk(__ret__))
98
99 class SensorManagerTest : public ::testing::TestWithParam<std::string> {
100 public:
SetUp()101 virtual void SetUp() override {
102 manager_ = ISensorManager::getService(GetParam());
103 ASSERT_NE(manager_, nullptr);
104 ashmem_ = IAllocator::getService("ashmem");
105 ASSERT_NE(ashmem_, nullptr);
106 }
107
108 // Call getSensorList. Filter result based on |pred| if it is provided.
GetSensorList(const std::function<bool (SensorInfo)> & pred=nullptr)109 android::base::Result<std::vector<SensorInfo>> GetSensorList(
110 const std::function<bool(SensorInfo)> &pred = nullptr) {
111 Result out_result = Result::INVALID_OPERATION;
112 std::vector<SensorInfo> out_info;
113
114 auto ret = manager_->getSensorList([&](const auto &list, auto result) {
115 out_result = result;
116 if (result == Result::OK) {
117 for (const auto &info : list) {
118 if (!pred || pred(info)) {
119 out_info.push_back(info);
120 }
121 }
122 }
123 });
124 if (!ret.isOk()) {
125 return android::base::Error() << ret.description();
126 }
127 if (out_result != Result::OK) {
128 return android::base::Error() << "getSensorList returns " << toString(out_result);
129 }
130 return out_info;
131 }
132
133 sp<ISensorManager> manager_;
134 sp<IAllocator> ashmem_;
135 };
136
137 using map_region = std::unique_ptr<void, std::function<void(void*)>>;
138
map(const hidl_memory & mem)139 map_region map(const hidl_memory &mem) {
140 if (mem.handle() == nullptr || mem.handle()->numFds != 1) {
141 return nullptr;
142 }
143 size_t size = mem.size();
144 void *buf = mmap(nullptr, size, PROT_READ, MAP_SHARED, mem.handle()->data[0], 0);
145 return map_region{buf, [size](void *localBuf) {
146 munmap(localBuf, size);
147 }};
148 }
149
TEST_P(SensorManagerTest,List)150 TEST_P(SensorManagerTest, List) {
151 ASSERT_RESULT_OK(GetSensorList());
152 }
153
TEST_P(SensorManagerTest,Ashmem)154 TEST_P(SensorManagerTest, Ashmem) {
155 auto ashmem_sensors = GetSensorList(
156 [](const auto &info) { return info.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM; });
157 ASSERT_RESULT_OK(ashmem_sensors);
158 if (ashmem_sensors->empty()) {
159 GTEST_SKIP() << "DIRECT_CHANNEL_ASHMEM not supported by HAL, skipping";
160 }
161 auto testOne = [this](uint64_t memSize, uint64_t intendedSize,
162 ISensorManager::createAshmemDirectChannel_cb callback) {
163 ASSERT_OK(ashmem_->allocate(memSize, [&](bool success, const auto &mem) {
164 ASSERT_TRUE(success);
165 ASSERT_NE(mem.handle(), nullptr);
166 ASSERT_OK(manager_->createAshmemDirectChannel(mem, intendedSize, callback));
167 }));
168 };
169
170 testOne(16, 16, [](const auto &chan, Result result) {
171 EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when memory size is too small";
172 EXPECT_EQ(chan, nullptr);
173 });
174
175 testOne(1024, 1024, [](const auto &chan, Result result) {
176 EXPECT_OK(result);
177 EXPECT_NE(chan, nullptr);
178 });
179
180 testOne(1024, 2048, [](const auto &chan, Result result) {
181 EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when intended size is too big";
182 EXPECT_EQ(chan, nullptr);
183 });
184
185 testOne(1024, 16, [](const auto &chan, Result result) {
186 EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when intended size is too small";
187 EXPECT_EQ(chan, nullptr);
188 });
189 }
190
parseEvents(uint8_t * buf,size_t memSize)191 static std::vector<Event> parseEvents(uint8_t *buf, size_t memSize) {
192 using O = SensorsEventFormatOffset;
193 using ::android::hardware::sensors::V1_0::implementation::convertFromSensorEvent;
194 size_t offset = 0;
195 int64_t lastCounter = -1;
196 std::vector<Event> events;
197 Event event;
198
199 while(offset + (size_t)O::TOTAL_LENGTH <= memSize) {
200 uint8_t *start = buf + offset;
201 int64_t atomicCounter = *reinterpret_cast<uint32_t *>(start + (size_t)O::ATOMIC_COUNTER);
202 if (atomicCounter <= lastCounter) {
203 break;
204 }
205 int32_t size = *reinterpret_cast<int32_t *>(start + (size_t)O::SIZE_FIELD);
206 if (size != (size_t)O::TOTAL_LENGTH) {
207 // unknown error, events parsed may be wrong, remove all
208 events.clear();
209 break;
210 }
211
212 convertFromSensorEvent(*reinterpret_cast<const sensors_event_t *>(start), &event);
213 events.push_back(event);
214 lastCounter = atomicCounter;
215 offset += (size_t)O::TOTAL_LENGTH;
216 }
217 return events;
218 }
219
TEST_P(SensorManagerTest,GetDefaultAccelerometer)220 TEST_P(SensorManagerTest, GetDefaultAccelerometer) {
221 auto accelerometer_ashmem_sensors =
222 GetSensorList([](const auto &info) { return info.type == SensorType::ACCELEROMETER; });
223 ASSERT_RESULT_OK(accelerometer_ashmem_sensors);
224
225 ASSERT_OK(
226 manager_->getDefaultSensor(SensorType::ACCELEROMETER, [&](const auto &info, auto result) {
227 if (accelerometer_ashmem_sensors->empty()) {
228 ASSERT_EQ(Result::NOT_EXIST, result);
229 } else {
230 ASSERT_OK(result);
231 ASSERT_THAT(*accelerometer_ashmem_sensors, Contains(info));
232 }
233 }));
234 }
235
TEST_P(SensorManagerTest,Accelerometer)236 TEST_P(SensorManagerTest, Accelerometer) {
237 using std::literals::chrono_literals::operator""ms;
238 using ::android::hardware::sensors::V1_0::implementation::convertFromRateLevel;
239
240 auto accelerometer_ashmem_sensors = GetSensorList([](const auto &info) {
241 if (info.type != SensorType::ACCELEROMETER) return false;
242 if (!(info.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM)) return false;
243 int maxLevel =
244 (info.flags & SensorFlagBits::MASK_DIRECT_REPORT) >> (int)SensorFlagShift::DIRECT_REPORT;
245 return maxLevel >= convertFromRateLevel(RateLevel::FAST);
246 });
247 ASSERT_RESULT_OK(accelerometer_ashmem_sensors);
248
249 if (accelerometer_ashmem_sensors->empty()) {
250 GTEST_SKIP() << "No accelerometer sensor that supports DIRECT_CHANNEL_ASHMEM and fast report "
251 << "rate, skipping";
252 }
253
254 for (const auto &info : *accelerometer_ashmem_sensors) {
255 int32_t handle = info.sensorHandle;
256 const size_t memSize = (size_t)SensorsEventFormatOffset::TOTAL_LENGTH * 300;
257 ASSERT_OK(ashmem_->allocate(memSize, [&](bool success, const auto &mem) {
258 ASSERT_TRUE(success);
259 map_region buf = map(mem);
260 ASSERT_NE(buf, nullptr);
261 ASSERT_OK(
262 manager_->createAshmemDirectChannel(mem, memSize, [&](const auto &chan, Result result) {
263 ASSERT_OK(result);
264 ASSERT_NE(chan, nullptr);
265
266 int32_t returnedToken;
267 ASSERT_OK(chan->configure(handle, RateLevel::FAST, [&](auto token, auto res) {
268 ASSERT_OK(res);
269 ASSERT_GT(token, 0);
270 returnedToken = token;
271 })); // ~200Hz
272 std::this_thread::sleep_for(500ms);
273 ASSERT_OK(chan->configure(handle, RateLevel::STOP, [](auto token, auto res) {
274 ASSERT_OK(res);
275 ASSERT_EQ(token, 0);
276 }));
277
278 auto events = parseEvents(static_cast<uint8_t *>(buf.get()), memSize);
279
280 EXPECT_TRUE(isIncreasing(events.begin(), events.end(), [](const auto &event) {
281 return event.timestamp;
282 })) << "timestamp is not monotonically increasing";
283 for (const auto &event : events) {
284 EXPECT_EQ(returnedToken, event.sensorHandle)
285 << "configure token and sensor handle don't match.";
286 }
287 }));
288 }));
289 }
290 }
291
292 INSTANTIATE_TEST_SUITE_P(
293 PerInstance, SensorManagerTest,
294 testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISensorManager::descriptor)),
295 android::hardware::PrintInstanceNameToString);
296