• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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