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