From e0b7951d632a5334f17b7e16cdf4bc4cfe9b2196 Mon Sep 17 00:00:00 2001 From: "Harpreet \\\"Eli\\\" Sangha" Date: Mon, 2 Sep 2019 14:21:49 +0900 Subject: [PATCH] Vibrator Service: Allow HAL Version Checking Broke up the halCall() API into two components, one that implements the initial service retrieval and one that implements the retry on connection loss. This allows the service retrival API to double as test for supported version with little overhead. Test: Manually via CLI Change-Id: I12cf8838e933187d473157c9576d1b13b03913d4 Signed-off-by: Harpreet \"Eli\" Sangha --- .../com_android_server_VibratorService.cpp | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) 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