Cache results from Vibrator HAL getters in wrapper

Cache HAL capabilities and supported effects, since these values do not
change for the same underlying HAL.

Bug: 153418251
Test: atest libvibratorservice_test
Change-Id: I23b9480d23810debb065794071319003360857cb
diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp
index 04a8e6a..db27bd9 100644
--- a/services/vibratorservice/VibratorHalWrapper.cpp
+++ b/services/vibratorservice/VibratorHalWrapper.cpp
@@ -44,6 +44,18 @@
 // -------------------------------------------------------------------------------------------------
 
 template <class T>
+HalResult<T> loadCached(const std::function<HalResult<T>()>& loadFn, std::optional<T>& cache) {
+    if (cache.has_value()) {
+        return HalResult<T>::ok(cache.value());
+    }
+    HalResult<T> ret = loadFn();
+    if (ret.isOk()) {
+        cache.emplace(ret.value());
+    }
+    return ret;
+}
+
+template <class T>
 bool isStaticCastValid(Effect effect) {
     T castEffect = static_cast<T>(effect);
     auto iter = hardware::hidl_enum_range<T>();
@@ -214,15 +226,23 @@
 }
 
 HalResult<Capabilities> AidlHalWrapper::getCapabilities() {
-    int32_t capabilities = 0;
-    auto result = mHandle->getCapabilities(&capabilities);
-    return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
+    std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
+    static auto loadFn = [this]() {
+        int32_t capabilities = 0;
+        auto result = mHandle->getCapabilities(&capabilities);
+        return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
+    };
+    return loadCached<Capabilities>(loadFn, mCapabilities);
 }
 
 HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffects() {
-    std::vector<Effect> supportedEffects;
-    auto result = mHandle->getSupportedEffects(&supportedEffects);
-    return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
+    std::lock_guard<std::mutex> lock(mSupportedEffectsMutex);
+    static auto loadFn = [this]() {
+        std::vector<Effect> supportedEffects;
+        auto result = mHandle->getSupportedEffects(&supportedEffects);
+        return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
+    };
+    return loadCached<std::vector<Effect>>(loadFn, mSupportedEffects);
 }
 
 HalResult<milliseconds> AidlHalWrapper::performEffect(
@@ -279,10 +299,9 @@
 }
 
 HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilities() {
-    hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
-    Capabilities capabilities =
-            result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
-    return HalResult<Capabilities>::fromReturn(result, capabilities);
+    std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
+    return loadCached<Capabilities>(std::bind(&HidlHalWrapperV1_0::getCapabilitiesInternal, this),
+                                    mCapabilities);
 }
 
 HalResult<std::vector<Effect>> HidlHalWrapperV1_0::getSupportedEffects() {
@@ -308,6 +327,13 @@
     return HalResult<void>::unsupported();
 }
 
+HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilitiesInternal() {
+    hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
+    Capabilities capabilities =
+            result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
+    return HalResult<Capabilities>::fromReturn(result, capabilities);
+}
+
 // -------------------------------------------------------------------------------------------------
 
 HalResult<milliseconds> HidlHalWrapperV1_1::performEffect(Effect effect, EffectStrength strength,
@@ -355,19 +381,6 @@
     return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
 }
 
-HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilities() {
-    HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilities();
-    if (!parentResult.isOk()) {
-        // Loading for versions up to v1.2 already failed, so propagate failure.
-        return parentResult;
-    }
-
-    Capabilities capabilities = parentResult.value();
-    auto result = mHandleV1_3->supportsExternalControl();
-    capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
-    return HalResult<Capabilities>::fromReturn(result, capabilities);
-}
-
 HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(Effect effect, EffectStrength strength,
                                                           const std::function<void()>&) {
     if (isStaticCastValid<V1_0::Effect>(effect)) {
@@ -392,6 +405,19 @@
     return HalResult<milliseconds>::unsupported();
 }
 
+HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() {
+    HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilitiesInternal();
+    if (!parentResult.isOk()) {
+        // Loading for previous HAL versions already failed, so propagate failure.
+        return parentResult;
+    }
+
+    Capabilities capabilities = parentResult.value();
+    auto result = mHandleV1_3->supportsExternalControl();
+    capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
+    return HalResult<Capabilities>::fromReturn(result, capabilities);
+}
+
 // -------------------------------------------------------------------------------------------------
 
 }; // namespace vibrator