diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp index d5fbd2b316e76..7aa9c7cce8765 100644 --- a/services/core/jni/com_android_server_VibratorService.cpp +++ b/services/core/jni/com_android_server_VibratorService.cpp @@ -56,37 +56,57 @@ inline Return NullptrStatus() { return Return{Status::fromExceptionCode(Status::EX_NULL_POINTER)}; } -// Helper used to transparently deal with the vibrator HAL becoming unavailable. +template +class HalWrapper { + public: + static std::unique_ptr Create() { + // Assume that if getService returns a nullptr, HAL is not available on the + // device. + auto hal = I::getService(); + return hal ? std::unique_ptr(new HalWrapper(std::move(hal))) : nullptr; + } + + // Helper used to transparently deal with the vibrator HAL becoming unavailable. + template + Return call(Return (I::* fn)(Args0...), Args1&&... args1) { + // Return doesn't have a default constructor, so make a Return with + // STATUS::EX_NONE. + using ::android::hardware::Status; + Return 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 = (mHal == nullptr) ? NullptrStatus() + : (*mHal.*fn)(std::forward(args1)...); + + if (ret.isOk()) { + break; + } + + ALOGE("Failed to issue command to vibrator HAL. Retrying."); + // Restoring connection to the HAL. + mHal = I::tryGetService(); + } + return ret; + } + + private: + HalWrapper(sp &&hal) : mHal(std::move(hal)) {} + + private: + sp mHal; +}; + +template +static auto getHal() { + static auto sHalWrapper = HalWrapper::Create(); + return sHalWrapper.get(); +} + template Return halCall(Return (I::* fn)(Args0...), Args1&&... args1) { - // Assume that if getService returns a nullptr, HAL is not available on the - // device. - static sp sHal = I::getService(); - static bool sAvailable = sHal != nullptr; - - if (!sAvailable) { - return NullptrStatus(); - } - - // Return doesn't have a default constructor, so make a Return with - // STATUS::EX_NONE. - using ::android::hardware::Status; - Return 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() - : (*sHal.*fn)(std::forward(args1)...); - - if (ret.isOk()) { - break; - } - - ALOGE("Failed to issue command to vibrator HAL. Retrying."); - // Restoring connection to the HAL. - sHal = I::tryGetService(); - } - return ret; + auto hal = getHal(); + return hal ? hal->call(fn, std::forward(args1)...) : NullptrStatus(); } template