1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_OS_VIBRATORHALCONTROLLER_H 18 #define ANDROID_OS_VIBRATORHALCONTROLLER_H 19 20 #include <android-base/thread_annotations.h> 21 #include <android/hardware/vibrator/IVibrator.h> 22 23 #include <vibratorservice/VibratorCallbackScheduler.h> 24 #include <vibratorservice/VibratorHalWrapper.h> 25 26 namespace android { 27 28 namespace vibrator { 29 30 std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler); 31 32 template <typename T> 33 using HalFunction = std::function<T(HalWrapper*)>; 34 35 // Controller for Vibrator HAL handle. 36 // This relies on a given Connector to connect to the underlying Vibrator HAL service and reconnects 37 // after each failed api call. This also ensures connecting to the service is thread-safe. 38 class HalController { 39 public: 40 using Connector = 41 std::function<std::shared_ptr<HalWrapper>(std::shared_ptr<CallbackScheduler>)>; 42 HalController()43 HalController() : HalController(std::make_shared<CallbackScheduler>(), &connectHal) {} HalController(std::shared_ptr<CallbackScheduler> callbackScheduler,Connector connector)44 HalController(std::shared_ptr<CallbackScheduler> callbackScheduler, Connector connector) 45 : mConnector(connector), 46 mConnectedHal(nullptr), 47 mCallbackScheduler(std::move(callbackScheduler)) {} 48 virtual ~HalController() = default; 49 50 /* Connects to the newest HAL version available, possibly waiting for the registered service to 51 * become available. This will automatically be called at the first API usage if it was not 52 * manually called beforehand. Calling this manually during the setup phase can avoid slowing 53 * the first API call later on. Returns true if any HAL version is available, false otherwise. 54 */ 55 virtual bool init(); 56 57 /* Reloads HAL service instance without waiting. This relies on the HAL version found by init() 58 * to rapidly reconnect to the specific HAL service, or defers to init() if it was never called. 59 */ 60 virtual void tryReconnect(); 61 62 /* Returns info loaded from the connected HAL. This allows partial results to be returned if any 63 * of the Info fields has failed, but also retried on any failure. 64 */ getInfo()65 Info getInfo() { 66 static Info sDefaultInfo = InfoCache().get(); 67 return apply<Info>([](HalWrapper* hal) { return hal->getInfo(); }, sDefaultInfo, "getInfo"); 68 } 69 70 /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the 71 * result has failed. Parameter functionName is for logging purposes. 72 */ 73 template <typename T> doWithRetry(const HalFunction<HalResult<T>> & halFn,const char * functionName)74 HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) { 75 return apply(halFn, HalResult<T>::unsupported(), functionName); 76 } 77 78 private: 79 static constexpr int MAX_RETRIES = 1; 80 81 Connector mConnector; 82 std::mutex mConnectedHalMutex; 83 // Shared pointer to allow local copies to be used by different threads. 84 std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex); 85 // Shared pointer to allow copies to be passed to possible recreated mConnectedHal instances. 86 std::shared_ptr<CallbackScheduler> mCallbackScheduler; 87 88 /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the 89 * result has failed. Given default value is returned when no HAL is available, and given 90 * function name is for logging purposes. 91 */ 92 template <typename T> apply(const HalFunction<T> & halFn,T defaultValue,const char * functionName)93 T apply(const HalFunction<T>& halFn, T defaultValue, const char* functionName) { 94 if (!init()) { 95 ALOGV("Skipped %s because Vibrator HAL is not available", functionName); 96 return defaultValue; 97 } 98 std::shared_ptr<HalWrapper> hal; 99 { 100 std::lock_guard<std::mutex> lock(mConnectedHalMutex); 101 hal = mConnectedHal; 102 } 103 104 for (int i = 0; i < MAX_RETRIES; i++) { 105 T result = halFn(hal.get()); 106 if (result.checkAndLogFailure(functionName)) { 107 tryReconnect(); 108 } else { 109 return result; 110 } 111 } 112 113 return halFn(hal.get()); 114 } 115 }; 116 117 }; // namespace vibrator 118 119 }; // namespace android 120 121 #endif // ANDROID_OS_VIBRATORHALCONTROLLER_H 122