1 /* 2 * Copyright (C) 2019 The Android Open Source Project * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #include <thread> 17 18 #include "utils.h" 19 #include "vibrator.h" 20 21 using std::chrono::milliseconds; 22 using std::this_thread::sleep_for; 23 24 namespace android { 25 namespace idlcli { 26 27 class CommandVibrator; 28 29 namespace vibrator { 30 31 /* 32 * The following static asserts are only relevant here because the argument 33 * parser uses a single implementation for determining the string names. 34 */ 35 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) == 36 static_cast<uint8_t>(aidl::EffectStrength::LIGHT)); 37 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) == 38 static_cast<uint8_t>(aidl::EffectStrength::MEDIUM)); 39 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) == 40 static_cast<uint8_t>(aidl::EffectStrength::STRONG)); 41 static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) == 42 static_cast<uint8_t>(aidl::Effect::CLICK)); 43 static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) == 44 static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK)); 45 static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK)); 46 static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD)); 47 static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP)); 48 static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) == 49 static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK)); 50 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) == 51 static_cast<uint8_t>(aidl::Effect::RINGTONE_1)); 52 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) == 53 static_cast<uint8_t>(aidl::Effect::RINGTONE_2)); 54 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == 55 static_cast<uint8_t>(aidl::Effect::RINGTONE_15)); 56 static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == 57 static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); 58 59 using aidl::Effect; 60 using aidl::EffectStrength; 61 62 class CommandPerform : public Command { getDescription() const63 std::string getDescription() const override { return "Perform vibration effect."; } 64 getUsageSummary() const65 std::string getUsageSummary() const override { return "[options] <effect> <strength>"; } 66 getUsageDetails() const67 UsageDetails getUsageDetails() const override { 68 UsageDetails details{ 69 {"-b", {"Block for duration of vibration."}}, 70 {"<effect>", {"Effect ID."}}, 71 {"<strength>", {"0-2."}}, 72 }; 73 return details; 74 } 75 doArgs(Args & args)76 Status doArgs(Args &args) override { 77 while (args.get<std::string>().value_or("").find("-") == 0) { 78 auto opt = *args.pop<std::string>(); 79 if (opt == "--") { 80 break; 81 } else if (opt == "-b") { 82 mBlocking = true; 83 } else { 84 std::cerr << "Invalid Option '" << opt << "'!" << std::endl; 85 return USAGE; 86 } 87 } 88 if (auto effect = args.pop<decltype(mEffect)>()) { 89 mEffect = *effect; 90 std::cout << "Effect: " << toString(mEffect) << std::endl; 91 } else { 92 std::cerr << "Missing or Invalid Effect!" << std::endl; 93 return USAGE; 94 } 95 if (auto strength = args.pop<decltype(mStrength)>()) { 96 mStrength = *strength; 97 std::cout << "Strength: " << toString(mStrength) << std::endl; 98 } else { 99 std::cerr << "Missing or Invalid Strength!" << std::endl; 100 return USAGE; 101 } 102 if (!args.empty()) { 103 std::cerr << "Unexpected Arguments!" << std::endl; 104 return USAGE; 105 } 106 return OK; 107 } 108 doMain(Args &&)109 Status doMain(Args && /*args*/) override { 110 std::string statusStr; 111 uint32_t lengthMs; 112 Status ret; 113 std::shared_ptr<VibratorCallback> callback; 114 115 if (auto hal = getHal<aidl::IVibrator>()) { 116 ABinderProcess_setThreadPoolMaxThreadCount(1); 117 ABinderProcess_startThreadPool(); 118 119 int32_t cap; 120 hal->call(&aidl::IVibrator::getCapabilities, &cap); 121 122 if (mBlocking && (cap & aidl::IVibrator::CAP_PERFORM_CALLBACK)) { 123 callback = ndk::SharedRefBase::make<VibratorCallback>(); 124 } 125 126 int32_t aidlLengthMs; 127 auto status = hal->call(&aidl::IVibrator::perform, mEffect, mStrength, callback, 128 &aidlLengthMs); 129 130 statusStr = status.getDescription(); 131 lengthMs = static_cast<uint32_t>(aidlLengthMs); 132 ret = status.isOk() ? OK : ERROR; 133 } else { 134 Return<void> hidlRet; 135 V1_0::Status status; 136 auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) { 137 status = retStatus; 138 lengthMs = retLengthMs; 139 }; 140 141 if (auto hal = getHal<V1_3::IVibrator>()) { 142 hidlRet = 143 hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect), 144 static_cast<V1_0::EffectStrength>(mStrength), callback); 145 } else if (auto hal = getHal<V1_2::IVibrator>()) { 146 hidlRet = 147 hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect), 148 static_cast<V1_0::EffectStrength>(mStrength), callback); 149 } else if (auto hal = getHal<V1_1::IVibrator>()) { 150 hidlRet = hal->call(&V1_1::IVibrator::perform_1_1, 151 static_cast<V1_1::Effect_1_1>(mEffect), 152 static_cast<V1_0::EffectStrength>(mStrength), callback); 153 } else if (auto hal = getHal<V1_0::IVibrator>()) { 154 hidlRet = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect), 155 static_cast<V1_0::EffectStrength>(mStrength), callback); 156 } else { 157 return UNAVAILABLE; 158 } 159 160 statusStr = toString(status); 161 ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR; 162 } 163 164 if (ret == OK && mBlocking) { 165 if (callback) { 166 callback->waitForComplete(); 167 } else { 168 sleep_for(milliseconds(lengthMs)); 169 } 170 } 171 172 std::cout << "Status: " << statusStr << std::endl; 173 std::cout << "Length: " << lengthMs << std::endl; 174 175 return ret; 176 } 177 178 bool mBlocking; 179 Effect mEffect; 180 EffectStrength mStrength; 181 }; 182 183 static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform"); 184 185 } // namespace vibrator 186 } // namespace idlcli 187 } // namespace android 188