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