|  | /* | 
|  | * Copyright (C) 2019 The Android Open Source Project | 
|  | * | 
|  | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | * you may not use this file except in compliance with the License. | 
|  | * You may obtain a copy of the License at | 
|  | * | 
|  | *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | * | 
|  | * Unless required by applicable law or agreed to in writing, software | 
|  | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | * See the License for the specific language governing permissions and | 
|  | * limitations under the License. | 
|  | */ | 
|  | #ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_ | 
|  | #define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_ | 
|  |  | 
|  | #include <aidl/android/hardware/vibrator/IVibrator.h> | 
|  | #include <android/binder_manager.h> | 
|  | #include <android/hardware/vibrator/1.3/IVibrator.h> | 
|  |  | 
|  | #include "utils.h" | 
|  |  | 
|  | #include "log/log.h" | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | using hardware::Return; | 
|  |  | 
|  | static constexpr int NUM_TRIES = 2; | 
|  |  | 
|  | // Creates a Return<R> with STATUS::EX_NULL_POINTER. | 
|  | template <class R> | 
|  | inline R NullptrStatus() { | 
|  | using ::android::hardware::Status; | 
|  | return Status::fromExceptionCode(Status::EX_NULL_POINTER); | 
|  | } | 
|  |  | 
|  | template <> | 
|  | inline ndk::ScopedAStatus NullptrStatus() { | 
|  | return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_NULL_POINTER)); | 
|  | } | 
|  |  | 
|  | template <typename I> | 
|  | inline auto getService() { | 
|  | return I::getService(); | 
|  | } | 
|  |  | 
|  | template <> | 
|  | inline auto getService<aidl::android::hardware::vibrator::IVibrator>() { | 
|  | const auto instance = | 
|  | std::string() + aidl::android::hardware::vibrator::IVibrator::descriptor + "/default"; | 
|  | auto vibBinder = ndk::SpAIBinder(AServiceManager_getService(instance.c_str())); | 
|  | return aidl::android::hardware::vibrator::IVibrator::fromBinder(vibBinder); | 
|  | } | 
|  |  | 
|  | template <typename I> | 
|  | using shared_ptr = std::result_of_t<decltype(getService<I>)&()>; | 
|  |  | 
|  | template <typename I> | 
|  | class HalWrapper { | 
|  | public: | 
|  | static std::unique_ptr<HalWrapper> Create() { | 
|  | // Assume that if getService returns a nullptr, HAL is not available on the | 
|  | // device. | 
|  | auto hal = getService<I>(); | 
|  | return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr; | 
|  | } | 
|  |  | 
|  | template <class R, class... Args0, class... Args1> | 
|  | R call(R (I::*fn)(Args0...), Args1&&... args1) { | 
|  | return (*mHal.*fn)(std::forward<Args1>(args1)...); | 
|  | } | 
|  |  | 
|  | private: | 
|  | HalWrapper(shared_ptr<I>&& hal) : mHal(std::move(hal)) {} | 
|  |  | 
|  | private: | 
|  | shared_ptr<I> mHal; | 
|  | }; | 
|  |  | 
|  | template <typename I> | 
|  | static auto getHal() { | 
|  | static auto sHalWrapper = HalWrapper<I>::Create(); | 
|  | return sHalWrapper.get(); | 
|  | } | 
|  |  | 
|  | template <class R, class I, class... Args0, class... Args1> | 
|  | R halCall(R (I::*fn)(Args0...), Args1&&... args1) { | 
|  | auto hal = getHal<I>(); | 
|  | return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>(); | 
|  | } | 
|  |  | 
|  | namespace idlcli { | 
|  | namespace vibrator { | 
|  |  | 
|  | namespace V1_0 = ::android::hardware::vibrator::V1_0; | 
|  | namespace V1_1 = ::android::hardware::vibrator::V1_1; | 
|  | namespace V1_2 = ::android::hardware::vibrator::V1_2; | 
|  | namespace V1_3 = ::android::hardware::vibrator::V1_3; | 
|  | namespace aidl = ::aidl::android::hardware::vibrator; | 
|  |  | 
|  | } // namespace vibrator | 
|  | } // namespace idlcli | 
|  |  | 
|  | } // namespace android | 
|  |  | 
|  | #endif // FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_ |