• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
23 namespace android {
24 namespace idlcli {
25 
26 class CommandVibrator;
27 
28 namespace vibrator {
29 
30 using aidl::CompositePwleV2;
31 using aidl::PwleV2Primitive;
32 
33 class CommandComposePwleV2 : public Command {
getDescription() const34     std::string getDescription() const override { return "Compose normalized PWLE vibration."; }
35 
getUsageSummary() const36     std::string getUsageSummary() const override {
37         return "[options] <time> <frequency> <amplitude> ...";
38     }
39 
getUsageDetails() const40     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 
doArgs(Args & args)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 
doMain(Args &&)110     Status doMain(Args&& /*args*/) override {
111         auto hal = getHal();
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->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 
141 static const auto Command =
142         CommandRegistry<CommandVibrator>::Register<CommandComposePwleV2>("composePwleV2");
143 
144 } // namespace vibrator
145 } // namespace idlcli
146 } // namespace android
147