• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 "PowerHalControllerBenchmarks"
18 
19 #include <benchmark/benchmark.h>
20 #include <vibratorservice/VibratorHalController.h>
21 
22 using ::android::enum_range;
23 using ::android::hardware::vibrator::CompositeEffect;
24 using ::android::hardware::vibrator::CompositePrimitive;
25 using ::android::hardware::vibrator::Effect;
26 using ::android::hardware::vibrator::EffectStrength;
27 using ::benchmark::Counter;
28 using ::benchmark::Fixture;
29 using ::benchmark::kMicrosecond;
30 using ::benchmark::State;
31 using ::benchmark::internal::Benchmark;
32 
33 using namespace android;
34 using namespace std::chrono_literals;
35 
36 class VibratorBench : public Fixture {
37 public:
SetUp(State &)38     void SetUp(State& /*state*/) override { mController.init(); }
39 
TearDown(State & state)40     void TearDown(State& state) override { turnVibratorOff(state); }
41 
DefaultConfig(Benchmark * b)42     static void DefaultConfig(Benchmark* b) { b->Unit(kMicrosecond); }
43 
DefaultArgs(Benchmark *)44     static void DefaultArgs(Benchmark* /*b*/) {
45         // none
46     }
47 
48 protected:
49     vibrator::HalController mController;
50 
getOtherArg(const State & state,std::size_t index) const51     auto getOtherArg(const State& state, std::size_t index) const { return state.range(index + 0); }
52 
hasCapabilities(vibrator::Capabilities && query,State & state)53     bool hasCapabilities(vibrator::Capabilities&& query, State& state) {
54         auto result = mController.getInfo().capabilities;
55         if (result.isFailed()) {
56             state.SkipWithError(result.errorMessage());
57             return false;
58         }
59         if (!result.isOk()) {
60             return false;
61         }
62         return (result.value() & query) == query;
63     }
64 
turnVibratorOff(State & state)65     void turnVibratorOff(State& state) {
66         checkHalResult(halCall<void>(mController, [](auto hal) { return hal->off(); }), state);
67     }
68 
69     template <class R>
checkHalResult(const vibrator::HalResult<R> & result,State & state)70     bool checkHalResult(const vibrator::HalResult<R>& result, State& state) {
71         if (result.isFailed()) {
72             state.SkipWithError(result.errorMessage());
73             return false;
74         }
75         return true;
76     }
77 
78     template <class R>
halCall(vibrator::HalController & controller,const vibrator::HalFunction<vibrator::HalResult<R>> & halFn)79     vibrator::HalResult<R> halCall(vibrator::HalController& controller,
80                                    const vibrator::HalFunction<vibrator::HalResult<R>>& halFn) {
81         return controller.doWithRetry<R>(halFn, "benchmark");
82     }
83 };
84 
85 #define BENCHMARK_WRAPPER(fixt, test, code)                \
86     BENCHMARK_DEFINE_F(fixt, test)                         \
87     /* NOLINTNEXTLINE */                                   \
88     (State& state){code} BENCHMARK_REGISTER_F(fixt, test) \
89             ->Apply(fixt::DefaultConfig)                   \
90             ->Apply(fixt::DefaultArgs)
91 
92 BENCHMARK_WRAPPER(VibratorBench, init, {
93     for (auto _ : state) {
94         state.PauseTiming();
95         vibrator::HalController controller;
96         state.ResumeTiming();
97         controller.init();
98     }
99 });
100 
101 BENCHMARK_WRAPPER(VibratorBench, initCached, {
102     for (auto _ : state) {
103         mController.init();
104     }
105 });
106 
107 BENCHMARK_WRAPPER(VibratorBench, ping, {
108     for (auto _ : state) {
109         state.ResumeTiming();
__anon866670c60202(auto hal) 110         auto ret = halCall<void>(mController, [](auto hal) { return hal->ping(); });
111         state.PauseTiming();
112         checkHalResult(ret, state);
113     }
114 });
115 
116 BENCHMARK_WRAPPER(VibratorBench, tryReconnect, {
117     for (auto _ : state) {
118         mController.tryReconnect();
119     }
120 });
121 
122 BENCHMARK_WRAPPER(VibratorBench, on, {
123     auto duration = 60s;
__anon866670c60302() 124     auto callback = []() {};
125 
126     for (auto _ : state) {
127         state.ResumeTiming();
128         auto ret =
__anon866670c60402(auto hal) 129                 halCall<void>(mController, [&](auto hal) { return hal->on(duration, callback); });
130         state.PauseTiming();
131         if (checkHalResult(ret, state)) {
132             turnVibratorOff(state);
133         }
134     }
135 });
136 
137 BENCHMARK_WRAPPER(VibratorBench, off, {
138     auto duration = 60s;
__anon866670c60502() 139     auto callback = []() {};
140 
141     for (auto _ : state) {
142         state.PauseTiming();
143         auto ret =
__anon866670c60602(auto hal) 144                 halCall<void>(mController, [&](auto hal) { return hal->on(duration, callback); });
145         if (!checkHalResult(ret, state)) {
146             continue;
147         }
148         state.ResumeTiming();
149         turnVibratorOff(state);
150     }
151 });
152 
153 BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
154     if (!hasCapabilities(vibrator::Capabilities::AMPLITUDE_CONTROL, state)) {
155         return;
156     }
157 
158     auto duration = 60s;
__anon866670c60702() 159     auto callback = []() {};
160     auto amplitude = 1.0f;
161 
162     for (auto _ : state) {
163         state.PauseTiming();
164         vibrator::HalController controller;
165         controller.init();
166         auto result =
__anon866670c60802(auto hal) 167                 halCall<void>(controller, [&](auto hal) { return hal->on(duration, callback); });
168         if (!checkHalResult(result, state)) {
169             continue;
170         }
171         state.ResumeTiming();
172         auto ret =
__anon866670c60902(auto hal) 173                 halCall<void>(controller, [&](auto hal) { return hal->setAmplitude(amplitude); });
174         state.PauseTiming();
175         if (checkHalResult(ret, state)) {
176             turnVibratorOff(state);
177         }
178     }
179 });
180 
181 BENCHMARK_WRAPPER(VibratorBench, setAmplitudeCached, {
182     if (!hasCapabilities(vibrator::Capabilities::AMPLITUDE_CONTROL, state)) {
183         return;
184     }
185 
186     auto duration = 6000s;
__anon866670c60a02() 187     auto callback = []() {};
188     auto amplitude = 1.0f;
189 
190     auto onResult =
__anon866670c60b02(auto hal) 191             halCall<void>(mController, [&](auto hal) { return hal->on(duration, callback); });
192     checkHalResult(onResult, state);
193 
194     for (auto _ : state) {
195         auto ret =
__anon866670c60c02(auto hal) 196                 halCall<void>(mController, [&](auto hal) { return hal->setAmplitude(amplitude); });
197         checkHalResult(ret, state);
198     }
199 });
200 
201 BENCHMARK_WRAPPER(VibratorBench, setExternalControl, {
202     if (!hasCapabilities(vibrator::Capabilities::EXTERNAL_CONTROL, state)) {
203         return;
204     }
205 
206     for (auto _ : state) {
207         state.PauseTiming();
208         vibrator::HalController controller;
209         controller.init();
210         state.ResumeTiming();
211         auto ret =
__anon866670c60d02(auto hal) 212                 halCall<void>(controller, [](auto hal) { return hal->setExternalControl(true); });
213         state.PauseTiming();
214         if (checkHalResult(ret, state)) {
215             auto result = halCall<void>(controller,
__anon866670c60e02(auto hal) 216                                         [](auto hal) { return hal->setExternalControl(false); });
217             checkHalResult(result, state);
218         }
219     }
220 });
221 
222 BENCHMARK_WRAPPER(VibratorBench, setExternalControlCached, {
223     if (!hasCapabilities(vibrator::Capabilities::EXTERNAL_CONTROL, state)) {
224         return;
225     }
226 
227     for (auto _ : state) {
228         state.ResumeTiming();
229         auto result =
__anon866670c60f02(auto hal) 230                 halCall<void>(mController, [](auto hal) { return hal->setExternalControl(true); });
231         state.PauseTiming();
232         if (checkHalResult(result, state)) {
233             auto ret = halCall<void>(mController,
__anon866670c61002(auto hal) 234                                      [](auto hal) { return hal->setExternalControl(false); });
235             checkHalResult(ret, state);
236         }
237     }
238 });
239 
240 BENCHMARK_WRAPPER(VibratorBench, setExternalAmplitudeCached, {
241     if (!hasCapabilities(vibrator::Capabilities::EXTERNAL_AMPLITUDE_CONTROL, state)) {
242         return;
243     }
244 
245     auto amplitude = 1.0f;
246 
247     auto onResult =
__anon866670c61102(auto hal) 248             halCall<void>(mController, [](auto hal) { return hal->setExternalControl(true); });
249     checkHalResult(onResult, state);
250 
251     for (auto _ : state) {
252         auto ret =
__anon866670c61202(auto hal) 253                 halCall<void>(mController, [&](auto hal) { return hal->setAmplitude(amplitude); });
254         checkHalResult(ret, state);
255     }
256 
257     auto offResult =
__anon866670c61302(auto hal) 258             halCall<void>(mController, [](auto hal) { return hal->setExternalControl(false); });
259     checkHalResult(offResult, state);
260 });
261 
262 BENCHMARK_WRAPPER(VibratorBench, getInfo, {
263     for (auto _ : state) {
264         state.PauseTiming();
265         vibrator::HalController controller;
266         controller.init();
267         state.ResumeTiming();
268         auto result = controller.getInfo();
269         checkHalResult(result.capabilities, state);
270         checkHalResult(result.supportedEffects, state);
271         checkHalResult(result.supportedPrimitives, state);
272         checkHalResult(result.primitiveDurations, state);
273         checkHalResult(result.resonantFrequency, state);
274         checkHalResult(result.qFactor, state);
275     }
276 });
277 
278 BENCHMARK_WRAPPER(VibratorBench, getInfoCached, {
279     // First call to cache values.
280     mController.getInfo();
281 
282     for (auto _ : state) {
283         auto result = mController.getInfo();
284         checkHalResult(result.capabilities, state);
285         checkHalResult(result.supportedEffects, state);
286         checkHalResult(result.supportedPrimitives, state);
287         checkHalResult(result.primitiveDurations, state);
288         checkHalResult(result.resonantFrequency, state);
289         checkHalResult(result.qFactor, state);
290     }
291 });
292 
293 class VibratorEffectsBench : public VibratorBench {
294 public:
DefaultArgs(Benchmark * b)295     static void DefaultArgs(Benchmark* b) {
296         vibrator::HalController controller;
297         auto effectsResult = controller.getInfo().supportedEffects;
298         if (!effectsResult.isOk()) {
299             return;
300         }
301 
302         std::vector<Effect> supported = effectsResult.value();
303         b->ArgNames({"Effect", "Strength"});
304 
305         if (supported.empty()) {
306             b->Args({static_cast<long>(-1), static_cast<long>(-1)});
307             return;
308         }
309 
310         for (const auto& effect : enum_range<Effect>()) {
311             if (std::find(supported.begin(), supported.end(), effect) == supported.end()) {
312                 continue;
313             }
314             for (const auto& strength : enum_range<EffectStrength>()) {
315                 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
316             }
317         }
318     }
319 
320 protected:
hasArgs(const State & state) const321     bool hasArgs(const State& state) const { return this->getOtherArg(state, 0) >= 0; }
322 
getEffect(const State & state) const323     auto getEffect(const State& state) const {
324         return static_cast<Effect>(this->getOtherArg(state, 0));
325     }
326 
getStrength(const State & state) const327     auto getStrength(const State& state) const {
328         return static_cast<EffectStrength>(this->getOtherArg(state, 1));
329     }
330 };
331 
332 BENCHMARK_WRAPPER(VibratorEffectsBench, alwaysOnEnable, {
333     if (!hasCapabilities(vibrator::Capabilities::ALWAYS_ON_CONTROL, state)) {
334         return;
335     }
336     if (!hasArgs(state)) {
337         return;
338     }
339 
340     int32_t id = 1;
341     auto effect = getEffect(state);
342     auto strength = getStrength(state);
343 
344     for (auto _ : state) {
345         state.ResumeTiming();
__anon866670c61402(auto hal) 346         auto ret = halCall<void>(mController, [&](auto hal) {
347             return hal->alwaysOnEnable(id, effect, strength);
348         });
349         state.PauseTiming();
350         if (checkHalResult(ret, state)) {
351             auto disableResult =
__anon866670c61502(auto hal) 352                     halCall<void>(mController, [&](auto hal) { return hal->alwaysOnDisable(id); });
353             checkHalResult(disableResult, state);
354         }
355     }
356 });
357 
358 BENCHMARK_WRAPPER(VibratorEffectsBench, alwaysOnDisable, {
359     if (!hasCapabilities(vibrator::Capabilities::ALWAYS_ON_CONTROL, state)) {
360         return;
361     }
362     if (!hasArgs(state)) {
363         return;
364     }
365 
366     int32_t id = 1;
367     auto effect = getEffect(state);
368     auto strength = getStrength(state);
369 
370     for (auto _ : state) {
371         state.PauseTiming();
__anon866670c61602(auto hal) 372         auto enableResult = halCall<void>(mController, [&](auto hal) {
373             return hal->alwaysOnEnable(id, effect, strength);
374         });
375         if (!checkHalResult(enableResult, state)) {
376             continue;
377         }
378         state.ResumeTiming();
379         auto disableResult =
__anon866670c61702(auto hal) 380                 halCall<void>(mController, [&](auto hal) { return hal->alwaysOnDisable(id); });
381         checkHalResult(disableResult, state);
382     }
383 });
384 
385 BENCHMARK_WRAPPER(VibratorEffectsBench, performEffect, {
386     if (!hasArgs(state)) {
387         return;
388     }
389 
390     auto effect = getEffect(state);
391     auto strength = getStrength(state);
__anon866670c61802() 392     auto callback = []() {};
393 
394     for (auto _ : state) {
395         state.ResumeTiming();
__anon866670c61902(auto hal) 396         auto ret = halCall<std::chrono::milliseconds>(mController, [&](auto hal) {
397             return hal->performEffect(effect, strength, callback);
398         });
399         state.PauseTiming();
400         if (checkHalResult(ret, state)) {
401             turnVibratorOff(state);
402         }
403     }
404 });
405 
406 class VibratorPrimitivesBench : public VibratorBench {
407 public:
DefaultArgs(Benchmark * b)408     static void DefaultArgs(Benchmark* b) {
409         vibrator::HalController controller;
410         auto primitivesResult = controller.getInfo().supportedPrimitives;
411         if (!primitivesResult.isOk()) {
412             return;
413         }
414 
415         std::vector<CompositePrimitive> supported = primitivesResult.value();
416         b->ArgNames({"Primitive"});
417 
418         if (supported.empty()) {
419             b->Args({static_cast<long>(-1)});
420             return;
421         }
422 
423         for (const auto& primitive : enum_range<CompositePrimitive>()) {
424             if (std::find(supported.begin(), supported.end(), primitive) == supported.end()) {
425                 continue;
426             }
427             if (primitive == CompositePrimitive::NOOP) {
428                 continue;
429             }
430             b->Args({static_cast<long>(primitive)});
431         }
432     }
433 
434 protected:
hasArgs(const State & state) const435     bool hasArgs(const State& state) const { return this->getOtherArg(state, 0) >= 0; }
436 
getPrimitive(const State & state) const437     auto getPrimitive(const State& state) const {
438         return static_cast<CompositePrimitive>(this->getOtherArg(state, 0));
439     }
440 };
441 
442 BENCHMARK_WRAPPER(VibratorPrimitivesBench, performComposedEffect, {
443     if (!hasCapabilities(vibrator::Capabilities::COMPOSE_EFFECTS, state)) {
444         return;
445     }
446     if (!hasArgs(state)) {
447         return;
448     }
449 
450     CompositeEffect effect;
451     effect.primitive = getPrimitive(state);
452     effect.scale = 1.0f;
453     effect.delayMs = static_cast<int32_t>(0);
454 
455     std::vector<CompositeEffect> effects;
456     effects.push_back(effect);
__anon866670c61a02() 457     auto callback = []() {};
458 
459     for (auto _ : state) {
460         state.ResumeTiming();
__anon866670c61b02(auto hal) 461         auto ret = halCall<std::chrono::milliseconds>(mController, [&](auto hal) {
462             return hal->performComposedEffect(effects, callback);
463         });
464         state.PauseTiming();
465         if (checkHalResult(ret, state)) {
466             turnVibratorOff(state);
467         }
468     }
469 });
470 
471 BENCHMARK_MAIN();