summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarpreet "Eli" Sangha <eliptus@google.com>2019-06-05 16:52:47 +0900
committerHarpreet \"Eli\" Sangha <eliptus@google.com>2019-09-11 14:13:44 +0900
commite47ae68f000b5f6da2bc6975075f1e5b17556a9a (patch)
tree376224aba6cf77dbc092c27a677f21af039e7525
parente380e5d82fb3eee5a7bf8d7f47882abe53f89d87 (diff)
downloadnative-e47ae68f000b5f6da2bc6975075f1e5b17556a9a.tar.gz
Add CLI for Directly Invoking IDL APIs
Initial implementation supports IVibrator only. Test: Manual Execution Change-Id: Iaaa2593e7926dc202a89a59c111869cd65f31332 Signed-off-by: Harpreet \"Eli\" Sangha <eliptus@google.com>
-rw-r--r--cmds/idlcli/Android.bp53
-rw-r--r--cmds/idlcli/CommandVibrator.cpp40
-rw-r--r--cmds/idlcli/IdlCli.h41
-rw-r--r--cmds/idlcli/main.cpp23
-rw-r--r--cmds/idlcli/utils.h270
-rw-r--r--cmds/idlcli/vibrator.h86
-rw-r--r--cmds/idlcli/vibrator/CommandOff.cpp61
-rw-r--r--cmds/idlcli/vibrator/CommandOn.cpp71
-rw-r--r--cmds/idlcli/vibrator/CommandPerform.cpp107
-rw-r--r--cmds/idlcli/vibrator/CommandSetAmplitude.cpp72
-rw-r--r--cmds/idlcli/vibrator/CommandSetExternalControl.cpp70
-rw-r--r--cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp63
-rw-r--r--cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp63
13 files changed, 1020 insertions, 0 deletions
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
new file mode 100644
index 0000000000..40b8dc74f7
--- /dev/null
+++ b/cmds/idlcli/Android.bp
@@ -0,0 +1,53 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+ name: "idlcli-defaults",
+ shared_libs: [
+ "android.hardware.vibrator@1.0",
+ "android.hardware.vibrator@1.1",
+ "android.hardware.vibrator@1.2",
+ "android.hardware.vibrator@1.3",
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ cflags: [
+ "-DLOG_TAG=\"idlcli\"",
+ ],
+}
+
+cc_library {
+ name: "libidlcli",
+ defaults: ["idlcli-defaults"],
+ srcs: [
+ "CommandVibrator.cpp",
+ "vibrator/CommandOff.cpp",
+ "vibrator/CommandOn.cpp",
+ "vibrator/CommandPerform.cpp",
+ "vibrator/CommandSetAmplitude.cpp",
+ "vibrator/CommandSetExternalControl.cpp",
+ "vibrator/CommandSupportsAmplitudeControl.cpp",
+ "vibrator/CommandSupportsExternalControl.cpp",
+ ],
+ visibility: [":__subpackages__"],
+}
+
+cc_binary {
+ name: "idlcli",
+ defaults: ["idlcli-defaults"],
+ srcs: ["main.cpp"],
+ whole_static_libs: ["libidlcli"],
+}
diff --git a/cmds/idlcli/CommandVibrator.cpp b/cmds/idlcli/CommandVibrator.cpp
new file mode 100644
index 0000000000..a7a70c38af
--- /dev/null
+++ b/cmds/idlcli/CommandVibrator.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+
+namespace android {
+namespace idlcli {
+
+class IdlCli;
+
+class CommandVibrator : public CommandWithSubcommands<CommandVibrator> {
+ std::string getDescription() const override { return "Invoke Vibrator HIDL APIs."; }
+
+ std::string getUsageSummary() const override { return "<api> [arguments]"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<api>", CommandRegistry<CommandVibrator>::List()},
+ };
+ return details;
+ }
+};
+
+static const auto Command = CommandRegistry<IdlCli>::Register<CommandVibrator>("vibrator");
+
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/IdlCli.h b/cmds/idlcli/IdlCli.h
new file mode 100644
index 0000000000..dd8430415e
--- /dev/null
+++ b/cmds/idlcli/IdlCli.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
+#define FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
+
+#include "utils.h"
+
+namespace android {
+namespace idlcli {
+
+class IdlCli : public CommandWithSubcommands<IdlCli> {
+ std::string getDescription() const override { return "Invoke IDL APIs."; }
+
+ std::string getUsageSummary() const override { return "<idl> [arguments]"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<idl>", CommandRegistry<IdlCli>::List()},
+ };
+ return details;
+ }
+};
+
+} // namespace idlcli
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_IDLCLI_H_
diff --git a/cmds/idlcli/main.cpp b/cmds/idlcli/main.cpp
new file mode 100644
index 0000000000..9ed9d8216a
--- /dev/null
+++ b/cmds/idlcli/main.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "IdlCli.h"
+#include "utils.h"
+
+int main(const int argc, const char* const argv[]) {
+ using namespace ::android::idlcli;
+ return IdlCli{}.main(Args{argc, argv});
+}
diff --git a/cmds/idlcli/utils.h b/cmds/idlcli/utils.h
new file mode 100644
index 0000000000..a8e595470d
--- /dev/null
+++ b/cmds/idlcli/utils.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
+#define FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
+
+#include <hidl/HidlSupport.h>
+
+#include <iomanip>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace idlcli {
+
+namespace overrides {
+
+namespace details {
+
+template <typename T>
+inline std::istream &operator>>(std::istream &stream, T &out) {
+ auto pos = stream.tellg();
+ auto tmp = +out;
+ auto min = +std::numeric_limits<T>::min();
+ auto max = +std::numeric_limits<T>::max();
+ stream >> tmp;
+ if (!stream) {
+ return stream;
+ }
+ if (tmp < min || tmp > max) {
+ stream.seekg(pos);
+ stream.setstate(std::ios_base::failbit);
+ return stream;
+ }
+ out = tmp;
+ return stream;
+}
+
+} // namespace details
+
+// override for default behavior of treating as a character
+inline std::istream &operator>>(std::istream &stream, int8_t &out) {
+ return details::operator>>(stream, out);
+}
+
+// override for default behavior of treating as a character
+inline std::istream &operator>>(std::istream &stream, uint8_t &out) {
+ return details::operator>>(stream, out);
+}
+
+} // namespace overrides
+
+template <typename T, typename R = hardware::hidl_enum_range<T>>
+inline std::istream &operator>>(std::istream &stream, T &out) {
+ using overrides::operator>>;
+ auto validRange = R();
+ auto pos = stream.tellg();
+ std::underlying_type_t<T> in;
+ T tmp;
+ stream >> in;
+ if (!stream) {
+ return stream;
+ }
+ tmp = static_cast<T>(in);
+ if (tmp < *validRange.begin() || tmp > *std::prev(validRange.end())) {
+ stream.seekg(pos);
+ stream.setstate(std::ios_base::failbit);
+ return stream;
+ }
+ out = tmp;
+ return stream;
+}
+
+enum Status : unsigned int {
+ OK,
+ USAGE,
+ UNAVAILABLE,
+ ERROR,
+};
+
+class Args {
+public:
+ Args(const int argc, const char *const argv[]) {
+ for (int argi = 0; argi < argc; argi++) {
+ mArgs.emplace_back(std::string_view(argv[argi]));
+ }
+ }
+
+ template <typename T = std::string>
+ std::optional<T> get() {
+ return get<T>(false);
+ }
+
+ template <typename T = std::string>
+ std::optional<T> pop() {
+ return get<T>(true);
+ }
+
+ bool empty() { return mArgs.empty(); }
+
+private:
+ template <typename T>
+ std::optional<T> get(bool erase) {
+ using idlcli::operator>>;
+ using overrides::operator>>;
+ T retValue;
+
+ if (mArgs.empty()) {
+ return {};
+ }
+
+ std::stringstream stream{std::string{mArgs.front()}};
+ stream >> std::setbase(0) >> retValue;
+ if (!stream || !stream.eof()) {
+ return {};
+ }
+
+ if (erase) {
+ mArgs.erase(mArgs.begin());
+ }
+
+ return retValue;
+ }
+
+ std::vector<std::string_view> mArgs;
+};
+
+class Command {
+protected:
+ struct Usage {
+ std::string name;
+ std::vector<std::string> details;
+ };
+ using UsageDetails = std::vector<Usage>;
+
+public:
+ virtual ~Command() = default;
+
+ Status main(Args &&args) {
+ Status status = doArgsAndMain(std::move(args));
+ if (status == USAGE) {
+ printUsage();
+ return ERROR;
+ }
+ if (status == UNAVAILABLE) {
+ std::cerr << "The requested operation is unavailable." << std::endl;
+ return ERROR;
+ }
+ return status;
+ }
+
+private:
+ virtual std::string getDescription() const = 0;
+ virtual std::string getUsageSummary() const = 0;
+ virtual UsageDetails getUsageDetails() const = 0;
+ virtual Status doArgs(Args &args) = 0;
+ virtual Status doMain(Args &&args) = 0;
+
+ void printUsage() const {
+ std::cerr << "Description:\n " << getDescription() << std::endl;
+ std::cerr << "Usage:\n " << mName << " " << getUsageSummary() << std::endl;
+
+ std::cerr << "Details:" << std::endl;
+ size_t entryNameWidth = 0;
+ for (auto &entry : getUsageDetails()) {
+ entryNameWidth = std::max(entryNameWidth, entry.name.length());
+ }
+ for (auto &entry : getUsageDetails()) {
+ auto prefix = entry.name;
+ for (auto &line : entry.details) {
+ std::cerr << " " << std::left << std::setw(entryNameWidth + 8) << prefix << line
+ << std::endl;
+ prefix = "";
+ }
+ }
+ }
+
+ Status doArgsAndMain(Args &&args) {
+ Status status;
+ mName = *args.pop();
+ if ((status = doArgs(args)) != OK) {
+ return status;
+ }
+ if ((status = doMain(std::move(args))) != OK) {
+ return status;
+ }
+ return OK;
+ }
+
+protected:
+ std::string mName;
+};
+
+template <typename T>
+class CommandRegistry {
+private:
+ using CommandCreator = std::function<std::unique_ptr<Command>()>;
+
+public:
+ template <typename U>
+ static CommandCreator Register(const std::string name) {
+ Instance()->mCommands[name] = [] { return std::make_unique<U>(); };
+ return Instance()->mCommands[name];
+ }
+
+ static std::unique_ptr<Command> Create(const std::string name) {
+ auto it = Instance()->mCommands.find(name);
+ if (it == Instance()->mCommands.end()) {
+ return nullptr;
+ }
+ return it->second();
+ }
+
+ static auto List() {
+ std::vector<std::string> list;
+ for (auto &it : Instance()->mCommands) {
+ list.push_back(it.first);
+ }
+ std::sort(list.begin(), list.end());
+ return list;
+ }
+
+private:
+ static CommandRegistry *Instance() {
+ static CommandRegistry sRegistry;
+ return &sRegistry;
+ }
+
+private:
+ std::map<const std::string, CommandCreator> mCommands;
+};
+
+template <typename T>
+class CommandWithSubcommands : public Command {
+private:
+ Status doArgs(Args &args) override {
+ mCommand = CommandRegistry<T>::Create(*args.get());
+ if (!mCommand) {
+ std::cerr << "Invalid Command!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args &&args) override { return mCommand->main(std::move(args)); }
+
+protected:
+ std::unique_ptr<Command> mCommand;
+};
+
+} // namespace idlcli
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_UTILS_H_
diff --git a/cmds/idlcli/vibrator.h b/cmds/idlcli/vibrator.h
new file mode 100644
index 0000000000..bcb207b7d0
--- /dev/null
+++ b/cmds/idlcli/vibrator.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
+#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
+
+#include <android/hardware/vibrator/1.3/IVibrator.h>
+
+#include "utils.h"
+
+#include "log/log.h"
+
+namespace android {
+
+using hardware::Return;
+
+static constexpr int NUM_TRIES = 2;
+
+// Creates a Return<R> with STATUS::EX_NULL_POINTER.
+template <class R>
+inline Return<R> NullptrStatus() {
+ using ::android::hardware::Status;
+ return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
+}
+
+template <typename I>
+class HalWrapper {
+public:
+ static std::unique_ptr<HalWrapper> Create() {
+ // Assume that if getService returns a nullptr, HAL is not available on the
+ // device.
+ auto hal = I::getService();
+ return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
+ }
+
+ template <class R, class... Args0, class... Args1>
+ Return<R> call(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+ return (*mHal.*fn)(std::forward<Args1>(args1)...);
+ }
+
+private:
+ HalWrapper(sp<I>&& hal) : mHal(std::move(hal)) {}
+
+private:
+ sp<I> mHal;
+};
+
+template <typename I>
+static auto getHal() {
+ static auto sHalWrapper = HalWrapper<I>::Create();
+ return sHalWrapper.get();
+}
+
+template <class R, class I, class... Args0, class... Args1>
+Return<R> halCall(Return<R> (I::*fn)(Args0...), Args1&&... args1) {
+ auto hal = getHal<I>();
+ return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
+}
+
+namespace idlcli {
+namespace vibrator {
+
+namespace V1_0 = ::android::hardware::vibrator::V1_0;
+namespace V1_1 = ::android::hardware::vibrator::V1_1;
+namespace V1_2 = ::android::hardware::vibrator::V1_2;
+namespace V1_3 = ::android::hardware::vibrator::V1_3;
+
+} // namespace vibrator
+} // namespace idlcli
+
+} // namespace android
+
+#endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
diff --git a/cmds/idlcli/vibrator/CommandOff.cpp b/cmds/idlcli/vibrator/CommandOff.cpp
new file mode 100644
index 0000000000..a674f0192f
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandOff.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandOff : public Command {
+ std::string getDescription() const override { return "Turn off vibrator."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::off);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOff>("off");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandOn.cpp b/cmds/idlcli/vibrator/CommandOn.cpp
new file mode 100644
index 0000000000..2164b7d149
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandOn.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandOn : public Command {
+ std::string getDescription() const override { return "Turn on vibrator."; }
+
+ std::string getUsageSummary() const override { return "<duration>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<duration>", {"In milliseconds."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto duration = args.pop<decltype(mDuration)>()) {
+ mDuration = *duration;
+ } else {
+ std::cerr << "Missing or Invalid Duration!" << std::endl;
+ return USAGE;
+ }
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::on, mDuration);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ uint32_t mDuration;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandOn>("on");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandPerform.cpp b/cmds/idlcli/vibrator/CommandPerform.cpp
new file mode 100644
index 0000000000..688cbd87a1
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandPerform.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+using V1_0::EffectStrength;
+using V1_3::Effect;
+
+class CommandPerform : public Command {
+ std::string getDescription() const override { return "Perform vibration effect."; }
+
+ std::string getUsageSummary() const override { return "<effect> <strength>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<effect>", {"Effect ID."}},
+ {"<strength>", {"0-2."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto effect = args.pop<decltype(mEffect)>()) {
+ mEffect = *effect;
+ std::cout << "Effect: " << toString(mEffect) << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Effect!" << std::endl;
+ return USAGE;
+ }
+ if (auto strength = args.pop<decltype(mStrength)>()) {
+ mStrength = *strength;
+ std::cout << "Strength: " << toString(mStrength) << std::endl;
+ } else {
+ std::cerr << "Missing or Invalid Strength!" << std::endl;
+ return USAGE;
+ }
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ Return<void> ret;
+ V1_0::Status status;
+ uint32_t lengthMs;
+ auto callback = [&status, &lengthMs](V1_0::Status retStatus, uint32_t retLengthMs) {
+ status = retStatus;
+ lengthMs = retLengthMs;
+ };
+
+ if (auto hal = getHal<V1_3::IVibrator>()) {
+ ret = hal->call(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(mEffect),
+ mStrength, callback);
+ } else if (auto hal = getHal<V1_2::IVibrator>()) {
+ ret = hal->call(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(mEffect),
+ mStrength, callback);
+ } else if (auto hal = getHal<V1_1::IVibrator>()) {
+ ret = hal->call(&V1_1::IVibrator::perform_1_1, static_cast<V1_1::Effect_1_1>(mEffect),
+ mStrength, callback);
+ } else if (auto hal = getHal<V1_0::IVibrator>()) {
+ ret = hal->call(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(mEffect),
+ mStrength, callback);
+ } else {
+ ret = NullptrStatus<void>();
+ }
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(status) << std::endl;
+ std::cout << "Length: " << lengthMs << std::endl;
+
+ return status == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ Effect mEffect;
+ EffectStrength mStrength;
+};
+
+static const auto Command = CommandRegistry<CommandVibrator>::Register<CommandPerform>("perform");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetAmplitude.cpp b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
new file mode 100644
index 0000000000..38a1dc279b
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSetAmplitude.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSetAmplitude : public Command {
+ std::string getDescription() const override { return "Set vibration amplitude."; }
+
+ std::string getUsageSummary() const override { return "<amplitude>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<amplitude>", {"1-255."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto amplitude = args.pop<decltype(mAmplitude)>()) {
+ mAmplitude = *amplitude;
+ } else {
+ std::cerr << "Missing or Invalid Amplitude!" << std::endl;
+ return USAGE;
+ }
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::setAmplitude, mAmplitude);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ uint8_t mAmplitude;
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSetAmplitude>("setAmplitude");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSetExternalControl.cpp b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
new file mode 100644
index 0000000000..5fb1faca16
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSetExternalControl.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSetExternalControl : public Command {
+ std::string getDescription() const override {
+ return "Enable/disable vibration external control.";
+ }
+
+ std::string getUsageSummary() const override { return "<enable>"; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{
+ {"<enable>", {"0/1."}},
+ };
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (auto enable = args.pop<decltype(mEnable)>()) {
+ mEnable = *enable;
+ } else {
+ std::cerr << "Missing Enable!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_3::IVibrator::setExternalControl, mEnable);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Status: " << toString(ret) << std::endl;
+
+ return ret == V1_0::Status::OK ? OK : ERROR;
+ }
+
+ bool mEnable;
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSetExternalControl>("setExternalControl");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
new file mode 100644
index 0000000000..cdc529a2f3
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSupportsAmplitudeControl.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSupportsAmplitudeControl : public Command {
+ std::string getDescription() const override { return "Check support for amplitude control."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_0::IVibrator::supportsAmplitudeControl);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Result: " << std::boolalpha << ret << std::endl;
+
+ return OK;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSupportsAmplitudeControl>(
+ "supportsAmplitudeControl");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android
diff --git a/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
new file mode 100644
index 0000000000..ed15d76286
--- /dev/null
+++ b/cmds/idlcli/vibrator/CommandSupportsExternalControl.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "utils.h"
+#include "vibrator.h"
+
+namespace android {
+namespace idlcli {
+
+class CommandVibrator;
+
+namespace vibrator {
+
+class CommandSupportsExternalControl : public Command {
+ std::string getDescription() const override { return "Check support for external control."; }
+
+ std::string getUsageSummary() const override { return ""; }
+
+ UsageDetails getUsageDetails() const override {
+ UsageDetails details{};
+ return details;
+ }
+
+ Status doArgs(Args &args) override {
+ if (!args.empty()) {
+ std::cerr << "Unexpected Arguments!" << std::endl;
+ return USAGE;
+ }
+ return OK;
+ }
+
+ Status doMain(Args && /*args*/) override {
+ auto ret = halCall(&V1_3::IVibrator::supportsExternalControl);
+
+ if (!ret.isOk()) {
+ return UNAVAILABLE;
+ }
+
+ std::cout << "Result: " << std::boolalpha << ret << std::endl;
+
+ return OK;
+ }
+};
+
+static const auto Command =
+ CommandRegistry<CommandVibrator>::Register<CommandSupportsExternalControl>(
+ "supportsExternalControl");
+
+} // namespace vibrator
+} // namespace idlcli
+} // namespace android