Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 98c97036 authored by Lais Andrade's avatar Lais Andrade
Browse files

Add wrapper for IVibratorManager.aidl to native vibrator service

Add a new implementation of vibrator::ManagerHalWrapper that interacts
with the default IVibratorManager.aidl service.

Add getCapabilities() method to the wrapper, mapping to the constant
values from IVibratorManager.aidl.

This reuses the HalWrapper and HalController to ensure each individual
vibrator will be loaded and reloaded correctly from IVibratorManager.

Bug: 167946816
Test: atest libvibratorservice_test
Change-Id: I5311b4118a3bec5920317aa392a30d171fd80c81
parent c1322b26
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ cc_library_shared {
        "libhidlbase",
        "liblog",
        "libutils",
        "android.hardware.vibrator-cpp",
        "android.hardware.vibrator-unstable-cpp",
        "android.hardware.vibrator@1.0",
        "android.hardware.vibrator@1.1",
        "android.hardware.vibrator@1.2",
+5 −29
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
#define LOG_TAG "VibratorHalWrapper"

#include <android/hardware/vibrator/1.3/IVibrator.h>
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <hardware/vibrator.h>

@@ -72,17 +71,6 @@ const constexpr char* STATUS_T_ERROR_MESSAGE_PREFIX = "status_t = ";
const constexpr char* STATUS_V_1_0_ERROR_MESSAGE_PREFIX =
        "android::hardware::vibrator::V1_0::Status = ";

template <typename T>
HalResult<T> HalResult<T>::fromStatus(binder::Status status, T data) {
    if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
        return HalResult<T>::unsupported();
    }
    if (status.isOk()) {
        return HalResult<T>::ok(data);
    }
    return HalResult<T>::failed(std::string(status.toString8().c_str()));
}

template <typename T>
HalResult<T> HalResult<T>::fromStatus(V1_0::Status status, T data) {
    switch (status) {
@@ -145,28 +133,16 @@ HalResult<void> HalResult<void>::fromReturn(hardware::Return<R>& ret) {

// -------------------------------------------------------------------------------------------------

class HalCallbackWrapper : public Aidl::BnVibratorCallback {
public:
    HalCallbackWrapper(std::function<void()> completionCallback)
          : mCompletionCallback(completionCallback) {}

    binder::Status onComplete() override {
        mCompletionCallback();
        return binder::Status::ok();
    }

private:
    const std::function<void()> mCompletionCallback;
};

// -------------------------------------------------------------------------------------------------

HalResult<void> AidlHalWrapper::ping() {
    return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder());
}

void AidlHalWrapper::tryReconnect() {
    sp<Aidl::IVibrator> newHandle = checkVintfService<Aidl::IVibrator>();
    auto result = mReconnectFn();
    if (!result.isOk()) {
        return;
    }
    sp<Aidl::IVibrator> newHandle = result.value();
    if (newHandle) {
        std::lock_guard<std::mutex> lock(mHandleMutex);
        mHandle = std::move(newHandle);
+137 −1
Original line number Diff line number Diff line
@@ -20,11 +20,14 @@

#include <vibratorservice/VibratorManagerHalWrapper.h>

namespace Aidl = android::hardware::vibrator;

namespace android {

namespace vibrator {

constexpr int32_t SINGLE_VIBRATOR_ID = 0;
const constexpr char* MISSING_VIBRATOR_MESSAGE_PREFIX = "No vibrator with id=";

HalResult<void> LegacyManagerHalWrapper::ping() {
    return mController->ping();
@@ -34,6 +37,10 @@ void LegacyManagerHalWrapper::tryReconnect() {
    mController->tryReconnect();
}

HalResult<ManagerCapabilities> LegacyManagerHalWrapper::getCapabilities() {
    return HalResult<ManagerCapabilities>::ok(ManagerCapabilities::NONE);
}

HalResult<std::vector<int32_t>> LegacyManagerHalWrapper::getVibratorIds() {
    if (mController->init()) {
        return HalResult<std::vector<int32_t>>::ok(std::vector<int32_t>(1, SINGLE_VIBRATOR_ID));
@@ -47,7 +54,7 @@ HalResult<std::shared_ptr<HalController>> LegacyManagerHalWrapper::getVibrator(i
        return HalResult<std::shared_ptr<HalController>>::ok(mController);
    }
    // Controller.init did not connect to any vibrator HAL service, so the device has no vibrator.
    return HalResult<std::shared_ptr<HalController>>::failed("No vibrator with id = " +
    return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX +
                                                             std::to_string(id));
}

@@ -63,6 +70,135 @@ HalResult<void> LegacyManagerHalWrapper::cancelSynced() {
    return HalResult<void>::unsupported();
}

// -------------------------------------------------------------------------------------------------

std::shared_ptr<HalWrapper> AidlManagerHalWrapper::ManagedHalConnector::connect(
        std::shared_ptr<CallbackScheduler> callbackScheduler) {
    std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [&]() {
        sp<Aidl::IVibrator> vibrator;
        auto result = this->mManager->getHal()->getVibrator(this->mVibratorId, &vibrator);
        return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator);
    };
    auto result = reconnectFn();
    if (!result.isOk()) {
        return nullptr;
    }
    auto vibrator = result.value();
    if (!vibrator) {
        return nullptr;
    }
    return std::move(std::make_unique<AidlHalWrapper>(std::move(callbackScheduler),
                                                      std::move(vibrator), reconnectFn));
}

HalResult<void> AidlManagerHalWrapper::ping() {
    return HalResult<void>::fromStatus(IInterface::asBinder(getHal())->pingBinder());
}

void AidlManagerHalWrapper::tryReconnect() {
    sp<Aidl::IVibratorManager> newHandle = checkVintfService<Aidl::IVibratorManager>();
    if (newHandle) {
        std::lock_guard<std::mutex> lock(mHandleMutex);
        mHandle = std::move(newHandle);
    }
}

HalResult<ManagerCapabilities> AidlManagerHalWrapper::getCapabilities() {
    std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
    if (mCapabilities.has_value()) {
        // Return copy of cached value.
        return HalResult<ManagerCapabilities>::ok(*mCapabilities);
    }
    int32_t cap = 0;
    auto result = getHal()->getCapabilities(&cap);
    auto ret = HalResult<ManagerCapabilities>::fromStatus(result,
                                                          static_cast<ManagerCapabilities>(cap));
    if (ret.isOk()) {
        // Cache copy of returned value.
        mCapabilities.emplace(ret.value());
    }
    return ret;
}

HalResult<std::vector<int32_t>> AidlManagerHalWrapper::getVibratorIds() {
    std::lock_guard<std::mutex> lock(mVibratorsMutex);
    if (mVibratorIds.has_value()) {
        // Return copy of cached values.
        return HalResult<std::vector<int32_t>>::ok(*mVibratorIds);
    }
    std::vector<int32_t> ids;
    auto result = getHal()->getVibratorIds(&ids);
    auto ret = HalResult<std::vector<int32_t>>::fromStatus(result, ids);
    if (ret.isOk()) {
        // Cache copy of returned value and the individual controllers.
        mVibratorIds.emplace(ret.value());
        for (auto& id : ids) {
            auto connector = std::make_unique<ManagedHalConnector>(this, id);
            auto controller =
                    std::make_unique<HalController>(std::move(connector), mCallbackScheduler);
            mVibrators[id] = std::move(controller);
        }
    }
    return ret;
}

HalResult<std::shared_ptr<HalController>> AidlManagerHalWrapper::getVibrator(int32_t id) {
    // Make sure we cache vibrator ids and initialize the individual controllers.
    getVibratorIds();
    std::lock_guard<std::mutex> lock(mVibratorsMutex);
    auto it = mVibrators.find(id);
    if (it != mVibrators.end()) {
        return HalResult<std::shared_ptr<HalController>>::ok(it->second);
    }
    return HalResult<std::shared_ptr<HalController>>::failed(MISSING_VIBRATOR_MESSAGE_PREFIX +
                                                             std::to_string(id));
}

HalResult<void> AidlManagerHalWrapper::prepareSynced(const std::vector<int32_t>& ids) {
    auto ret = HalResult<void>::fromStatus(getHal()->prepareSynced(ids));
    if (ret.isOk()) {
        // Force reload of all vibrator controllers that were prepared for a sync operation here.
        // This will trigger calls to getVibrator(id) on each controller, so they can use the
        // latest service provided by this manager.
        std::lock_guard<std::mutex> lock(mVibratorsMutex);
        for (auto& id : ids) {
            auto it = mVibrators.find(id);
            if (it != mVibrators.end()) {
                it->second->tryReconnect();
            }
        }
    }
    return ret;
}

HalResult<void> AidlManagerHalWrapper::triggerSynced(
        const std::function<void()>& completionCallback) {
    HalResult<ManagerCapabilities> capabilities = getCapabilities();
    bool supportsCallback = capabilities.isOk() &&
            static_cast<int32_t>(capabilities.value() & ManagerCapabilities::TRIGGER_CALLBACK);
    auto cb = supportsCallback ? new HalCallbackWrapper(completionCallback) : nullptr;
    return HalResult<void>::fromStatus(getHal()->triggerSynced(cb));
}

HalResult<void> AidlManagerHalWrapper::cancelSynced() {
    auto ret = HalResult<void>::fromStatus(getHal()->cancelSynced());
    if (ret.isOk()) {
        // Force reload of all vibrator controllers that were prepared for a sync operation before.
        // This will trigger calls to getVibrator(id) on each controller, so they can use the
        // latest service provided by this manager.
        std::lock_guard<std::mutex> lock(mVibratorsMutex);
        for (auto& entry : mVibrators) {
            entry.second->tryReconnect();
        }
    }
    return ret;
}

sp<Aidl::IVibratorManager> AidlManagerHalWrapper::getHal() {
    std::lock_guard<std::mutex> lock(mHandleMutex);
    return mHandle;
}

}; // namespace vibrator

}; // namespace android
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ cc_benchmark {
        "liblog",
        "libutils",
        "libvibratorservice",
        "android.hardware.vibrator-cpp",
        "android.hardware.vibrator-unstable-cpp",
        "android.hardware.vibrator@1.0",
        "android.hardware.vibrator@1.1",
        "android.hardware.vibrator@1.2",
+35 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <android-base/thread_annotations.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
#include <android/hardware/vibrator/BnVibratorCallback.h>
#include <android/hardware/vibrator/IVibrator.h>
#include <binder/IServiceManager.h>

@@ -40,7 +41,15 @@ public:
    }
    static HalResult<T> unsupported() { return HalResult("", /* unsupported= */ true); }

    static HalResult<T> fromStatus(binder::Status status, T data);
    static HalResult<T> fromStatus(binder::Status status, T data) {
        if (status.exceptionCode() == binder::Status::EX_UNSUPPORTED_OPERATION) {
            return HalResult<T>::unsupported();
        }
        if (status.isOk()) {
            return HalResult<T>::ok(data);
        }
        return HalResult<T>::failed(std::string(status.toString8().c_str()));
    }
    static HalResult<T> fromStatus(hardware::vibrator::V1_0::Status status, T data);

    template <typename R>
@@ -99,6 +108,20 @@ private:
          : mErrorMessage(std::move(errorMessage)), mFailed(true), mUnsupported(false) {}
};

class HalCallbackWrapper : public hardware::vibrator::BnVibratorCallback {
public:
    HalCallbackWrapper(std::function<void()> completionCallback)
          : mCompletionCallback(completionCallback) {}

    binder::Status onComplete() override {
        mCompletionCallback();
        return binder::Status::ok();
    }

private:
    const std::function<void()> mCompletionCallback;
};

// -------------------------------------------------------------------------------------------------

// Vibrator HAL capabilities.
@@ -178,9 +201,16 @@ protected:
// Wrapper for the AIDL Vibrator HAL.
class AidlHalWrapper : public HalWrapper {
public:
    AidlHalWrapper(std::shared_ptr<CallbackScheduler> scheduler,
                   sp<hardware::vibrator::IVibrator> handle)
          : HalWrapper(std::move(scheduler)), mHandle(std::move(handle)) {}
    AidlHalWrapper(
            std::shared_ptr<CallbackScheduler> scheduler, sp<hardware::vibrator::IVibrator> handle,
            std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> reconnectFn =
                    []() {
                        return HalResult<sp<hardware::vibrator::IVibrator>>::ok(
                                checkVintfService<hardware::vibrator::IVibrator>());
                    })
          : HalWrapper(std::move(scheduler)),
            mReconnectFn(reconnectFn),
            mHandle(std::move(handle)) {}
    virtual ~AidlHalWrapper() = default;

    HalResult<void> ping() override final;
@@ -211,6 +241,7 @@ public:
            const std::function<void()>& completionCallback) override final;

private:
    const std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> mReconnectFn;
    std::mutex mHandleMutex;
    std::mutex mCapabilitiesMutex;
    std::mutex mSupportedEffectsMutex;
Loading