Harpreet "Eli" Sangha | e863124 | 2019-01-31 15:43:36 +0900 | [diff] [blame] | 1 | /* |
| 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 | |
| 23 | namespace android { |
| 24 | namespace hardware { |
| 25 | namespace vibrator { |
| 26 | namespace V1_3 { |
| 27 | namespace implementation { |
| 28 | |
| 29 | static constexpr uint32_t MS_PER_S = 1000; |
| 30 | static constexpr uint32_t NS_PER_MS = 1000000; |
| 31 | |
| 32 | Vibrator::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 | |
| 46 | Return<Status> Vibrator::on(uint32_t timeoutMs) { |
| 47 | return activate(timeoutMs); |
| 48 | } |
| 49 | |
| 50 | Return<Status> Vibrator::off() { |
| 51 | return activate(0); |
| 52 | } |
| 53 | |
| 54 | Return<bool> Vibrator::supportsAmplitudeControl() { |
| 55 | return true; |
| 56 | } |
| 57 | |
| 58 | Return<Status> Vibrator::setAmplitude(uint8_t amplitude) { |
| 59 | ALOGI("Amplitude: %u -> %u\n", mAmplitude, amplitude); |
| 60 | mAmplitude = amplitude; |
| 61 | return Status::OK; |
| 62 | } |
| 63 | |
| 64 | Return<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 | |
| 70 | Return<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 Wright | a4c94fd | 2019-03-21 20:48:34 +0000 | [diff] [blame] | 77 | Return<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" Sangha | e863124 | 2019-01-31 15:43:36 +0900 | [diff] [blame] | 80 | } |
| 81 | |
| 82 | // Methods from ::android::hardware::vibrator::V1_3::IVibrator follow. |
| 83 | |
| 84 | Return<bool> Vibrator::supportsExternalControl() { |
| 85 | return true; |
| 86 | } |
| 87 | |
| 88 | Return<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 Wright | a4c94fd | 2019-03-21 20:48:34 +0000 | [diff] [blame] | 100 | Return<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" Sangha | a244321 | 2019-03-25 14:08:59 +0900 | [diff] [blame^] | 105 | ALOGI("Perform: Effect %s\n", effectToName(effect).c_str()); |
Michael Wright | a4c94fd | 2019-03-21 20:48:34 +0000 | [diff] [blame] | 106 | |
| 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" Sangha | e863124 | 2019-01-31 15:43:36 +0900 | [diff] [blame] | 118 | // Private methods follow. |
| 119 | |
| 120 | Status 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 | |
| 131 | Status 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 | |
| 164 | void 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 | |
| 177 | void Vibrator::timerCallback(union sigval sigval) { |
| 178 | static_cast<Vibrator*>(sigval.sival_ptr)->timeout(); |
| 179 | } |
| 180 | |
Harpreet "Eli" Sangha | a244321 | 2019-03-25 14:08:59 +0900 | [diff] [blame^] | 181 | const std::string Vibrator::effectToName(Effect effect) { |
| 182 | return toString(effect); |
Harpreet "Eli" Sangha | e863124 | 2019-01-31 15:43:36 +0900 | [diff] [blame] | 183 | } |
| 184 | |
| 185 | uint32_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 Wright | a4c94fd | 2019-03-21 20:48:34 +0000 | [diff] [blame] | 192 | case Effect::TEXTURE_TICK: |
Harpreet "Eli" Sangha | e863124 | 2019-01-31 15:43:36 +0900 | [diff] [blame] | 193 | 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 | |
| 233 | uint8_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 |