• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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