• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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