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 class CommandOn : public Command { getDescription() const32 std::string getDescription() const override { return "Turn on vibrator."; } 33 getUsageSummary() const34 std::string getUsageSummary() const override { return "[options] <duration>"; } 35 getUsageDetails() const36 UsageDetails getUsageDetails() const override { 37 UsageDetails details{ 38 {"-b", {"Block for duration of vibration."}}, 39 {"<duration>", {"In milliseconds."}}, 40 }; 41 return details; 42 } 43 doArgs(Args & args)44 Status doArgs(Args &args) override { 45 while (args.get<std::string>().value_or("").find("-") == 0) { 46 auto opt = *args.pop<std::string>(); 47 if (opt == "--") { 48 break; 49 } else if (opt == "-b") { 50 mBlocking = true; 51 } else { 52 std::cerr << "Invalid Option '" << opt << "'!" << std::endl; 53 return USAGE; 54 } 55 } 56 if (auto duration = args.pop<decltype(mDuration)>()) { 57 mDuration = *duration; 58 } else { 59 std::cerr << "Missing or Invalid Duration!" << std::endl; 60 return USAGE; 61 } 62 if (!args.empty()) { 63 std::cerr << "Unexpected Arguments!" << std::endl; 64 return USAGE; 65 } 66 return OK; 67 } 68 doMain(Args &&)69 Status doMain(Args && /*args*/) override { 70 std::string statusStr; 71 Status ret; 72 std::shared_ptr<VibratorCallback> callback; 73 74 if (auto hal = getHal<aidl::IVibrator>()) { 75 ABinderProcess_setThreadPoolMaxThreadCount(1); 76 ABinderProcess_startThreadPool(); 77 78 int32_t cap; 79 hal->call(&aidl::IVibrator::getCapabilities, &cap); 80 81 if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) { 82 callback = ndk::SharedRefBase::make<VibratorCallback>(); 83 } 84 85 auto status = hal->call(&aidl::IVibrator::on, mDuration, callback); 86 87 statusStr = status.getDescription(); 88 ret = status.isOk() ? OK : ERROR; 89 } else if (auto hal = getHal<V1_0::IVibrator>()) { 90 auto status = hal->call(&V1_0::IVibrator::on, mDuration); 91 statusStr = toString(status); 92 ret = status.isOk() && status == V1_0::Status::OK ? OK : ERROR; 93 } else { 94 return UNAVAILABLE; 95 } 96 97 if (ret == OK && mBlocking) { 98 if (callback) { 99 callback->waitForComplete(); 100 } else { 101 sleep_for(milliseconds(mDuration)); 102 } 103 } 104 105 std::cout << "Status: " << statusStr << std::endl; 106 107 return ret; 108 } 109 110 bool mBlocking; 111 uint32_t mDuration; 112 }; 113 114 static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOn>("on"); 115 116 } // namespace vibrator 117 } // namespace idlcli 118 } // namespace android 119