blob: 6d3cf84a2edef7b7a38ad41b1f69d8fb166b3a1f [file] [log] [blame]
Nathan Kulczakd7cdab22024-10-09 07:58:14 +00001/*
2 * Copyright (C) 2024 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 <stdlib.h>
17
18#include <charconv>
19
20#include "utils.h"
21#include "vibrator.h"
22
23namespace android {
24namespace idlcli {
25
26class CommandVibrator;
27
28namespace vibrator {
29
30using aidl::CompositePwleV2;
31using aidl::PwleV2Primitive;
32
33class CommandComposePwleV2 : public Command {
34 std::string getDescription() const override { return "Compose normalized PWLE vibration."; }
35
36 std::string getUsageSummary() const override {
37 return "[options] <time> <frequency> <amplitude> ...";
38 }
39
40 UsageDetails getUsageDetails() const override {
41 UsageDetails details{
42 {"-b", {"Block for duration of vibration."}},
43 {"<time>", {"Segment duration in milliseconds"}},
44 {"<frequency>", {"Target frequency in Hz"}},
45 {"<amplitude>", {"Target amplitude in [0.0, 1.0]"}},
46 {"...", {"May repeat multiple times."}},
47 };
48 return details;
49 }
50
51 Status doArgs(Args& args) override {
52 while (args.get<std::string>().value_or("").find("-") == 0) {
53 auto opt = *args.pop<std::string>();
54 if (opt == "--") {
55 break;
56 } else if (opt == "-b") {
57 mBlocking = true;
58 } else {
59 std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
60 return USAGE;
61 }
62 }
63
64 if (args.empty()) {
65 std::cerr << "Missing arguments! Please see usage" << std::endl;
66 return USAGE;
67 }
68
69 while (!args.empty()) {
70 PwleV2Primitive segment;
71
72 if (auto timeMs = args.pop<decltype(segment.timeMillis)>();
73 timeMs && *timeMs >= 0 && *timeMs <= 0x7ffff) {
74 segment.timeMillis = *timeMs;
75 std::cout << "Time: " << segment.timeMillis << std::endl;
76 } else {
77 std::cerr << "Missing or Invalid Time!" << std::endl;
78 return USAGE;
79 }
80
81 if (auto frequencyHz = args.pop<decltype(segment.frequencyHz)>();
82 frequencyHz && *frequencyHz >= 30 && *frequencyHz <= 300) {
83 segment.frequencyHz = *frequencyHz;
84 std::cout << "Frequency: " << segment.frequencyHz << std::endl;
85 } else {
86 std::cerr << "Missing or Invalid Frequency!" << std::endl;
87 return USAGE;
88 }
89
90 if (auto amplitude = args.pop<decltype(segment.amplitude)>();
91 amplitude && *amplitude >= 0 && *amplitude <= 1.0) {
92 segment.amplitude = *amplitude;
93 std::cout << "Amplitude: " << segment.amplitude << std::endl;
94 } else {
95 std::cerr << "Missing or Invalid Amplitude!" << std::endl;
96 return USAGE;
97 }
98
99 mCompositePwle.pwlePrimitives.emplace_back(std::move(segment));
100 }
101
102 if (!args.empty()) {
103 std::cerr << "Unexpected Arguments!" << std::endl;
104 return USAGE;
105 }
106
107 return OK;
108 }
109
110 Status doMain(Args&& /*args*/) override {
111 auto hal = getHal<aidl::IVibrator>();
112
113 if (!hal) {
114 return UNAVAILABLE;
115 }
116
117 ABinderProcess_setThreadPoolMaxThreadCount(1);
118 ABinderProcess_startThreadPool();
119
120 std::shared_ptr<VibratorCallback> callback;
121
122 if (mBlocking) {
123 callback = ndk::SharedRefBase::make<VibratorCallback>();
124 }
125
126 auto status = hal->call(&aidl::IVibrator::composePwleV2, mCompositePwle, callback);
127
128 if (status.isOk() && callback) {
129 callback->waitForComplete();
130 }
131
132 std::cout << "Status: " << status.getDescription() << std::endl;
133
134 return status.isOk() ? OK : ERROR;
135 }
136
137 bool mBlocking;
138 CompositePwleV2 mCompositePwle;
139};
140
141static const auto Command =
142 CommandRegistry<CommandVibrator>::Register<CommandComposePwleV2>("composePwleV2");
143
144} // namespace vibrator
145} // namespace idlcli
146} // namespace android