1 /*
2 * Copyright (C) 2009 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 <android/hardware/vibrator/1.3/IVibrator.h>
20 #include <android/hardware/vibrator/BnVibratorCallback.h>
21 #include <android/hardware/vibrator/IVibrator.h>
22 #include <binder/IServiceManager.h>
23
24 #include "jni.h"
25 #include <nativehelper/JNIHelp.h>
26 #include "android_runtime/AndroidRuntime.h"
27 #include "core_jni_helpers.h"
28
29 #include <utils/misc.h>
30 #include <utils/Log.h>
31 #include <hardware/vibrator.h>
32
33 #include <inttypes.h>
34 #include <stdio.h>
35
36 using android::hardware::Return;
37 using android::hardware::Void;
38 using android::hardware::vibrator::V1_0::EffectStrength;
39 using android::hardware::vibrator::V1_0::Status;
40 using android::hardware::vibrator::V1_1::Effect_1_1;
41
42 namespace V1_0 = android::hardware::vibrator::V1_0;
43 namespace V1_1 = android::hardware::vibrator::V1_1;
44 namespace V1_2 = android::hardware::vibrator::V1_2;
45 namespace V1_3 = android::hardware::vibrator::V1_3;
46 namespace aidl = android::hardware::vibrator;
47
48 namespace android {
49
50 static jmethodID sMethodIdOnComplete;
51
52 static struct {
53 jfieldID id;
54 jfieldID scale;
55 jfieldID delay;
56 } gPrimitiveClassInfo;
57
58 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
59 static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
60 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
61 static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
62 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
63 static_cast<uint8_t>(aidl::EffectStrength::STRONG));
64
65 static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
66 static_cast<uint8_t>(aidl::Effect::CLICK));
67 static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
68 static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
69 static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) ==
70 static_cast<uint8_t>(aidl::Effect::TICK));
71 static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) ==
72 static_cast<uint8_t>(aidl::Effect::THUD));
73 static_assert(static_cast<uint8_t>(V1_3::Effect::POP) ==
74 static_cast<uint8_t>(aidl::Effect::POP));
75 static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
76 static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
77 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
78 static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
79 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
80 static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
81 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
82 static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
83 static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
84 static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
85
86 class VibratorCallback {
87 public:
VibratorCallback(JNIEnv * env,jobject vibration)88 VibratorCallback(JNIEnv *env, jobject vibration) :
89 mVibration(MakeGlobalRefOrDie(env, vibration)) {}
90
~VibratorCallback()91 ~VibratorCallback() {
92 JNIEnv *env = AndroidRuntime::getJNIEnv();
93 env->DeleteGlobalRef(mVibration);
94 }
95
onComplete()96 void onComplete() {
97 auto env = AndroidRuntime::getJNIEnv();
98 env->CallVoidMethod(mVibration, sMethodIdOnComplete);
99 }
100
101 private:
102 jobject mVibration;
103 };
104
105 class AidlVibratorCallback : public aidl::BnVibratorCallback {
106 public:
AidlVibratorCallback(JNIEnv * env,jobject vibration)107 AidlVibratorCallback(JNIEnv *env, jobject vibration) :
108 mCb(env, vibration) {}
109
onComplete()110 binder::Status onComplete() override {
111 mCb.onComplete();
112 return binder::Status::ok(); // oneway, local call
113 }
114
115 private:
116 VibratorCallback mCb;
117 };
118
119 static constexpr int NUM_TRIES = 2;
120
121 template<class R>
NoneStatus()122 inline R NoneStatus() {
123 using ::android::hardware::Status;
124 return Status::fromExceptionCode(Status::EX_NONE);
125 }
126
127 template<>
NoneStatus()128 inline binder::Status NoneStatus() {
129 using binder::Status;
130 return Status::fromExceptionCode(Status::EX_NONE);
131 }
132
133 // Creates a Return<R> with STATUS::EX_NULL_POINTER.
134 template<class R>
NullptrStatus()135 inline R NullptrStatus() {
136 using ::android::hardware::Status;
137 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
138 }
139
140 template<>
NullptrStatus()141 inline binder::Status NullptrStatus() {
142 using binder::Status;
143 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
144 }
145
146 template <typename I>
getService()147 sp<I> getService() {
148 return I::getService();
149 }
150
151 template <>
getService()152 sp<aidl::IVibrator> getService() {
153 return waitForVintfService<aidl::IVibrator>();
154 }
155
156 template <typename I>
tryGetService()157 sp<I> tryGetService() {
158 return I::tryGetService();
159 }
160
161 template <>
tryGetService()162 sp<aidl::IVibrator> tryGetService() {
163 return checkVintfService<aidl::IVibrator>();
164 }
165
166 template <typename I>
167 class HalWrapper {
168 public:
Create()169 static std::unique_ptr<HalWrapper> Create() {
170 // Assume that if getService returns a nullptr, HAL is not available on the
171 // device.
172 auto hal = getService<I>();
173 return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
174 }
175
176 // Helper used to transparently deal with the vibrator HAL becoming unavailable.
177 template<class R, class... Args0, class... Args1>
call(R (I::* fn)(Args0...),Args1 &&...args1)178 R call(R (I::* fn)(Args0...), Args1&&... args1) {
179 // Return<R> doesn't have a default constructor, so make a Return<R> with
180 // STATUS::EX_NONE.
181 R ret{NoneStatus<R>()};
182
183 // Note that ret is guaranteed to be changed after this loop.
184 for (int i = 0; i < NUM_TRIES; ++i) {
185 ret = (mHal == nullptr) ? NullptrStatus<R>()
186 : (*mHal.*fn)(std::forward<Args1>(args1)...);
187
188 if (ret.isOk()) {
189 break;
190 }
191
192 ALOGE("Failed to issue command to vibrator HAL. Retrying.");
193
194 // Restoring connection to the HAL.
195 mHal = tryGetService<I>();
196 }
197 return ret;
198 }
199
200 private:
HalWrapper(sp<I> && hal)201 HalWrapper(sp<I> &&hal) : mHal(std::move(hal)) {}
202
203 private:
204 sp<I> mHal;
205 };
206
207 template <typename I>
getHal()208 static auto getHal() {
209 static auto sHalWrapper = HalWrapper<I>::Create();
210 return sHalWrapper.get();
211 }
212
213 template<class R, class I, class... Args0, class... Args1>
halCall(R (I::* fn)(Args0...),Args1 &&...args1)214 R halCall(R (I::* fn)(Args0...), Args1&&... args1) {
215 auto hal = getHal<I>();
216 return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
217 }
218
219 template<class R>
isValidEffect(jlong effect)220 bool isValidEffect(jlong effect) {
221 if (effect < 0) {
222 return false;
223 }
224 R val = static_cast<R>(effect);
225 auto iter = hardware::hidl_enum_range<R>();
226 return val >= *iter.begin() && val <= *std::prev(iter.end());
227 }
228
vibratorInit(JNIEnv * env,jclass clazz)229 static void vibratorInit(JNIEnv *env, jclass clazz)
230 {
231 if (auto hal = getHal<aidl::IVibrator>()) {
232 // IBinder::pingBinder isn't accessible as a pointer function
233 // but getCapabilities can serve the same purpose
234 int32_t cap;
235 hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
236 } else {
237 halCall(&V1_0::IVibrator::ping).isOk();
238 }
239 }
240
vibratorExists(JNIEnv *,jclass)241 static jboolean vibratorExists(JNIEnv* /* env */, jclass /* clazz */)
242 {
243 bool ok;
244
245 if (auto hal = getHal<aidl::IVibrator>()) {
246 // IBinder::pingBinder isn't accessible as a pointer function
247 // but getCapabilities can serve the same purpose
248 int32_t cap;
249 ok = hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
250 } else {
251 ok = halCall(&V1_0::IVibrator::ping).isOk();
252 }
253 return ok ? JNI_TRUE : JNI_FALSE;
254 }
255
vibratorOn(JNIEnv *,jclass,jlong timeout_ms)256 static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms)
257 {
258 if (auto hal = getHal<aidl::IVibrator>()) {
259 auto status = hal->call(&aidl::IVibrator::on, timeout_ms, nullptr);
260 if (!status.isOk()) {
261 ALOGE("vibratorOn command failed: %s", status.toString8().string());
262 }
263 } else {
264 Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
265 if (retStatus != Status::OK) {
266 ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
267 }
268 }
269 }
270
vibratorOff(JNIEnv *,jclass)271 static void vibratorOff(JNIEnv* /* env */, jclass /* clazz */)
272 {
273 if (auto hal = getHal<aidl::IVibrator>()) {
274 auto status = hal->call(&aidl::IVibrator::off);
275 if (!status.isOk()) {
276 ALOGE("vibratorOff command failed: %s", status.toString8().string());
277 }
278 } else {
279 Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
280 if (retStatus != Status::OK) {
281 ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
282 }
283 }
284 }
285
vibratorSupportsAmplitudeControl(JNIEnv *,jclass)286 static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jclass) {
287 if (auto hal = getHal<aidl::IVibrator>()) {
288 int32_t cap = 0;
289 if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
290 return false;
291 }
292 return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0;
293 } else {
294 return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
295 }
296 }
297
vibratorSetAmplitude(JNIEnv *,jclass,jint amplitude)298 static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) {
299 if (auto hal = getHal<aidl::IVibrator>()) {
300 auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, static_cast<float>(amplitude) / UINT8_MAX);
301 if (!status.isOk()) {
302 ALOGE("Failed to set vibrator amplitude: %s", status.toString8().string());
303 }
304 } else {
305 Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
306 .withDefault(Status::UNKNOWN_ERROR);
307 if (status != Status::OK) {
308 ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
309 static_cast<uint32_t>(status));
310 }
311 }
312 }
313
vibratorSupportsExternalControl(JNIEnv *,jclass)314 static jboolean vibratorSupportsExternalControl(JNIEnv*, jclass) {
315 if (auto hal = getHal<aidl::IVibrator>()) {
316 int32_t cap = 0;
317 if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
318 return false;
319 }
320 return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0;
321 } else {
322 return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
323 }
324 }
325
vibratorSetExternalControl(JNIEnv *,jclass,jboolean enabled)326 static void vibratorSetExternalControl(JNIEnv*, jclass, jboolean enabled) {
327 if (auto hal = getHal<aidl::IVibrator>()) {
328 auto status = hal->call(&aidl::IVibrator::IVibrator::setExternalControl, enabled);
329 if (!status.isOk()) {
330 ALOGE("Failed to set vibrator external control: %s", status.toString8().string());
331 }
332 } else {
333 Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
334 .withDefault(Status::UNKNOWN_ERROR);
335 if (status != Status::OK) {
336 ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
337 static_cast<uint32_t>(status));
338 }
339 }
340 }
341
vibratorGetSupportedEffects(JNIEnv * env,jclass)342 static jintArray vibratorGetSupportedEffects(JNIEnv *env, jclass) {
343 if (auto hal = getHal<aidl::IVibrator>()) {
344 std::vector<aidl::Effect> supportedEffects;
345 if (!hal->call(&aidl::IVibrator::getSupportedEffects, &supportedEffects).isOk()) {
346 return nullptr;
347 }
348 jintArray arr = env->NewIntArray(supportedEffects.size());
349 env->SetIntArrayRegion(arr, 0, supportedEffects.size(),
350 reinterpret_cast<jint*>(supportedEffects.data()));
351 return arr;
352 } else {
353 return nullptr;
354 }
355 }
356
vibratorPerformEffect(JNIEnv * env,jclass,jlong effect,jlong strength,jobject vibration,jboolean withCallback)357 static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength,
358 jobject vibration, jboolean withCallback) {
359 if (auto hal = getHal<aidl::IVibrator>()) {
360 int32_t lengthMs;
361 sp<AidlVibratorCallback> effectCallback =
362 (withCallback != JNI_FALSE ? new AidlVibratorCallback(env, vibration) : nullptr);
363 aidl::Effect effectType(static_cast<aidl::Effect>(effect));
364 aidl::EffectStrength effectStrength(static_cast<aidl::EffectStrength>(strength));
365
366 auto status = hal->call(&aidl::IVibrator::perform, effectType, effectStrength, effectCallback, &lengthMs);
367 if (!status.isOk()) {
368 if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
369 ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
370 ": %s", static_cast<int64_t>(effect), static_cast<int32_t>(strength), status.toString8().string());
371 }
372 return -1;
373 }
374 return lengthMs;
375 } else {
376 Status status;
377 uint32_t lengthMs;
378 auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
379 status = retStatus;
380 lengthMs = retLengthMs;
381 };
382 EffectStrength effectStrength(static_cast<EffectStrength>(strength));
383
384 Return<void> ret;
385 if (isValidEffect<V1_0::Effect>(effect)) {
386 ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
387 effectStrength, callback);
388 } else if (isValidEffect<Effect_1_1>(effect)) {
389 ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
390 effectStrength, callback);
391 } else if (isValidEffect<V1_2::Effect>(effect)) {
392 ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
393 effectStrength, callback);
394 } else if (isValidEffect<V1_3::Effect>(effect)) {
395 ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
396 effectStrength, callback);
397 } else {
398 ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
399 static_cast<int32_t>(effect));
400 return -1;
401 }
402
403 if (!ret.isOk()) {
404 ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
405 return -1;
406 }
407
408 if (status == Status::OK) {
409 return lengthMs;
410 } else if (status != Status::UNSUPPORTED_OPERATION) {
411 // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
412 // doesn't have a pre-defined waveform to perform for it, so we should just give the
413 // opportunity to fall back to the framework waveforms.
414 ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
415 ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
416 static_cast<int32_t>(strength), static_cast<uint32_t>(status));
417 }
418 }
419
420 return -1;
421 }
422
effectFromJavaPrimitive(JNIEnv * env,jobject primitive)423 static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
424 aidl::CompositeEffect effect;
425 effect.primitive = static_cast<aidl::CompositePrimitive>(
426 env->GetIntField(primitive, gPrimitiveClassInfo.id));
427 effect.scale = static_cast<float>(env->GetFloatField(primitive, gPrimitiveClassInfo.scale));
428 effect.delayMs = static_cast<int>(env->GetIntField(primitive, gPrimitiveClassInfo.delay));
429 return effect;
430 }
431
vibratorPerformComposedEffect(JNIEnv * env,jclass,jobjectArray composition,jobject vibration)432 static void vibratorPerformComposedEffect(JNIEnv* env, jclass, jobjectArray composition,
433 jobject vibration) {
434 auto hal = getHal<aidl::IVibrator>();
435 if (!hal) {
436 return;
437 }
438 size_t size = env->GetArrayLength(composition);
439 std::vector<aidl::CompositeEffect> effects;
440 for (size_t i = 0; i < size; i++) {
441 jobject element = env->GetObjectArrayElement(composition, i);
442 effects.push_back(effectFromJavaPrimitive(env, element));
443 }
444 sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
445
446 auto status = hal->call(&aidl::IVibrator::compose, effects, effectCallback);
447 if (!status.isOk()) {
448 if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
449 ALOGE("Failed to play haptic effect composition");
450 }
451 }
452 }
453
vibratorGetCapabilities(JNIEnv *,jclass)454 static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
455 if (auto hal = getHal<aidl::IVibrator>()) {
456 int32_t cap = 0;
457 if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
458 return 0;
459 }
460 return cap;
461 }
462
463 return 0;
464 }
465
vibratorAlwaysOnEnable(JNIEnv * env,jclass,jlong id,jlong effect,jlong strength)466 static void vibratorAlwaysOnEnable(JNIEnv* env, jclass, jlong id, jlong effect, jlong strength) {
467 auto status = halCall(&aidl::IVibrator::alwaysOnEnable, id,
468 static_cast<aidl::Effect>(effect), static_cast<aidl::EffectStrength>(strength));
469 if (!status.isOk()) {
470 ALOGE("vibratortAlwaysOnEnable command failed (%s).", status.toString8().string());
471 }
472 }
473
vibratorAlwaysOnDisable(JNIEnv * env,jclass,jlong id)474 static void vibratorAlwaysOnDisable(JNIEnv* env, jclass, jlong id) {
475 auto status = halCall(&aidl::IVibrator::alwaysOnDisable, id);
476 if (!status.isOk()) {
477 ALOGE("vibratorAlwaysOnDisable command failed (%s).", status.toString8().string());
478 }
479 }
480
481 static const JNINativeMethod method_table[] = {
482 {"vibratorExists", "()Z", (void*)vibratorExists},
483 {"vibratorInit", "()V", (void*)vibratorInit},
484 {"vibratorOn", "(J)V", (void*)vibratorOn},
485 {"vibratorOff", "()V", (void*)vibratorOff},
486 {"vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
487 {"vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
488 {"vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;Z)J",
489 (void*)vibratorPerformEffect},
490 {"vibratorPerformComposedEffect",
491 "([Landroid/os/VibrationEffect$Composition$PrimitiveEffect;Lcom/android/server/"
492 "VibratorService$Vibration;)V",
493 (void*)vibratorPerformComposedEffect},
494 {"vibratorGetSupportedEffects", "()[I", (void*)vibratorGetSupportedEffects},
495 {"vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
496 {"vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
497 {"vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
498 {"vibratorAlwaysOnEnable", "(JJJ)V", (void*)vibratorAlwaysOnEnable},
499 {"vibratorAlwaysOnDisable", "(J)V", (void*)vibratorAlwaysOnDisable},
500 };
501
register_android_server_VibratorService(JNIEnv * env)502 int register_android_server_VibratorService(JNIEnv *env) {
503 sMethodIdOnComplete = GetMethodIDOrDie(env,
504 FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),
505 "onComplete", "()V");
506 jclass primitiveClass = FindClassOrDie(env,
507 "android/os/VibrationEffect$Composition$PrimitiveEffect");
508 gPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "id", "I");
509 gPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "scale", "F");
510 gPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "delay", "I");
511 return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
512 method_table, NELEM(method_table));
513 }
514
515 };
516