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