• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/sensor.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 <gtest/gtest.h>
31 #include <sensors/convert.h>
32 
33 using ::android::frameworks::sensorservice::V1_0::ISensorManager;
34 using ::android::frameworks::sensorservice::V1_0::Result;
35 using ::android::hardware::sensors::V1_0::Event;
36 using ::android::hardware::sensors::V1_0::RateLevel;
37 using ::android::hardware::sensors::V1_0::SensorFlagBits;
38 using ::android::hardware::sensors::V1_0::SensorFlagShift;
39 using ::android::hardware::sensors::V1_0::SensorType;
40 using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
41 using ::android::hardware::Return;
42 using ::android::hardware::Void;
43 using ::android::hardware::hidl_memory;
44 using ::android::hidl::allocator::V1_0::IAllocator;
45 using ::android::sp;
46 
47 template <typename T>
isOk(const Return<T> & ret)48 static inline ::testing::AssertionResult isOk(const Return<T> &ret) {
49   return (ret.isOk()
50       ? ::testing::AssertionSuccess()
51       : ::testing::AssertionFailure()) << ret.description();
52 }
53 
54 template <>
55 __attribute__((__unused__))
isOk(const Return<Result> & ret)56 inline ::testing::AssertionResult isOk(const Return<Result> &ret) {
57   return ((ret.isOk() && ret == Result::OK)
58       ? ::testing::AssertionSuccess()
59       : ::testing::AssertionFailure())
60       << ret.description() << ", "
61       << (ret.isOk() ? toString(static_cast<Result>(ret)) : "");
62 }
63 
isOk(Result result)64 static inline ::testing::AssertionResult isOk(Result result) {
65   using ::android::frameworks::sensorservice::V1_0::toString;
66   return (result == Result::OK
67       ? ::testing::AssertionSuccess()
68       : ::testing::AssertionFailure()) << toString(result);
69 }
70 
71 template<typename I, typename F>
isIncreasing(I begin,I end,F getField)72 static ::testing::AssertionResult isIncreasing(I begin, I end, F getField) {
73   typename std::iterator_traits<I>::pointer lastValue = nullptr;
74   I iter;
75   size_t pos;
76   for (iter = begin, pos = 0; iter != end; ++iter, ++pos) {
77     if (iter == begin) {
78       lastValue = &(*iter);
79       continue;
80     }
81     if (getField(*iter) < getField(*lastValue)) {
82       return ::testing::AssertionFailure() << "Not an increasing sequence, pos = "
83           << pos << ", " << getField(*iter) << " < " << getField(*lastValue);
84     }
85   }
86   return ::testing::AssertionSuccess();
87 }
88 
89 #define EXPECT_OK(__ret__) EXPECT_TRUE(isOk(__ret__))
90 #define ASSERT_OK(__ret__) ASSERT_TRUE(isOk(__ret__))
91 
92 // The main test class for sensorservice HIDL HAL.
93 class SensorManagerTest : public ::testing::Test {
94  public:
SetUp()95   virtual void SetUp() override {
96     manager_ = ISensorManager::getService();
97     ASSERT_NE(manager_, nullptr);
98     ashmem_ = IAllocator::getService("ashmem");
99     ASSERT_NE(ashmem_, nullptr);
100   }
TearDown()101   virtual void TearDown() override {}
102 
103   sp<ISensorManager> manager_;
104   sp<IAllocator> ashmem_;
105 };
106 
107 // A class for test environment setup (kept since this file is a template).
108 class SensorManagerHidlEnvironment : public ::testing::Environment {
109  public:
SetUp()110   virtual void SetUp() {}
TearDown()111   virtual void TearDown() {}
112 };
113 
114 using map_region = std::unique_ptr<void, std::function<void(void*)>>;
115 
map(const hidl_memory & mem)116 map_region map(const hidl_memory &mem) {
117   if (mem.handle() == nullptr || mem.handle()->numFds != 1) {
118     return nullptr;
119   }
120   size_t size = mem.size();
121   void *buf = mmap(nullptr, size, PROT_READ, MAP_SHARED, mem.handle()->data[0], 0);
122   return map_region{buf, [size](void *localBuf) {
123     munmap(localBuf, size);
124   }};
125 }
126 
127 /*
128  * Ping! make sure the service is alive.
129  */
TEST_F(SensorManagerTest,Ping)130 TEST_F(SensorManagerTest, Ping) {
131   EXPECT_OK(manager_->ping());
132 }
133 
TEST_F(SensorManagerTest,List)134 TEST_F(SensorManagerTest, List) {
135   ASSERT_OK(manager_->getSensorList([] (__unused const auto &list, auto result) {
136     using ::android::hardware::sensors::V1_0::toString;
137     ASSERT_OK(result);
138     // Do something to the list of sensors.
139   }));
140 }
141 
TEST_F(SensorManagerTest,Ashmem)142 TEST_F(SensorManagerTest, Ashmem) {
143 
144   auto testOne = [this](uint64_t memSize, uint64_t intendedSize,
145         ISensorManager::createAshmemDirectChannel_cb callback) {
146     ASSERT_OK(ashmem_->allocate(memSize, [&](bool success, const auto &mem) {
147       ASSERT_TRUE(success);
148       ASSERT_NE(mem.handle(), nullptr);
149       ASSERT_OK(manager_->createAshmemDirectChannel(mem, intendedSize, callback));
150     }));
151   };
152 
153   testOne(16, 16, [](const auto &chan, Result result) {
154     EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when memory size is too small";
155     EXPECT_EQ(chan, nullptr);
156   });
157 
158   testOne(1024, 1024, [](const auto &chan, Result result) {
159     EXPECT_OK(result);
160     EXPECT_NE(chan, nullptr);
161   });
162 
163   testOne(1024, 2048, [](const auto &chan, Result result) {
164     EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when intended size is too big";
165     EXPECT_EQ(chan, nullptr);
166   });
167 
168   testOne(1024, 16, [](const auto &chan, Result result) {
169     EXPECT_EQ(result, Result::BAD_VALUE) << "unexpected result when intended size is too small";
170     EXPECT_EQ(chan, nullptr);
171   });
172 }
173 
parseEvents(uint8_t * buf,size_t memSize)174 static std::vector<Event> parseEvents(uint8_t *buf, size_t memSize) {
175   using O = SensorsEventFormatOffset;
176   using ::android::hardware::sensors::V1_0::implementation::convertFromSensorEvent;
177   size_t offset = 0;
178   int64_t lastCounter = -1;
179   std::vector<Event> events;
180   Event event;
181 
182   while(offset + (size_t)O::TOTAL_LENGTH <= memSize) {
183     uint8_t *start = buf + offset;
184     int64_t atomicCounter = *reinterpret_cast<uint32_t *>(start + (size_t)O::ATOMIC_COUNTER);
185     if (atomicCounter <= lastCounter) {
186       break;
187     }
188     int32_t size = *reinterpret_cast<int32_t *>(start + (size_t)O::SIZE_FIELD);
189     if (size != (size_t)O::TOTAL_LENGTH) {
190       // unknown error, events parsed may be wrong, remove all
191       events.clear();
192       break;
193     }
194 
195     convertFromSensorEvent(*reinterpret_cast<const sensors_event_t *>(start), &event);
196     events.push_back(event);
197     lastCounter = atomicCounter;
198     offset += (size_t)O::TOTAL_LENGTH;
199   }
200   return events;
201 }
202 
TEST_F(SensorManagerTest,Accelerometer)203 TEST_F(SensorManagerTest, Accelerometer) {
204   using std::literals::chrono_literals::operator""ms;
205   using ::android::hardware::sensors::V1_0::implementation::convertFromRateLevel;
206   Result getSensorResult;
207   int32_t handle;
208   ASSERT_OK(manager_->getDefaultSensor(SensorType::ACCELEROMETER, [&] (const auto &info, auto result) {
209     getSensorResult = result;
210     handle = info.sensorHandle;
211     if (result == Result::OK) {
212       ASSERT_TRUE(info.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM);
213 
214       int maxLevel = (info.flags & SensorFlagBits::MASK_DIRECT_REPORT)
215           >> (int)SensorFlagShift::DIRECT_REPORT;
216       ASSERT_TRUE(maxLevel >= convertFromRateLevel(RateLevel::FAST))
217           << "Accelerometer does not support fast report rate, test cannot proceed.";
218     }
219   }));
220   if (getSensorResult == Result::NOT_EXIST) {
221     LOG(WARNING) << "Cannot find accelerometer, skipped SensorManagerTest.Accelerometer";
222     return;
223   }
224   ASSERT_OK(getSensorResult);
225   const size_t memSize = (size_t)SensorsEventFormatOffset::TOTAL_LENGTH * 300;
226   ASSERT_OK(ashmem_->allocate(memSize, [&] (bool success, const auto &mem) {
227     ASSERT_TRUE(success);
228     map_region buf = map(mem);
229     ASSERT_NE(buf, nullptr);
230     ASSERT_OK(manager_->createAshmemDirectChannel(mem, memSize, [&](const auto &chan, Result result) {
231       ASSERT_OK(result);
232       ASSERT_NE(chan, nullptr);
233 
234       int32_t returnedToken;
235       ASSERT_OK(chan->configure(handle, RateLevel::FAST, [&](auto token, auto res) {
236         ASSERT_OK(res);
237         ASSERT_GT(token, 0);
238         returnedToken = token;
239       })); // ~200Hz
240       std::this_thread::sleep_for(500ms);
241       ASSERT_OK(chan->configure(handle, RateLevel::STOP, [](auto token, auto res) {
242         ASSERT_OK(res);
243         ASSERT_EQ(token, 0);
244       }));
245 
246       auto events = parseEvents(static_cast<uint8_t *>(buf.get()), memSize);
247 
248       EXPECT_TRUE(isIncreasing(events.begin(), events.end(), [](const auto &event) {
249         return event.timestamp;
250       })) << "timestamp is not monotonically increasing";
251       for (const auto &event : events) {
252         EXPECT_EQ(returnedToken, event.sensorHandle)
253             << "configure token and sensor handle don't match.";
254       }
255     }));
256   }));
257 }
258 
main(int argc,char ** argv)259 int main(int argc, char** argv) {
260   ::testing::AddGlobalTestEnvironment(new SensorManagerHidlEnvironment);
261   ::testing::InitGoogleTest(&argc, argv);
262   int status = RUN_ALL_TESTS();
263   LOG(INFO) << "Test result = " << status;
264   return status;
265 }
266