blob: 2137789ce9e6c762cfbddabeab98780cb8378f4e [file] [log] [blame]
Harpreet "Eli" Sanghae8631242019-01-31 15:43:36 +09001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "VibratorService"
18
19#include <log/log.h>
20
21#include "Vibrator.h"
22
23namespace android {
24namespace hardware {
25namespace vibrator {
26namespace V1_3 {
27namespace implementation {
28
29static constexpr uint32_t MS_PER_S = 1000;
30static constexpr uint32_t NS_PER_MS = 1000000;
31
32Vibrator::Vibrator() {
33 sigevent se{};
34 se.sigev_notify = SIGEV_THREAD;
35 se.sigev_value.sival_ptr = this;
36 se.sigev_notify_function = timerCallback;
37 se.sigev_notify_attributes = nullptr;
38
39 if (timer_create(CLOCK_REALTIME, &se, &mTimer) < 0) {
40 ALOGE("Can not create timer!%s", strerror(errno));
41 }
42}
43
44// Methods from ::android::hardware::vibrator::V1_0::IVibrator follow.
45
46Return<Status> Vibrator::on(uint32_t timeoutMs) {
47 return activate(timeoutMs);
48}
49
50Return<Status> Vibrator::off() {
51 return activate(0);
52}
53
54Return<bool> Vibrator::supportsAmplitudeControl() {
55 return true;
56}
57
58Return<Status> Vibrator::setAmplitude(uint8_t amplitude) {
59 ALOGI("Amplitude: %u -> %u\n", mAmplitude, amplitude);
60 mAmplitude = amplitude;
61 return Status::OK;
62}
63
64Return<void> Vibrator::perform(V1_0::Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
65 return perform_1_1(static_cast<V1_1::Effect_1_1>(effect), strength, _hidl_cb);
66}
67
68// Methods from ::android::hardware::vibrator::V1_1::IVibrator follow.
69
70Return<void> Vibrator::perform_1_1(V1_1::Effect_1_1 effect, EffectStrength strength,
71 perform_cb _hidl_cb) {
72 return perform_1_2(static_cast<V1_2::Effect>(effect), strength, _hidl_cb);
73}
74
75// Methods from ::android::hardware::vibrator::V1_2::IVibrator follow.
76
Michael Wrighta4c94fd2019-03-21 20:48:34 +000077Return<void> Vibrator::perform_1_2(V1_2::Effect effect, EffectStrength strength,
78 perform_cb _hidl_cb) {
79 return perform_1_3(static_cast<V1_3::Effect>(effect), strength, _hidl_cb);
Harpreet "Eli" Sanghae8631242019-01-31 15:43:36 +090080}
81
82// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
83
84Return<bool> Vibrator::supportsExternalControl() {
85 return true;
86}
87
88Return<Status> Vibrator::setExternalControl(bool enabled) {
89 if (mEnabled) {
90 ALOGW("Setting external control while the vibrator is enabled is unsupported!");
91 return Status::UNSUPPORTED_OPERATION;
92 } else {
93 ALOGI("ExternalControl: %s -> %s\n", mExternalControl ? "true" : "false",
94 enabled ? "true" : "false");
95 mExternalControl = enabled;
96 return Status::OK;
97 }
98}
99
Michael Wrighta4c94fd2019-03-21 20:48:34 +0000100Return<void> Vibrator::perform_1_3(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
101 uint8_t amplitude;
102 uint32_t ms;
103 Status status;
104
Harpreet "Eli" Sanghaa2443212019-03-25 14:08:59 +0900105 ALOGI("Perform: Effect %s\n", effectToName(effect).c_str());
Michael Wrighta4c94fd2019-03-21 20:48:34 +0000106
107 amplitude = strengthToAmplitude(strength);
108 setAmplitude(amplitude);
109
110 ms = effectToMs(effect);
111 status = activate(ms);
112
113 _hidl_cb(status, ms);
114
115 return Void();
116}
117
Harpreet "Eli" Sanghae8631242019-01-31 15:43:36 +0900118// Private methods follow.
119
120Status Vibrator::enable(bool enabled) {
121 if (mExternalControl) {
122 ALOGW("Enabling/disabling while the vibrator is externally controlled is unsupported!");
123 return Status::UNSUPPORTED_OPERATION;
124 } else {
125 ALOGI("Enabled: %s -> %s\n", mEnabled ? "true" : "false", enabled ? "true" : "false");
126 mEnabled = enabled;
127 return Status::OK;
128 }
129}
130
131Status Vibrator::activate(uint32_t ms) {
132 std::lock_guard<std::mutex> lock{mMutex};
133 Status status = Status::OK;
134
135 if (ms > 0) {
136 status = enable(true);
137 if (status != Status::OK) {
138 return status;
139 }
140 }
141
142 itimerspec ts{};
143 ts.it_value.tv_sec = ms / MS_PER_S;
144 ts.it_value.tv_nsec = ms % MS_PER_S * NS_PER_MS;
145
146 if (timer_settime(mTimer, 0, &ts, nullptr) < 0) {
147 ALOGE("Can not set timer!");
148 status = Status::UNKNOWN_ERROR;
149 }
150
151 if ((status != Status::OK) || !ms) {
152 Status _status;
153
154 _status = enable(false);
155
156 if (status == Status::OK) {
157 status = _status;
158 }
159 }
160
161 return status;
162}
163
164void Vibrator::timeout() {
165 std::lock_guard<std::mutex> lock{mMutex};
166 itimerspec ts{};
167
168 if (timer_gettime(mTimer, &ts) < 0) {
169 ALOGE("Can not read timer!");
170 }
171
172 if (ts.it_value.tv_sec == 0 && ts.it_value.tv_nsec == 0) {
173 enable(false);
174 }
175}
176
177void Vibrator::timerCallback(union sigval sigval) {
178 static_cast<Vibrator*>(sigval.sival_ptr)->timeout();
179}
180
Harpreet "Eli" Sanghaa2443212019-03-25 14:08:59 +0900181const std::string Vibrator::effectToName(Effect effect) {
182 return toString(effect);
Harpreet "Eli" Sanghae8631242019-01-31 15:43:36 +0900183}
184
185uint32_t Vibrator::effectToMs(Effect effect) {
186 switch (effect) {
187 case Effect::CLICK:
188 return 10;
189 case Effect::DOUBLE_CLICK:
190 return 15;
191 case Effect::TICK:
Michael Wrighta4c94fd2019-03-21 20:48:34 +0000192 case Effect::TEXTURE_TICK:
Harpreet "Eli" Sanghae8631242019-01-31 15:43:36 +0900193 return 5;
194 case Effect::THUD:
195 return 5;
196 case Effect::POP:
197 return 5;
198 case Effect::HEAVY_CLICK:
199 return 10;
200 case Effect::RINGTONE_1:
201 return 30000;
202 case Effect::RINGTONE_2:
203 return 30000;
204 case Effect::RINGTONE_3:
205 return 30000;
206 case Effect::RINGTONE_4:
207 return 30000;
208 case Effect::RINGTONE_5:
209 return 30000;
210 case Effect::RINGTONE_6:
211 return 30000;
212 case Effect::RINGTONE_7:
213 return 30000;
214 case Effect::RINGTONE_8:
215 return 30000;
216 case Effect::RINGTONE_9:
217 return 30000;
218 case Effect::RINGTONE_10:
219 return 30000;
220 case Effect::RINGTONE_11:
221 return 30000;
222 case Effect::RINGTONE_12:
223 return 30000;
224 case Effect::RINGTONE_13:
225 return 30000;
226 case Effect::RINGTONE_14:
227 return 30000;
228 case Effect::RINGTONE_15:
229 return 30000;
230 }
231}
232
233uint8_t Vibrator::strengthToAmplitude(EffectStrength strength) {
234 switch (strength) {
235 case EffectStrength::LIGHT:
236 return 128;
237 case EffectStrength::MEDIUM:
238 return 192;
239 case EffectStrength::STRONG:
240 return 255;
241 }
242}
243
244} // namespace implementation
245} // namespace V1_3
246} // namespace vibrator
247} // namespace hardware
248} // namespace android