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 using aidl::Effect; 32 using aidl::EffectStrength; 33 34 class CommandPerform : public Command { getDescription() const35 std::string getDescription() const override { return "Perform vibration effect."; } 36 getUsageSummary() const37 std::string getUsageSummary() const override { return "[options] <effect> <strength>"; } 38 getUsageDetails() const39 UsageDetails getUsageDetails() const override { 40 UsageDetails details{ 41 {"-b", {"Block for duration of vibration."}}, 42 {"<effect>", {"Effect ID."}}, 43 {"<strength>", {"0-2."}}, 44 }; 45 return details; 46 } 47 doArgs(Args & args)48 Status doArgs(Args &args) override { 49 while (args.get<std::string>().value_or("").find("-") == 0) { 50 auto opt = *args.pop<std::string>(); 51 if (opt == "--") { 52 break; 53 } else if (opt == "-b") { 54 mBlocking = true; 55 } else { 56 std::cerr << "Invalid Option '" << opt << "'!" << std::endl; 57 return USAGE; 58 } 59 } 60 if (auto effect = args.pop<decltype(mEffect)>()) { 61 mEffect = *effect; 62 std::cout << "Effect: " << toString(mEffect) << std::endl; 63 } else { 64 std::cerr << "Missing or Invalid Effect!" << std::endl; 65 return USAGE; 66 } 67 if (auto strength = args.pop<decltype(mStrength)>()) { 68 mStrength = *strength; 69 std::cout << "Strength: " << toString(mStrength) << std::endl; 70 } else { 71 std::cerr << "Missing or Invalid Strength!" << std::endl; 72 return USAGE; 73 } 74 if (!args.empty()) { 75 std::cerr << "Unexpected Arguments!" << std::endl; 76 return USAGE; 77 } 78 return OK; 79 } 80 doMain(Args &&)81 Status doMain(Args && /*args*/) override { 82 auto hal = getHal(); 83 84 if (!hal) { 85 return UNAVAILABLE; 86 } 87 88 uint32_t lengthMs; 89 std::shared_ptr<VibratorCallback> callback; 90 91 ABinderProcess_setThreadPoolMaxThreadCount(1); 92 ABinderProcess_startThreadPool(); 93 94 int32_t cap; 95 hal->getCapabilities(&cap); 96 97 if (mBlocking && (cap & aidl::IVibrator::CAP_PERFORM_CALLBACK)) { 98 callback = ndk::SharedRefBase::make<VibratorCallback>(); 99 } 100 101 int32_t aidlLengthMs; 102 auto status = hal->perform(mEffect, mStrength, callback, &aidlLengthMs); 103 104 lengthMs = static_cast<uint32_t>(aidlLengthMs); 105 106 if (status.isOk() && mBlocking) { 107 if (callback) { 108 callback->waitForComplete(); 109 } else { 110 sleep_for(milliseconds(lengthMs)); 111 } 112 } 113 114 std::cout << "Status: " << status.getDescription() << std::endl; 115 std::cout << "Length: " << lengthMs << std::endl; 116 117 return status.isOk() ? OK : ERROR; 118 } 119 120 bool mBlocking; 121 Effect mEffect; 122 EffectStrength mStrength; 123 }; 124 125 static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform"); 126 127 } // namespace vibrator 128 } // namespace idlcli 129 } // namespace android 130