1 /*
2  * Copyright (C) 2019 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 #ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
17 #define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
18 
19 #include <aidl/android/hardware/vibrator/IVibrator.h>
20 #include <android/binder_manager.h>
21 #include <android/hardware/vibrator/1.3/IVibrator.h>
22 
23 #include "utils.h"
24 
25 #include "log/log.h"
26 
27 namespace android {
28 
29 using hardware::Return;
30 
31 static constexpr int NUM_TRIES = 2;
32 
33 // Creates a Return<R> with STATUS::EX_NULL_POINTER.
34 template <class R>
NullptrStatus()35 inline R NullptrStatus() {
36     using ::android::hardware::Status;
37     return Status::fromExceptionCode(Status::EX_NULL_POINTER);
38 }
39 
40 template <>
NullptrStatus()41 inline ndk::ScopedAStatus NullptrStatus() {
42     return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_NULL_POINTER));
43 }
44 
45 template <typename I>
getService()46 inline auto getService() {
47     return I::getService();
48 }
49 
50 template <>
51 inline auto getService<aidl::android::hardware::vibrator::IVibrator>() {
52     const auto instance =
53             std::string() + aidl::android::hardware::vibrator::IVibrator::descriptor + "/default";
54     auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str()));
55     return aidl::android::hardware::vibrator::IVibrator::fromBinder(vibBinder);
56 }
57 
58 template <typename I>
59 using shared_ptr = std::result_of_t<decltype(getService<I>)&()>;
60 
61 template <typename I>
62 class HalWrapper {
63 public:
Create()64     static std::unique_ptr<HalWrapper> Create() {
65         // Assume that if getService returns a nullptr, HAL is not available on the
66         // device.
67         auto hal = getService<I>();
68         return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
69     }
70 
71     template <class R, class... Args0, class... Args1>
call(R (I::* fn)(Args0...),Args1 &&...args1)72     R call(R (I::*fn)(Args0...), Args1&&... args1) {
73         return (*mHal.*fn)(std::forward<Args1>(args1)...);
74     }
75 
76 private:
HalWrapper(shared_ptr<I> && hal)77     HalWrapper(shared_ptr<I>&& hal) : mHal(std::move(hal)) {}
78 
79 private:
80     shared_ptr<I> mHal;
81 };
82 
83 template <typename I>
getHal()84 static auto getHal() {
85     static auto sHalWrapper = HalWrapper<I>::Create();
86     return sHalWrapper.get();
87 }
88 
89 template <class R, class I, class... Args0, class... Args1>
halCall(R (I::* fn)(Args0...),Args1 &&...args1)90 R halCall(R (I::*fn)(Args0...), Args1&&... args1) {
91     auto hal = getHal<I>();
92     return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
93 }
94 
95 namespace idlcli {
96 namespace vibrator {
97 
98 namespace V1_0 = ::android::hardware::vibrator::V1_0;
99 namespace V1_1 = ::android::hardware::vibrator::V1_1;
100 namespace V1_2 = ::android::hardware::vibrator::V1_2;
101 namespace V1_3 = ::android::hardware::vibrator::V1_3;
102 namespace aidl = ::aidl::android::hardware::vibrator;
103 
104 } // namespace vibrator
105 } // namespace idlcli
106 
107 } // namespace android
108 
109 #endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
110