Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d6d2c148 authored by Tri Vo's avatar Tri Vo Committed by Android (Google) Code Review
Browse files

Merge "Fwk vibrator server handles vibrator hal dying." into oc-dr1-dev

parents 6e086877 a92c154d
Loading
Loading
Loading
Loading
+85 −71
Original line number Original line Diff line number Diff line
@@ -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) {
@@ -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) {
@@ -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;
}
}