1 /* * Copyright (C) 2019 The Android Open Source Project *
2  * Licensed under the Apache License, Version 2.0 (the "License");
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  *      http://www.apache.org/licenses/LICENSE-2.0
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  * See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 #include "benchmark/benchmark.h"
16 
17 #include <android-base/file.h>
18 #include <cutils/fs.h>
19 
20 #include "Hardware.h"
21 #include "Stats.h"
22 #include "Vibrator.h"
23 
24 namespace aidl {
25 namespace android {
26 namespace hardware {
27 namespace vibrator {
28 
29 class VibratorBench : public benchmark::Fixture {
30   private:
31     static constexpr const char *FILE_NAMES[]{
32             "device/f0_stored",
33             "device/redc_stored",
34             "device/q_stored",
35             "activate",
36             "duration",
37             "state",
38             "device/cp_trigger_duration",
39             "device/cp_trigger_index",
40             "device/cp_trigger_queue",
41             "device/cp_dig_scale",
42             "device/dig_scale",
43             "device/asp_enable",
44             "device/gpio1_fall_index",
45             "device/gpio1_fall_dig_scale",
46             "device/gpio1_rise_index",
47             "device/gpio1_rise_dig_scale",
48             "device/vibe_state",
49             "device/num_waves",
50     };
51 
52   public:
SetUp(::benchmark::State &)53     void SetUp(::benchmark::State & /*state*/) override {
54         auto prefix = std::filesystem::path(mFilesDir.path) / "";
55         const std::map<const std::string, const std::string> content{
56                 {"duration", std::to_string((uint32_t)std::rand() ?: 1)},
57                 {"device/asp_enable", std::to_string(0)},
58                 {"device/cp_trigger_duration", std::to_string(0)},
59                 {"device/num_waves", std::to_string(10)},
60                 {"device/vibe_state", std::to_string(0)},
61         };
62 
63         setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true);
64 
65         for (auto n : FILE_NAMES) {
66             const auto it = content.find(n);
67             const auto name = std::filesystem::path(n);
68             const auto path = std::filesystem::path(mFilesDir.path) / name;
69 
70             fs_mkdirs(path.c_str(), S_IRWXU);
71 
72             if (it != content.end()) {
73                 std::ofstream{path} << it->second << std::endl;
74             } else {
75                 symlink("/dev/null", path.c_str());
76             }
77         }
78 
79         mVibrator = ndk::SharedRefBase::make<Vibrator>(
80                 std::make_unique<HwApi>(), std::make_unique<HwCal>(), std::make_unique<StatsApi>());
81     }
82 
DefaultArgs(benchmark::internal::Benchmark * b)83     static void DefaultArgs(benchmark::internal::Benchmark *b) { b->Unit(benchmark::kMicrosecond); }
84 
SupportedEffectArgs(benchmark::internal::Benchmark * b)85     static void SupportedEffectArgs(benchmark::internal::Benchmark *b) {
86         b->ArgNames({"Effect", "Strength"});
87         for (Effect effect : ndk::enum_range<Effect>()) {
88             for (EffectStrength strength : ndk::enum_range<EffectStrength>()) {
89                 b->Args({static_cast<long>(effect), static_cast<long>(strength)});
90             }
91         }
92     }
93 
94   protected:
95     TemporaryDir mFilesDir;
96     std::shared_ptr<IVibrator> mVibrator;
97 };
98 
99 #define BENCHMARK_WRAPPER(fixt, test, code) \
100     BENCHMARK_DEFINE_F(fixt, test)          \
101     /* NOLINTNEXTLINE */                    \
102     (benchmark::State & state){code} BENCHMARK_REGISTER_F(fixt, test)->Apply(fixt::DefaultArgs)
103 
104 BENCHMARK_WRAPPER(VibratorBench, on, {
105     uint32_t duration = std::rand() ?: 1;
106 
107     for (auto _ : state) {
108         mVibrator->on(duration, nullptr);
109     }
110 });
111 
112 BENCHMARK_WRAPPER(VibratorBench, off, {
113     for (auto _ : state) {
114         mVibrator->off();
115     }
116 });
117 
118 BENCHMARK_WRAPPER(VibratorBench, setAmplitude, {
119     uint8_t amplitude = std::rand() ?: 1;
120 
121     for (auto _ : state) {
122         mVibrator->setAmplitude(amplitude);
123     }
124 });
125 
126 BENCHMARK_WRAPPER(VibratorBench, setExternalControl_enable, {
127     for (auto _ : state) {
128         mVibrator->setExternalControl(true);
129     }
130 });
131 
132 BENCHMARK_WRAPPER(VibratorBench, setExternalControl_disable, {
133     for (auto _ : state) {
134         mVibrator->setExternalControl(false);
135     }
136 });
137 
138 BENCHMARK_WRAPPER(VibratorBench, getCapabilities, {
139     int32_t capabilities;
140 
141     for (auto _ : state) {
142         mVibrator->getCapabilities(&capabilities);
143     }
144 });
145 
146 BENCHMARK_WRAPPER(VibratorBench, perform, {
147     Effect effect = Effect(state.range(0));
148     EffectStrength strength = EffectStrength(state.range(1));
149     int32_t lengthMs;
150 
151     ndk::ScopedAStatus status = mVibrator->perform(effect, strength, nullptr, &lengthMs);
152 
153     if (!status.isOk()) {
154         return;
155     }
156 
157     for (auto _ : state) {
158         mVibrator->perform(effect, strength, nullptr, &lengthMs);
159     }
160 })->Apply(VibratorBench::SupportedEffectArgs);
161 
162 }  // namespace vibrator
163 }  // namespace hardware
164 }  // namespace android
165 }  // namespace aidl
166 
167 BENCHMARK_MAIN();
168