Loading services/core/jni/com_android_server_VibratorService.cpp +85 −71 Original line number Original line Diff line number Diff line Loading @@ -42,73 +42,86 @@ using IVibrator_1_1 = android::hardware::vibrator::V1_1::IVibrator; namespace android namespace android { { static sp<IVibrator> mHal; static constexpr int NUM_TRIES = 2; // Creates a Return<R> with STATUS::EX_NULL_POINTER. template<class R> inline Return<R> NullptrStatus() { using ::android::hardware::Status; return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)}; } // Helper used to transparently deal with the vibrator HAL becoming unavailable. template<class R, class I, class... Args0, class... Args1> Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) { // Assume that if getService returns a nullptr, HAL is not available on the // device. static sp<I> sHal = I::getService(); static bool sAvailable = sHal != nullptr; if (!sAvailable) { return NullptrStatus<R>(); } // Return<R> doesn't have a default constructor, so make a Return<R> with // STATUS::EX_NONE. using ::android::hardware::Status; Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)}; // Note that ret is guaranteed to be changed after this loop. for (int i = 0; i < NUM_TRIES; ++i) { ret = (sHal == nullptr) ? NullptrStatus<R>() : (*sHal.*fn)(std::forward<Args1>(args1)...); if (!ret.isOk()) { ALOGE("Failed to issue command to vibrator HAL. Retrying."); // Restoring connection to the HAL. sHal = I::tryGetService(); } } return ret; } static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) { { /* TODO(b/31632518) */ halCall(&IVibrator::ping).isOk(); if (mHal != nullptr) { return; } mHal = IVibrator::getService(); } } static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */) static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */) { { if (mHal != nullptr) { return halCall(&IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE; return JNI_TRUE; } else { return JNI_FALSE; } } } static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) { { if (mHal != nullptr) { Status retStatus = halCall(&IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR); Status retStatus = mHal->on(timeout_ms); if (retStatus != Status::OK) { if (retStatus != Status::OK) { ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); } } } else { ALOGW("Tried to vibrate but there is no vibrator device."); } } } static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) { { if (mHal != nullptr) { Status retStatus = halCall(&IVibrator::off).withDefault(Status::UNKNOWN_ERROR); Status retStatus = mHal->off(); if (retStatus != Status::OK) { if (retStatus != Status::OK) { ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); } } } else { ALOGW("Tried to stop vibrating but there is no vibrator device."); } } } static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) { static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) { if (mHal != nullptr) { return halCall(&IVibrator::supportsAmplitudeControl).withDefault(false); return mHal->supportsAmplitudeControl(); } else { ALOGW("Unable to get max vibration amplitude, there is no vibrator device."); } return false; } } static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { if (mHal != nullptr) { Status status = halCall(&IVibrator::setAmplitude, static_cast<uint32_t>(amplitude)) Status status = mHal->setAmplitude(static_cast<uint32_t>(amplitude)); .withDefault(Status::UNKNOWN_ERROR); if (status != Status::OK) { if (status != Status::OK) { ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", static_cast<uint32_t>(status)); static_cast<uint32_t>(status)); } } } else { ALOGW("Unable to set vibration amplitude, there is no vibrator device."); } } } static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) { static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) { if (mHal != nullptr) { Status status; Status status; uint32_t lengthMs; uint32_t lengthMs; auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { Loading @@ -121,16 +134,20 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", static_cast<int32_t>(effect)); static_cast<int32_t>(effect)); } else if (effect == static_cast<uint32_t>(Effect_1_1::TICK)) { } else if (effect == static_cast<uint32_t>(Effect_1_1::TICK)) { sp<IVibrator_1_1> hal_1_1 = IVibrator_1_1::castFrom(mHal); auto ret = halCall(&IVibrator_1_1::perform_1_1, static_cast<Effect_1_1>(effect), if (hal_1_1 != nullptr) { effectStrength, callback); hal_1_1->perform_1_1(static_cast<Effect_1_1>(effect), effectStrength, callback); if (!ret.isOk()) { } else { ALOGW("Failed to perform effect (%" PRId32 "), insufficient HAL version", ALOGW("Failed to perform effect (%" PRId32 "), insufficient HAL version", static_cast<int32_t>(effect)); static_cast<int32_t>(effect)); } } } else { } else { mHal->perform(static_cast<Effect>(effect), effectStrength, callback); auto ret = halCall(&IVibrator::perform, static_cast<Effect>(effect), effectStrength, callback); if (!ret.isOk()) { ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect)); } } } if (status == Status::OK) { if (status == Status::OK) { return lengthMs; return lengthMs; } else if (status != Status::UNSUPPORTED_OPERATION) { } else if (status != Status::UNSUPPORTED_OPERATION) { Loading @@ -141,9 +158,6 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength ", error=%" PRIu32 ").", static_cast<int64_t>(effect), ", error=%" PRIu32 ").", static_cast<int64_t>(effect), static_cast<int32_t>(strength), static_cast<uint32_t>(status)); static_cast<int32_t>(strength), static_cast<uint32_t>(status)); } } } else { ALOGW("Unable to perform haptic effect, there is no vibrator device."); } return -1; return -1; } } Loading Loading
services/core/jni/com_android_server_VibratorService.cpp +85 −71 Original line number Original line Diff line number Diff line Loading @@ -42,73 +42,86 @@ using IVibrator_1_1 = android::hardware::vibrator::V1_1::IVibrator; namespace android namespace android { { static sp<IVibrator> mHal; static constexpr int NUM_TRIES = 2; // Creates a Return<R> with STATUS::EX_NULL_POINTER. template<class R> inline Return<R> NullptrStatus() { using ::android::hardware::Status; return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)}; } // Helper used to transparently deal with the vibrator HAL becoming unavailable. template<class R, class I, class... Args0, class... Args1> Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) { // Assume that if getService returns a nullptr, HAL is not available on the // device. static sp<I> sHal = I::getService(); static bool sAvailable = sHal != nullptr; if (!sAvailable) { return NullptrStatus<R>(); } // Return<R> doesn't have a default constructor, so make a Return<R> with // STATUS::EX_NONE. using ::android::hardware::Status; Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)}; // Note that ret is guaranteed to be changed after this loop. for (int i = 0; i < NUM_TRIES; ++i) { ret = (sHal == nullptr) ? NullptrStatus<R>() : (*sHal.*fn)(std::forward<Args1>(args1)...); if (!ret.isOk()) { ALOGE("Failed to issue command to vibrator HAL. Retrying."); // Restoring connection to the HAL. sHal = I::tryGetService(); } } return ret; } static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) { { /* TODO(b/31632518) */ halCall(&IVibrator::ping).isOk(); if (mHal != nullptr) { return; } mHal = IVibrator::getService(); } } static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */) static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */) { { if (mHal != nullptr) { return halCall(&IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE; return JNI_TRUE; } else { return JNI_FALSE; } } } static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) { { if (mHal != nullptr) { Status retStatus = halCall(&IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR); Status retStatus = mHal->on(timeout_ms); if (retStatus != Status::OK) { if (retStatus != Status::OK) { ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); } } } else { ALOGW("Tried to vibrate but there is no vibrator device."); } } } static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) { { if (mHal != nullptr) { Status retStatus = halCall(&IVibrator::off).withDefault(Status::UNKNOWN_ERROR); Status retStatus = mHal->off(); if (retStatus != Status::OK) { if (retStatus != Status::OK) { ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); } } } else { ALOGW("Tried to stop vibrating but there is no vibrator device."); } } } static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) { static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) { if (mHal != nullptr) { return halCall(&IVibrator::supportsAmplitudeControl).withDefault(false); return mHal->supportsAmplitudeControl(); } else { ALOGW("Unable to get max vibration amplitude, there is no vibrator device."); } return false; } } static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { if (mHal != nullptr) { Status status = halCall(&IVibrator::setAmplitude, static_cast<uint32_t>(amplitude)) Status status = mHal->setAmplitude(static_cast<uint32_t>(amplitude)); .withDefault(Status::UNKNOWN_ERROR); if (status != Status::OK) { if (status != Status::OK) { ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", static_cast<uint32_t>(status)); static_cast<uint32_t>(status)); } } } else { ALOGW("Unable to set vibration amplitude, there is no vibrator device."); } } } static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) { static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) { if (mHal != nullptr) { Status status; Status status; uint32_t lengthMs; uint32_t lengthMs; auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { Loading @@ -121,16 +134,20 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")", static_cast<int32_t>(effect)); static_cast<int32_t>(effect)); } else if (effect == static_cast<uint32_t>(Effect_1_1::TICK)) { } else if (effect == static_cast<uint32_t>(Effect_1_1::TICK)) { sp<IVibrator_1_1> hal_1_1 = IVibrator_1_1::castFrom(mHal); auto ret = halCall(&IVibrator_1_1::perform_1_1, static_cast<Effect_1_1>(effect), if (hal_1_1 != nullptr) { effectStrength, callback); hal_1_1->perform_1_1(static_cast<Effect_1_1>(effect), effectStrength, callback); if (!ret.isOk()) { } else { ALOGW("Failed to perform effect (%" PRId32 "), insufficient HAL version", ALOGW("Failed to perform effect (%" PRId32 "), insufficient HAL version", static_cast<int32_t>(effect)); static_cast<int32_t>(effect)); } } } else { } else { mHal->perform(static_cast<Effect>(effect), effectStrength, callback); auto ret = halCall(&IVibrator::perform, static_cast<Effect>(effect), effectStrength, callback); if (!ret.isOk()) { ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect)); } } } if (status == Status::OK) { if (status == Status::OK) { return lengthMs; return lengthMs; } else if (status != Status::UNSUPPORTED_OPERATION) { } else if (status != Status::UNSUPPORTED_OPERATION) { Loading @@ -141,9 +158,6 @@ static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength ", error=%" PRIu32 ").", static_cast<int64_t>(effect), ", error=%" PRIu32 ").", static_cast<int64_t>(effect), static_cast<int32_t>(strength), static_cast<uint32_t>(status)); static_cast<int32_t>(strength), static_cast<uint32_t>(status)); } } } else { ALOGW("Unable to perform haptic effect, there is no vibrator device."); } return -1; return -1; } } Loading