blob: bb9a0576974760c021ade6a5f1d037a8b15ae6d8 [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
77Return<void> Vibrator::perform_1_2(Effect effect, EffectStrength strength, perform_cb _hidl_cb) {
78 uint8_t amplitude;
79 uint32_t ms;
80 Status status;
81
82 ALOGI("Perform: Effect %s\n", effectToName(effect));
83
84 amplitude = strengthToAmplitude(strength);
85 setAmplitude(amplitude);
86
87 ms = effectToMs(effect);
88 status = activate(ms);
89
90 _hidl_cb(status, ms);
91
92 return Void();
93}
94
95// Methods from ::android::hardware::vibrator::V1_3::IVibrator follow.
96
97Return<bool> Vibrator::supportsExternalControl() {
98 return true;
99}
100
101Return<Status> Vibrator::setExternalControl(bool enabled) {
102 if (mEnabled) {
103 ALOGW("Setting external control while the vibrator is enabled is unsupported!");
104 return Status::UNSUPPORTED_OPERATION;
105 } else {
106 ALOGI("ExternalControl: %s -> %s\n", mExternalControl ? "true" : "false",
107 enabled ? "true" : "false");
108 mExternalControl = enabled;
109 return Status::OK;
110 }
111}
112
113// Private methods follow.
114
115Status Vibrator::enable(bool enabled) {
116 if (mExternalControl) {
117 ALOGW("Enabling/disabling while the vibrator is externally controlled is unsupported!");
118 return Status::UNSUPPORTED_OPERATION;
119 } else {
120 ALOGI("Enabled: %s -> %s\n", mEnabled ? "true" : "false", enabled ? "true" : "false");
121 mEnabled = enabled;
122 return Status::OK;
123 }
124}
125
126Status Vibrator::activate(uint32_t ms) {
127 std::lock_guard<std::mutex> lock{mMutex};
128 Status status = Status::OK;
129
130 if (ms > 0) {
131 status = enable(true);
132 if (status != Status::OK) {
133 return status;
134 }
135 }
136
137 itimerspec ts{};
138 ts.it_value.tv_sec = ms / MS_PER_S;
139 ts.it_value.tv_nsec = ms % MS_PER_S * NS_PER_MS;
140
141 if (timer_settime(mTimer, 0, &ts, nullptr) < 0) {
142 ALOGE("Can not set timer!");
143 status = Status::UNKNOWN_ERROR;
144 }
145
146 if ((status != Status::OK) || !ms) {
147 Status _status;
148
149 _status = enable(false);
150
151 if (status == Status::OK) {
152 status = _status;
153 }
154 }
155
156 return status;
157}
158
159void Vibrator::timeout() {
160 std::lock_guard<std::mutex> lock{mMutex};
161 itimerspec ts{};
162
163 if (timer_gettime(mTimer, &ts) < 0) {
164 ALOGE("Can not read timer!");
165 }
166
167 if (ts.it_value.tv_sec == 0 && ts.it_value.tv_nsec == 0) {
168 enable(false);
169 }
170}
171
172void Vibrator::timerCallback(union sigval sigval) {
173 static_cast<Vibrator*>(sigval.sival_ptr)->timeout();
174}
175
176const char* Vibrator::effectToName(Effect effect) {
177 return toString(effect).c_str();
178}
179
180uint32_t Vibrator::effectToMs(Effect effect) {
181 switch (effect) {
182 case Effect::CLICK:
183 return 10;
184 case Effect::DOUBLE_CLICK:
185 return 15;
186 case Effect::TICK:
187 return 5;
188 case Effect::THUD:
189 return 5;
190 case Effect::POP:
191 return 5;
192 case Effect::HEAVY_CLICK:
193 return 10;
194 case Effect::RINGTONE_1:
195 return 30000;
196 case Effect::RINGTONE_2:
197 return 30000;
198 case Effect::RINGTONE_3:
199 return 30000;
200 case Effect::RINGTONE_4:
201 return 30000;
202 case Effect::RINGTONE_5:
203 return 30000;
204 case Effect::RINGTONE_6:
205 return 30000;
206 case Effect::RINGTONE_7:
207 return 30000;
208 case Effect::RINGTONE_8:
209 return 30000;
210 case Effect::RINGTONE_9:
211 return 30000;
212 case Effect::RINGTONE_10:
213 return 30000;
214 case Effect::RINGTONE_11:
215 return 30000;
216 case Effect::RINGTONE_12:
217 return 30000;
218 case Effect::RINGTONE_13:
219 return 30000;
220 case Effect::RINGTONE_14:
221 return 30000;
222 case Effect::RINGTONE_15:
223 return 30000;
224 }
225}
226
227uint8_t Vibrator::strengthToAmplitude(EffectStrength strength) {
228 switch (strength) {
229 case EffectStrength::LIGHT:
230 return 128;
231 case EffectStrength::MEDIUM:
232 return 192;
233 case EffectStrength::STRONG:
234 return 255;
235 }
236}
237
238} // namespace implementation
239} // namespace V1_3
240} // namespace vibrator
241} // namespace hardware
242} // namespace android