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