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