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 #pragma once
17 
18 #include <future>
19 
20 #include <aidl/android/hardware/vibrator/BnVibratorCallback.h>
21 #include <aidl/android/hardware/vibrator/IVibrator.h>
22 #include <aidl/android/hardware/vibrator/IVibratorManager.h>
23 #include <android/binder_manager.h>
24 #include <android/binder_process.h>
25 #include <android/hardware/vibrator/1.3/IVibrator.h>
26 
27 #include "IdlCli.h"
28 #include "utils.h"
29 
30 namespace android {
31 
32 using hardware::Return;
33 using idlcli::IdlCli;
34 
35 static constexpr int NUM_TRIES = 2;
36 
37 // Creates a Return<R> with STATUS::EX_NULL_POINTER.
38 template <class R>
NullptrStatus()39 inline R NullptrStatus() {
40     using ::android::hardware::Status;
41     return Status::fromExceptionCode(Status::EX_NULL_POINTER);
42 }
43 
44 template <>
NullptrStatus()45 inline ndk::ScopedAStatus NullptrStatus() {
46     return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_NULL_POINTER));
47 }
48 
49 template <typename I>
getService(std::string name)50 inline auto getService(std::string name) {
51     const auto instance = std::string() + I::descriptor + "/" + name;
52     auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str()));
53     return I::fromBinder(vibBinder);
54 }
55 
56 template <>
57 inline auto getService<android::hardware::vibrator::V1_0::IVibrator>(std::string name) {
58     return android::hardware::vibrator::V1_0::IVibrator::getService(name);
59 }
60 
61 template <>
62 inline auto getService<android::hardware::vibrator::V1_1::IVibrator>(std::string name) {
63     return android::hardware::vibrator::V1_1::IVibrator::getService(name);
64 }
65 
66 template <>
67 inline auto getService<android::hardware::vibrator::V1_2::IVibrator>(std::string name) {
68     return android::hardware::vibrator::V1_2::IVibrator::getService(name);
69 }
70 
71 template <>
72 inline auto getService<android::hardware::vibrator::V1_3::IVibrator>(std::string name) {
73     return android::hardware::vibrator::V1_3::IVibrator::getService(name);
74 }
75 
76 template <typename I>
77 using shared_ptr = std::invoke_result_t<decltype(getService<I>)&, std::string>;
78 
79 template <typename I>
80 class HalWrapper {
81 public:
Create()82     static std::unique_ptr<HalWrapper> Create() {
83         // Assume that if getService returns a nullptr, HAL is not available on the
84         // device.
85         const auto name = IdlCli::Get().getName();
86         auto hal = getService<I>(name.empty() ? "default" : name);
87         return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
88     }
89 
90     template <class R, class... Args0, class... Args1>
call(R (I::* fn)(Args0...),Args1 &&...args1)91     R call(R (I::*fn)(Args0...), Args1&&... args1) {
92         return (*mHal.*fn)(std::forward<Args1>(args1)...);
93     }
94 
95 private:
HalWrapper(shared_ptr<I> && hal)96     HalWrapper(shared_ptr<I>&& hal) : mHal(std::move(hal)) {}
97 
98 private:
99     shared_ptr<I> mHal;
100 };
101 
102 template <typename I>
getHal()103 static auto getHal() {
104     static auto sHalWrapper = HalWrapper<I>::Create();
105     return sHalWrapper.get();
106 }
107 
108 template <class R, class I, class... Args0, class... Args1>
halCall(R (I::* fn)(Args0...),Args1 &&...args1)109 R halCall(R (I::*fn)(Args0...), Args1&&... args1) {
110     auto hal = getHal<I>();
111     return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
112 }
113 
114 namespace idlcli {
115 namespace vibrator {
116 
117 namespace V1_0 = ::android::hardware::vibrator::V1_0;
118 namespace V1_1 = ::android::hardware::vibrator::V1_1;
119 namespace V1_2 = ::android::hardware::vibrator::V1_2;
120 namespace V1_3 = ::android::hardware::vibrator::V1_3;
121 namespace aidl = ::aidl::android::hardware::vibrator;
122 
123 class VibratorCallback : public aidl::BnVibratorCallback {
124 public:
onComplete()125     ndk::ScopedAStatus onComplete() override {
126         mPromise.set_value();
127         return ndk::ScopedAStatus::ok();
128     }
waitForComplete()129     void waitForComplete() { mPromise.get_future().wait(); }
130 
131 private:
132     std::promise<void> mPromise;
133 };
134 
135 } // namespace vibrator
136 } // namespace idlcli
137 
138 } // namespace android
139