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 <android-base/properties.h> 19 #include <cutils/fs.h> 20 21 #include "Hardware.h" 22 #include "Vibrator.h" 23 24 namespace aidl { 25 namespace android { 26 namespace hardware { 27 namespace vibrator { 28 29 using ::android::base::SetProperty; 30 31 class VibratorBench : public benchmark::Fixture { 32 private: 33 static constexpr const char *FILE_NAMES[]{ 34 "device/autocal", 35 "device/ol_lra_period", 36 "activate", 37 "duration", 38 "state", 39 "device/rtp_input", 40 "device/mode", 41 "device/set_sequencer", 42 "device/scale", 43 "device/ctrl_loop", 44 "device/lp_trigger_effect", 45 "device/lp_trigger_scale", 46 "device/lra_wave_shape", 47 "device/od_clamp", 48 }; 49 static constexpr char PROPERTY_PREFIX[] = "test.vibrator.hal."; 50 51 public: SetUp(::benchmark::State & state)52 void SetUp(::benchmark::State &state) override { 53 auto prefix = std::filesystem::path(mFilesDir.path) / ""; 54 55 setenv("HWAPI_PATH_PREFIX", prefix.c_str(), true); 56 57 for (auto n : FILE_NAMES) { 58 const auto name = std::filesystem::path(n); 59 const auto path = std::filesystem::path(mFilesDir.path) / name; 60 61 fs_mkdirs(path.c_str(), S_IRWXU); 62 symlink("/dev/null", path.c_str()); 63 } 64 65 setenv("PROPERTY_PREFIX", PROPERTY_PREFIX, true); 66 67 SetProperty(std::string() + PROPERTY_PREFIX + "config.dynamic", getDynamicConfig(state)); 68 69 mVibrator = ndk::SharedRefBase::make<Vibrator>(HwApi::Create(), std::make_unique<HwCal>()); 70 } 71 DefaultConfig(benchmark::internal::Benchmark * b)72 static void DefaultConfig(benchmark::internal::Benchmark *b) { 73 b->Unit(benchmark::kMicrosecond); 74 } 75 DefaultArgs(benchmark::internal::Benchmark * b)76 static void DefaultArgs(benchmark::internal::Benchmark *b) { 77 b->ArgNames({"DynamicConfig"}); 78 b->Args({false}); 79 b->Args({true}); 80 } 81 82 protected: getDynamicConfig(const::benchmark::State & state) const83 std::string getDynamicConfig(const ::benchmark::State &state) const { 84 return std::to_string(state.range(0)); 85 } 86 getOtherArg(const::benchmark::State & state,std::size_t index) const87 auto getOtherArg(const ::benchmark::State &state, std::size_t index) const { 88 return state.range(index + 1); 89 } 90 91 protected: 92 TemporaryDir mFilesDir; 93 std::shared_ptr<IVibrator> mVibrator; 94 }; 95 96 #define BENCHMARK_WRAPPER(fixt, test, code) \ 97 BENCHMARK_DEFINE_F(fixt, test) \ 98 /* NOLINTNEXTLINE */ \ 99 (benchmark::State & state){code} BENCHMARK_REGISTER_F(fixt, test) \ 100 ->Apply(fixt::DefaultConfig) \ 101 ->Apply(fixt::DefaultArgs) 102 103 BENCHMARK_WRAPPER(VibratorBench, on, { 104 uint32_t duration = std::rand() ?: 1; 105 106 for (auto _ : state) { 107 mVibrator->on(duration, nullptr); 108 } 109 }); 110 111 BENCHMARK_WRAPPER(VibratorBench, off, { 112 for (auto _ : state) { 113 mVibrator->off(); 114 } 115 }); 116 117 BENCHMARK_WRAPPER(VibratorBench, setAmplitude, { 118 uint8_t amplitude = std::rand() ?: 1; 119 120 for (auto _ : state) { 121 mVibrator->setAmplitude(amplitude); 122 } 123 }); 124 125 BENCHMARK_WRAPPER(VibratorBench, setExternalControl_enable, { 126 for (auto _ : state) { 127 mVibrator->setExternalControl(true); 128 } 129 }); 130 131 BENCHMARK_WRAPPER(VibratorBench, setExternalControl_disable, { 132 for (auto _ : state) { 133 mVibrator->setExternalControl(false); 134 } 135 }); 136 137 BENCHMARK_WRAPPER(VibratorBench, getCapabilities, { 138 int32_t capabilities; 139 140 for (auto _ : state) { 141 mVibrator->getCapabilities(&capabilities); 142 } 143 }); 144 145 class VibratorEffectsBench : public VibratorBench { 146 public: DefaultArgs(benchmark::internal::Benchmark * b)147 static void DefaultArgs(benchmark::internal::Benchmark *b) { 148 b->ArgNames({"DynamicConfig", "Effect", "Strength"}); 149 for (const auto &dynamic : {false, true}) { 150 for (const auto &effect : ndk::enum_range<Effect>()) { 151 for (const auto &strength : ndk::enum_range<EffectStrength>()) { 152 b->Args({dynamic, static_cast<long>(effect), static_cast<long>(strength)}); 153 } 154 } 155 } 156 } 157 158 protected: getEffect(const::benchmark::State & state) const159 auto getEffect(const ::benchmark::State &state) const { 160 return static_cast<Effect>(getOtherArg(state, 0)); 161 } 162 getStrength(const::benchmark::State & state) const163 auto getStrength(const ::benchmark::State &state) const { 164 return static_cast<EffectStrength>(getOtherArg(state, 1)); 165 } 166 }; 167 168 BENCHMARK_WRAPPER(VibratorEffectsBench, perform, { 169 Effect effect = getEffect(state); 170 EffectStrength strength = getStrength(state); 171 int32_t lengthMs; 172 173 ndk::ScopedAStatus status = mVibrator->perform(effect, strength, nullptr, &lengthMs); 174 175 if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { 176 return; 177 } 178 179 for (auto _ : state) { 180 mVibrator->perform(effect, strength, nullptr, &lengthMs); 181 } 182 }); 183 184 } // namespace vibrator 185 } // namespace hardware 186 } // namespace android 187 } // namespace aidl 188 189 BENCHMARK_MAIN(); 190