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 "utils.h"
17 #include "vibrator.h"
18 
19 namespace android {
20 namespace idlcli {
21 
22 class CommandVibrator;
23 
24 namespace vibrator {
25 
26 /*
27  * The following static asserts are only relevant here because the argument
28  * parser uses a single implementation for determining the string names.
29  */
30 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
31               static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
32 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
33               static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
34 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
35               static_cast<uint8_t>(aidl::EffectStrength::STRONG));
36 static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
37               static_cast<uint8_t>(aidl::Effect::CLICK));
38 static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
39               static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
40 static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK));
41 static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD));
42 static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP));
43 static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
44               static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
45 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
46               static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
47 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
48               static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
49 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
50               static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
51 static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
52               static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
53 
54 using V1_0::EffectStrength;
55 using V1_3::Effect;
56 
57 class CommandPerform : public Command {
getDescription() const58     std::string getDescription() const override { return "Perform vibration effect."; }
59 
getUsageSummary() const60     std::string getUsageSummary() const override { return "<effect> <strength>"; }
61 
getUsageDetails() const62     UsageDetails getUsageDetails() const override {
63         UsageDetails details{
64                 {"<effect>", {"Effect ID."}},
65                 {"<strength>", {"0-2."}},
66         };
67         return details;
68     }
69 
doArgs(Args & args)70     Status doArgs(Args &args) override {
71         if (auto effect = args.pop<decltype(mEffect)>()) {
72             mEffect = *effect;
73             std::cout << "Effect: " << toString(mEffect) << std::endl;
74         } else {
75             std::cerr << "Missing or Invalid Effect!" << std::endl;
76             return USAGE;
77         }
78         if (auto strength = args.pop<decltype(mStrength)>()) {
79             mStrength = *strength;
80             std::cout << "Strength: " << toString(mStrength) << std::endl;
81         } else {
82             std::cerr << "Missing or Invalid Strength!" << std::endl;
83             return USAGE;
84         }
85         if (!args.empty()) {
86             std::cerr << "Unexpected Arguments!" << std::endl;
87             return USAGE;
88         }
89         return OK;
90     }
91 
doMain(Args &&)92     Status doMain(Args && /*args*/) override {
93         std::string statusStr;
94         uint32_t lengthMs;
95         Status ret;
96 
97         if (auto hal = getHal<aidl::IVibrator>()) {
98             int32_t aidlLengthMs;
99             auto status =
100                     hal->call(&aidl::IVibrator::perform, static_cast<aidl::Effect>(mEffect),
101                               static_cast<aidl::EffectStrength>(mStrength), nullptr, &aidlLengthMs);
102             statusStr = status.getDescription();
103             lengthMs = static_cast<uint32_t>(aidlLengthMs);
104             ret = status.isOk() ? OK : ERROR;
105         } else {
106             Return<void> hidlRet;
107             V1_0::Status status;
108             auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
109                 status = retStatus;
110                 lengthMs = retLengthMs;
111             };
112 
113             if (auto hal = getHal<V1_3::IVibrator>()) {
114                 hidlRet = hal->call(&V1_3::IVibrator::perform_1_3,
115                                     static_cast<V1_3::Effect>(mEffect), mStrength, callback);
116             } else if (auto hal = getHal<V1_2::IVibrator>()) {
117                 hidlRet = hal->call(&V1_2::IVibrator::perform_1_2,
118                                     static_cast<V1_2::Effect>(mEffect), mStrength, callback);
119             } else if (auto hal = getHal<V1_1::IVibrator>()) {
120                 hidlRet = hal->call(&V1_1::IVibrator::perform_1_1,
121                                     static_cast<V1_1::Effect_1_1>(mEffect), mStrength, callback);
122             } else if (auto hal = getHal<V1_0::IVibrator>()) {
123                 hidlRet = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
124                                     mStrength, callback);
125             } else {
126                 return UNAVAILABLE;
127             }
128 
129             statusStr = toString(status);
130             ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
131         }
132 
133         std::cout << "Status: " << statusStr << std::endl;
134         std::cout << "Length: " << lengthMs << std::endl;
135 
136         return ret;
137     }
138 
139     Effect mEffect;
140     EffectStrength mStrength;
141 };
142 
143 static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform");
144 
145 } // namespace vibrator
146 } // namespace idlcli
147 } // namespace android
148