1 /*
2 * Copyright (C) 2022 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_aidl_hal_test"
18 #include <aidl/Gtest.h>
19 #include <aidl/Vintf.h>
20 #include <aidl/android/frameworks/sensorservice/ISensorManager.h>
21 #include <aidl/android/frameworks/sensorservice/BnEventQueueCallback.h>
22 #include <aidl/android/frameworks/sensorservice/IEventQueue.h>
23 #include <aidl/android/hardware/graphics/common/BufferUsage.h>
24 #include <aidl/android/hardware/graphics/common/PixelFormat.h>
25 #include <aidl/sensors/convert.h>
26 #include <android-base/logging.h>
27 #include <android-base/result.h>
28 #include <android/binder_manager.h>
29 #include <android/sensor.h>
30 #include <binder/IServiceManager.h>
31 #include <cutils/ashmem.h>
32 #include <gmock/gmock.h>
33 #include <gtest/gtest.h>
34 #include <sys/mman.h>
35 #include <ui/GraphicBufferAllocator.h>
36 #include <ui/GraphicBuffer.h>
37 #include <chrono>
38 #include <thread>
39
40 using aidl::android::frameworks::sensorservice::BnEventQueueCallback;
41 using aidl::android::frameworks::sensorservice::IEventQueue;
42 using aidl::android::frameworks::sensorservice::IDirectReportChannel;
43 using aidl::android::frameworks::sensorservice::ISensorManager;
44 using aidl::android::hardware::common::Ashmem;
45 using aidl::android::hardware::graphics::common::BufferUsage;
46 using aidl::android::hardware::graphics::common::PixelFormat;
47 using aidl::android::hardware::sensors::Event;
48 using aidl::android::hardware::sensors::ISensors;
49 using aidl::android::hardware::sensors::SensorInfo;
50 using aidl::android::hardware::sensors::SensorType;
51 using ::android::sp;
52 using ndk::ScopedAStatus;
53 using ndk::ScopedFileDescriptor;
54 using ::testing::Contains;
55
56 class EventCallback : public BnEventQueueCallback {
57 public:
EventCallback()58 EventCallback() {}
~EventCallback()59 ~EventCallback() {}
onEvent(const Event & e)60 ndk::ScopedAStatus onEvent(const Event &e) override {
61 std::unique_lock<std::mutex> lck(mtx);
62 if (e.sensorType == SensorType::ACCELEROMETER && !eventReceived) {
63 eventReceived = true;
64 cv.notify_all();
65 }
66 return ndk::ScopedAStatus::ok();
67 }
waitForEvent()68 void waitForEvent() {
69 std::unique_lock<std::mutex> lck(mtx);
70 cv.wait_for(lck, std::chrono::seconds(10), [this](){ return eventReceived; });
71 EXPECT_TRUE(eventReceived) << "wait event timeout";
72 }
73 private:
74 std::mutex mtx;
75 std::condition_variable_any cv;
76 bool eventReceived = false;
77 };
78
isOk(const ScopedAStatus & status)79 static inline ::testing::AssertionResult isOk(const ScopedAStatus& status) {
80 return status.isOk() ? ::testing::AssertionSuccess()
81 : ::testing::AssertionFailure() << status.getDescription();
82 }
83
84 template <typename I, typename F>
isIncreasing(I begin,I end,F getField)85 static ::testing::AssertionResult isIncreasing(I begin, I end, F getField) {
86 typename std::iterator_traits<I>::pointer lastValue = nullptr;
87 I iter;
88 size_t pos;
89 for (iter = begin, pos = 0; iter != end; ++iter, ++pos) {
90 if (iter == begin) {
91 lastValue = &(*iter);
92 continue;
93 }
94 if (getField(*iter) < getField(*lastValue)) {
95 return ::testing::AssertionFailure()
96 << "Not an increasing sequence, pos = " << pos << ", " << getField(*iter)
97 << " < " << getField(*lastValue);
98 }
99 }
100 return ::testing::AssertionSuccess();
101 }
102
103 #define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
104 #define ASSERT_OK(__ret__) ASSERT_TRUE(isOk(__ret__))
105
106 class SensorManagerTest : public ::testing::TestWithParam<std::string> {
107 public:
SetUp()108 virtual void SetUp() override {
109 manager_ = ISensorManager::fromBinder(
110 ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
111 ASSERT_NE(manager_, nullptr);
112 }
113
114 // Call getSensorList. Filter result based on |pred| if it is provided.
GetSensorList(std::vector<SensorInfo> * out_info,const std::function<bool (SensorInfo)> & pred=nullptr)115 ndk::ScopedAStatus GetSensorList(std::vector<SensorInfo>* out_info,
116 const std::function<bool(SensorInfo)>& pred = nullptr) {
117 ndk::ScopedAStatus ret = manager_->getSensorList(out_info);
118 if (ret.isOk() && pred) {
119 out_info->erase(std::remove_if(out_info->begin(), out_info->end(),
120 [pred](const auto& el) { return !pred(el); }),
121 out_info->end());
122 }
123 return ret;
124 }
125
126 std::shared_ptr<ISensorManager> manager_;
127 };
128
129 using map_region = std::unique_ptr<void, std::function<void(void*)>>;
130
map(const Ashmem & mem)131 map_region map(const Ashmem& mem) {
132 if (mem.fd.get() == -1) {
133 return nullptr;
134 }
135 size_t size = mem.size;
136 void* buf = mmap(nullptr, size, PROT_READ, MAP_SHARED, mem.fd.get(), 0);
137 return map_region{buf, [size](void* localBuf) { munmap(localBuf, size); }};
138 }
139
TEST_P(SensorManagerTest,List)140 TEST_P(SensorManagerTest, List) {
141 std::vector<SensorInfo> sensorList;
142 auto res = GetSensorList(&sensorList);
143 ASSERT_OK(res) << res.getDescription();
144 }
145
TEST_P(SensorManagerTest,Ashmem)146 TEST_P(SensorManagerTest, Ashmem) {
147 std::vector<SensorInfo> sensorList;
148 auto res = GetSensorList(&sensorList, [](const auto& info) {
149 return info.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM;
150 });
151 ASSERT_OK(res);
152 if (sensorList.empty()) {
153 GTEST_SKIP() << "DIRECT_CHANNEL_ASHMEM not supported by HAL, skipping";
154 }
155 auto testOne = [this](int64_t memSize, int64_t intendedSize,
156 void (*callback)(const std::shared_ptr<IDirectReportChannel>&,
157 const ScopedAStatus&)) {
158 auto fd = ashmem_create_region("sensorservice_vts", memSize);
159 ASSERT_TRUE(fd != -1);
160 Ashmem ashmem = {ScopedFileDescriptor(fd), memSize};
161 std::shared_ptr<IDirectReportChannel> chan;
162 ScopedAStatus res = manager_->createAshmemDirectChannel(ashmem, intendedSize, &chan);
163 callback(chan, res);
164 };
165
166 testOne(16, 16, [](const auto& chan, const ScopedAStatus& result) {
167 EXPECT_EQ(result.getServiceSpecificError(), ISensorManager::RESULT_BAD_VALUE)
168 << "unexpected result when memory size is too small";
169 EXPECT_EQ(chan, nullptr);
170 });
171
172 testOne(1024, 1024, [](const auto& chan, const ScopedAStatus& result) {
173 EXPECT_OK(result);
174 EXPECT_NE(chan, nullptr);
175 });
176
177 testOne(1024, 2048, [](const auto& chan, const ScopedAStatus& result) {
178 EXPECT_EQ(result.getServiceSpecificError(), ISensorManager::RESULT_BAD_VALUE)
179 << "unexpected result when intended size is too big";
180 EXPECT_EQ(chan, nullptr);
181 });
182
183 testOne(1024, 16, [](const auto& chan, const ScopedAStatus& result) {
184 EXPECT_EQ(result.getServiceSpecificError(), ISensorManager::RESULT_BAD_VALUE)
185 << "unexpected result when intended size is too small";
186 EXPECT_EQ(chan, nullptr);
187 });
188 }
189
parseEvents(uint8_t * buf,size_t memSize)190 static std::vector<Event> parseEvents(uint8_t* buf, size_t memSize) {
191 using android::hardware::sensors::implementation::convertFromSensorEvent;
192 size_t offset = 0;
193 int64_t lastCounter = -1;
194 std::vector<Event> events;
195 Event event;
196
197 while (offset + (size_t)ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH <= memSize) {
198 uint8_t* start = buf + offset;
199 int64_t atomicCounter = *reinterpret_cast<uint32_t*>(
200 start + (size_t)ISensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_ATOMIC_COUNTER);
201 if (atomicCounter <= lastCounter) {
202 break;
203 }
204 int32_t size = *reinterpret_cast<int32_t*>(
205 start + (size_t)ISensors::DIRECT_REPORT_SENSOR_EVENT_OFFSET_SIZE_FIELD);
206 if (size != (size_t)ISensors::DIRECT_REPORT_SENSOR_EVENT_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)ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH;
216 }
217 return events;
218 }
219
TEST_P(SensorManagerTest,GetDefaultAccelerometer)220 TEST_P(SensorManagerTest, GetDefaultAccelerometer) {
221 std::vector<SensorInfo> sensorList;
222 auto res = GetSensorList(
223 &sensorList, [](const auto& info) { return info.type == SensorType::ACCELEROMETER; });
224 ASSERT_OK(res);
225
226 SensorInfo info;
227 res = manager_->getDefaultSensor(SensorType::ACCELEROMETER, &info);
228 if (sensorList.empty()) {
229 ASSERT_EQ(ISensorManager::RESULT_NOT_EXIST, res.getServiceSpecificError());
230 } else {
231 ASSERT_OK(res);
232 ASSERT_THAT(sensorList, Contains(info));
233 }
234 }
235
TEST_P(SensorManagerTest,Accelerometer)236 TEST_P(SensorManagerTest, Accelerometer) {
237 using std::literals::chrono_literals::operator""ms;
238
239 std::vector<SensorInfo> sensorList;
240 auto res = GetSensorList(&sensorList, [](const auto& info) {
241 if (info.type != SensorType::ACCELEROMETER) return false;
242 if (!(info.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_ASHMEM)) return false;
243 int maxLevel = (info.flags & SensorInfo::SENSOR_FLAG_BITS_MASK_DIRECT_REPORT) >>
244 SensorInfo::SENSOR_FLAG_SHIFT_DIRECT_REPORT;
245 return maxLevel >= static_cast<int>(ISensors::RateLevel::FAST);
246 });
247 ASSERT_OK(res);
248
249 if (sensorList.empty()) {
250 GTEST_SKIP()
251 << "No accelerometer sensor that supports DIRECT_CHANNEL_ASHMEM and fast report "
252 << "rate, skipping";
253 }
254
255 for (const auto& info : sensorList) {
256 int32_t handle = info.sensorHandle;
257 const size_t memSize = (size_t)ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH * 300;
258 auto fd = ashmem_create_region("sensorservice_vts", memSize);
259 ASSERT_TRUE(fd != -1);
260 Ashmem mem = {ScopedFileDescriptor(fd), memSize};
261 map_region buf = map(mem);
262 ASSERT_NE(buf, nullptr);
263 std::shared_ptr<IDirectReportChannel> chan;
264 auto res = manager_->createAshmemDirectChannel(mem, memSize, &chan);
265 ASSERT_OK(res);
266 ASSERT_NE(chan, nullptr);
267
268 int32_t token = 0;
269 ASSERT_OK(chan->configure(handle, ISensors::RateLevel::FAST, &token));
270 ASSERT_GT(token, 0);
271 std::this_thread::sleep_for(500ms);
272 int32_t zeroToken = 0;
273 ASSERT_OK(chan->configure(handle, ISensors::RateLevel::STOP, &zeroToken));
274 ASSERT_OK(res);
275 ASSERT_EQ(zeroToken, 0);
276
277 auto events = parseEvents(static_cast<uint8_t*>(buf.get()), memSize);
278
279 EXPECT_TRUE(isIncreasing(events.begin(), events.end(), [](const auto& event) {
280 return event.timestamp;
281 })) << "timestamp is not monotonically increasing";
282 for (const auto& event : events) {
283 EXPECT_EQ(token, event.sensorHandle)
284 << "configure token and sensor handle don't match.";
285 }
286 }
287 }
288
TEST_P(SensorManagerTest,DISABLED_CreateGrallocDirectChannel)289 TEST_P(SensorManagerTest, DISABLED_CreateGrallocDirectChannel) {
290 std::vector<SensorInfo> sensorList;
291 auto res = GetSensorList(&sensorList, [](const auto& info) {
292 return info.flags & SensorInfo::SENSOR_FLAG_BITS_DIRECT_CHANNEL_GRALLOC;
293 });
294 ASSERT_OK(res);
295 if (sensorList.empty()) {
296 GTEST_SKIP() << "DIRECT_CHANNEL_GRALLOC not supported by HAL, skipping";
297 }
298 static constexpr uint64_t kBufferUsage =
299 static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA) |
300 static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN) |
301 static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY);
302 uint32_t stride = 0;
303 buffer_handle_t bufferHandle;
304 android::status_t status = android::GraphicBufferAllocator::get().allocate(
305 ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH, 1,
306 static_cast<int>(PixelFormat::BLOB), 1, kBufferUsage, &bufferHandle, &stride,
307 "sensorservice_vts");
308 ASSERT_TRUE(status == android::OK) << "failed to allocate memory";
309
310 std::shared_ptr<IDirectReportChannel> chan;
311 res = manager_->createGrallocDirectChannel(ScopedFileDescriptor(bufferHandle->data[0]),
312 ISensors::DIRECT_REPORT_SENSOR_EVENT_TOTAL_LENGTH, &chan);
313 EXPECT_OK(res);
314 ASSERT_NE(chan, nullptr);
315 }
316
TEST_P(SensorManagerTest,DISABLED_EnableAndDisableSensor)317 TEST_P(SensorManagerTest, DISABLED_EnableAndDisableSensor) {
318 std::vector<SensorInfo> sensorList;
319 auto res = GetSensorList(
320 &sensorList, [](const auto& info) { return info.type == SensorType::ACCELEROMETER; });
321 ASSERT_OK(res);
322
323 SensorInfo info;
324 res = manager_->getDefaultSensor(SensorType::ACCELEROMETER, &info);
325 if (sensorList.empty()) {
326 GTEST_SKIP() << "No accelerometer sensor, skipping";
327 } else {
328 ASSERT_OK(res);
329 ASSERT_THAT(sensorList, Contains(info));
330 }
331 std::shared_ptr<EventCallback> mSensorEventCallback =
332 ndk::SharedRefBase::make<EventCallback>();
333 std::shared_ptr<IEventQueue> mSensorEventQueue;
334 ASSERT_OK(manager_->createEventQueue(mSensorEventCallback, &mSensorEventQueue));
335 ASSERT_OK(mSensorEventQueue->enableSensor(info.sensorHandle, info.minDelayUs, 0));
336 mSensorEventCallback->waitForEvent();
337 ASSERT_OK(mSensorEventQueue->disableSensor(info.sensorHandle));
338 }
339
340 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SensorManagerTest);
341 INSTANTIATE_TEST_SUITE_P(
342 PerInstance, SensorManagerTest,
343 testing::ValuesIn(android::getAidlHalInstanceNames(ISensorManager::descriptor)),
344 android::PrintInstanceNameToString);
345