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 // TODO(b/308452413): remove this file once android.os.vibrator.remove_hidl_support is removed 18 19 #ifndef ANDROID_OS_VIBRATORHALCONTROLLER_H 20 #define ANDROID_OS_VIBRATORHALCONTROLLER_H 21 22 #include <aidl/android/hardware/vibrator/IVibrator.h> 23 #include <android-base/thread_annotations.h> 24 25 #include <vibratorservice/VibratorCallbackScheduler.h> 26 #include <vibratorservice/VibratorHalWrapper.h> 27 28 namespace android { 29 30 namespace vibrator { 31 32 std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler); 33 34 template <typename T> 35 using HalFunction = std::function<T(HalWrapper*)>; 36 37 // Controller for Vibrator HAL handle. 38 // This relies on a given Connector to connect to the underlying Vibrator HAL service and reconnects 39 // after each failed api call. This also ensures connecting to the service is thread-safe. 40 class HalController { 41 public: 42 using Connector = 43 std::function<std::shared_ptr<HalWrapper>(std::shared_ptr<CallbackScheduler>)>; 44 HalController()45 HalController() : HalController(std::make_shared<CallbackScheduler>(), &connectHal) {} HalController(std::shared_ptr<CallbackScheduler> callbackScheduler,Connector connector)46 HalController(std::shared_ptr<CallbackScheduler> callbackScheduler, Connector connector) 47 : mConnector(connector), 48 mConnectedHal(nullptr), 49 mCallbackScheduler(std::move(callbackScheduler)) {} 50 virtual ~HalController() = default; 51 52 /* Connects to the newest HAL version available, possibly waiting for the registered service to 53 * become available. This will automatically be called at the first API usage if it was not 54 * manually called beforehand. Calling this manually during the setup phase can avoid slowing 55 * the first API call later on. Returns true if any HAL version is available, false otherwise. 56 */ 57 virtual bool init(); 58 59 /* Reloads HAL service instance without waiting. This relies on the HAL version found by init() 60 * to rapidly reconnect to the specific HAL service, or defers to init() if it was never called. 61 */ 62 virtual void tryReconnect(); 63 64 /* Returns info loaded from the connected HAL. This allows partial results to be returned if any 65 * of the Info fields has failed, but also retried on any failure. 66 */ getInfo()67 Info getInfo() { 68 static Info sDefaultInfo = InfoCache().get(); 69 if (!init()) { 70 ALOGV("Skipped getInfo because Vibrator HAL is not available"); 71 return sDefaultInfo; 72 } 73 std::shared_ptr<HalWrapper> hal; 74 { 75 std::lock_guard<std::mutex> lock(mConnectedHalMutex); 76 hal = mConnectedHal; 77 } 78 79 for (int i = 0; i < MAX_RETRIES; i++) { 80 Info result = hal.get()->getInfo(); 81 result.logFailures(); 82 if (result.shouldRetry()) { 83 tryReconnect(); 84 } else { 85 return result; 86 } 87 } 88 89 Info result = hal.get()->getInfo(); 90 result.logFailures(); 91 return result; 92 } 93 94 /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the 95 * result has failed. Parameter functionName is for logging purposes. 96 */ 97 template <typename T> doWithRetry(const HalFunction<HalResult<T>> & halFn,const char * functionName)98 HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, const char* functionName) { 99 return doWithRetry<T>(halFn, HalResult<T>::unsupported(), functionName); 100 } 101 102 private: 103 static constexpr int MAX_RETRIES = 1; 104 105 Connector mConnector; 106 std::mutex mConnectedHalMutex; 107 // Shared pointer to allow local copies to be used by different threads. 108 std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex); 109 // Shared pointer to allow copies to be passed to possible recreated mConnectedHal instances. 110 std::shared_ptr<CallbackScheduler> mCallbackScheduler; 111 112 /* Calls given HAL function, applying automatic retries to reconnect with the HAL when the 113 * result has failed. Given default value is returned when no HAL is available, and given 114 * function name is for logging purposes. 115 */ 116 template <typename T> doWithRetry(const HalFunction<HalResult<T>> & halFn,HalResult<T> defaultValue,const char * functionName)117 HalResult<T> doWithRetry(const HalFunction<HalResult<T>>& halFn, HalResult<T> defaultValue, 118 const char* functionName) { 119 if (!init()) { 120 ALOGV("Skipped %s because Vibrator HAL is not available", functionName); 121 return defaultValue; 122 } 123 std::shared_ptr<HalWrapper> hal; 124 { 125 std::lock_guard<std::mutex> lock(mConnectedHalMutex); 126 hal = mConnectedHal; 127 } 128 129 HalResult<T> result = doOnce(hal.get(), halFn, functionName); 130 for (int i = 0; i < MAX_RETRIES && result.shouldRetry(); i++) { 131 tryReconnect(); 132 result = doOnce(hal.get(), halFn, functionName); 133 } 134 return result; 135 } 136 137 template <typename T> doOnce(HalWrapper * hal,const HalFunction<HalResult<T>> & halFn,const char * functionName)138 HalResult<T> doOnce(HalWrapper* hal, const HalFunction<HalResult<T>>& halFn, 139 const char* functionName) { 140 HalResult<T> result = halFn(hal); 141 if (result.isFailed()) { 142 ALOGE("Vibrator HAL %s failed: %s", functionName, result.errorMessage()); 143 } 144 return result; 145 } 146 }; 147 148 }; // namespace vibrator 149 150 }; // namespace android 151 152 #endif // ANDROID_OS_VIBRATORHALCONTROLLER_H 153