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

Commit a859b8be authored by Lais Andrade's avatar Lais Andrade Committed by Android (Google) Code Review
Browse files

Merge "Introduce controller for VibratorManager HAL"

parents 58a0f5f1 f20b1449
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ namespace vibrator {

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

std::shared_ptr<HalWrapper> HalConnector::connect(std::shared_ptr<CallbackScheduler> scheduler) {
std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler) {
    static bool gHalExists = true;
    if (!gHalExists) {
        // We already tried to connect to all of the vibrator HAL versions and none was available.
@@ -106,7 +106,7 @@ HalResult<T> HalController::apply(HalController::hal_fn<T>& halFn, const char* f
        std::lock_guard<std::mutex> lock(mConnectedHalMutex);
        if (mConnectedHal == nullptr) {
            // Init was never called, so connect to HAL for the first time during this call.
            mConnectedHal = mHalConnector->connect(mCallbackScheduler);
            mConnectedHal = mConnector(mCallbackScheduler);

            if (mConnectedHal == nullptr) {
                ALOGV("Skipped %s because Vibrator HAL is not available", functionName);
@@ -129,7 +129,7 @@ HalResult<T> HalController::apply(HalController::hal_fn<T>& halFn, const char* f
bool HalController::init() {
    std::lock_guard<std::mutex> lock(mConnectedHalMutex);
    if (mConnectedHal == nullptr) {
        mConnectedHal = mHalConnector->connect(mCallbackScheduler);
        mConnectedHal = mConnector(mCallbackScheduler);
    }
    return mConnectedHal != nullptr;
}
@@ -142,7 +142,7 @@ HalResult<void> HalController::ping() {
void HalController::tryReconnect() {
    std::lock_guard<std::mutex> lock(mConnectedHalMutex);
    if (mConnectedHal == nullptr) {
        mConnectedHal = mHalConnector->connect(mCallbackScheduler);
        mConnectedHal = mConnector(mCallbackScheduler);
    } else {
        mConnectedHal->tryReconnect();
    }
+149 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.
 */

#define LOG_TAG "VibratorManagerHalController"

#include <utils/Log.h>

#include <vibratorservice/VibratorManagerHalController.h>

namespace Aidl = android::hardware::vibrator;

namespace android {

namespace vibrator {

std::shared_ptr<ManagerHalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler) {
    static bool gHalExists = true;
    if (gHalExists) {
        sp<Aidl::IVibratorManager> hal = waitForVintfService<Aidl::IVibratorManager>();
        if (hal) {
            ALOGV("Successfully connected to VibratorManager HAL AIDL service.");
            return std::make_shared<AidlManagerHalWrapper>(std::move(scheduler), aidlHal);
        }
    }

    gHalExists = false;
    return std::make_shared<LegacyManagerHalWrapper>();
}

static constexpr int MAX_RETRIES = 1;

template <typename T>
HalResult<T> ManagerHalController::processHalResult(HalResult<T> result, const char* functionName) {
    if (result.isFailed()) {
        ALOGE("%s failed: %s", functionName, result.errorMessage());
        std::lock_guard<std::mutex> lock(mConnectedHalMutex);
        mConnectedHal->tryReconnect();
    }
    return result;
}

template <typename T>
HalResult<T> ManagerHalController::apply(ManagerHalController::hal_fn<T>& halFn,
                                         const char* functionName) {
    std::shared_ptr<ManagerHalWrapper> hal = nullptr;
    {
        std::lock_guard<std::mutex> lock(mConnectedHalMutex);
        if (mConnectedHal == nullptr) {
            // Init was never called, so connect to HAL for the first time during this call.
            mConnectedHal = mConnector(mCallbackScheduler);

            if (mConnectedHal == nullptr) {
                ALOGV("Skipped %s because VibratorManager HAL is not available", functionName);
                return HalResult<T>::unsupported();
            }
        }
        hal = mConnectedHal;
    }

    HalResult<T> ret = processHalResult(halFn(hal), functionName);
    for (int i = 0; i < MAX_RETRIES && ret.isFailed(); i++) {
        ret = processHalResult(halFn(hal), functionName);
    }

    return ret;
}

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

bool ManagerHalController::init() {
    std::lock_guard<std::mutex> lock(mConnectedHalMutex);
    if (mConnectedHal == nullptr) {
        mConnectedHal = mConnector(mCallbackScheduler);
    }
    return mConnectedHal != nullptr;
}

HalResult<void> ManagerHalController::ping() {
    hal_fn<void> pingFn = [](std::shared_ptr<ManagerHalWrapper> hal) { return hal->ping(); };
    return apply(pingFn, "ping");
}

void ManagerHalController::tryReconnect() {
    std::lock_guard<std::mutex> lock(mConnectedHalMutex);
    if (mConnectedHal == nullptr) {
        mConnectedHal = mConnector(mCallbackScheduler);
    } else {
        mConnectedHal->tryReconnect();
    }
}

HalResult<ManagerCapabilities> ManagerHalController::getCapabilities() {
    hal_fn<ManagerCapabilities> getCapabilitiesFn = [](std::shared_ptr<ManagerHalWrapper> hal) {
        return hal->getCapabilities();
    };
    return apply(getCapabilitiesFn, "getCapabilities");
}

HalResult<std::vector<int32_t>> ManagerHalController::getVibratorIds() {
    hal_fn<std::vector<int32_t>> getVibratorIdsFn = [](std::shared_ptr<ManagerHalWrapper> hal) {
        return hal->getVibratorIds();
    };
    return apply(getVibratorIdsFn, "getVibratorIds");
}

HalResult<std::shared_ptr<HalController>> ManagerHalController::getVibrator(int32_t id) {
    hal_fn<std::shared_ptr<HalController>> getVibratorFn =
            [&](std::shared_ptr<ManagerHalWrapper> hal) { return hal->getVibrator(id); };
    return apply(getVibratorFn, "getVibrator");
}

HalResult<void> ManagerHalController::prepareSynced(const std::vector<int32_t>& ids) {
    hal_fn<void> prepareSyncedFn = [&](std::shared_ptr<ManagerHalWrapper> hal) {
        return hal->prepareSynced(ids);
    };
    return apply(prepareSyncedFn, "prepareSynced");
}

HalResult<void> ManagerHalController::triggerSynced(
        const std::function<void()>& completionCallback) {
    hal_fn<void> triggerSyncedFn = [&](std::shared_ptr<ManagerHalWrapper> hal) {
        return hal->triggerSynced(completionCallback);
    };
    return apply(triggerSyncedFn, "triggerSynced");
}

HalResult<void> ManagerHalController::cancelSynced() {
    hal_fn<void> cancelSyncedFn = [](std::shared_ptr<ManagerHalWrapper> hal) {
        return hal->cancelSynced();
    };
    return apply(cancelSyncedFn, "cancelSynced");
}

}; // namespace vibrator

}; // namespace android
+8 −7
Original line number Diff line number Diff line
@@ -72,11 +72,11 @@ HalResult<void> LegacyManagerHalWrapper::cancelSynced() {

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

std::shared_ptr<HalWrapper> AidlManagerHalWrapper::ManagedHalConnector::connect(
        std::shared_ptr<CallbackScheduler> callbackScheduler) {
    std::function<HalResult<sp<Aidl::IVibrator>>()> reconnectFn = [&]() {
std::shared_ptr<HalWrapper> AidlManagerHalWrapper::connectToVibrator(
        int32_t vibratorId, 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);
        auto result = this->getHal()->getVibrator(vibratorId, &vibrator);
        return HalResult<sp<Aidl::IVibrator>>::fromStatus(result, vibrator);
    };
    auto result = reconnectFn();
@@ -133,9 +133,10 @@ HalResult<std::vector<int32_t>> AidlManagerHalWrapper::getVibratorIds() {
        // 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);
            HalController::Connector connector = [&, id](auto scheduler) {
                return this->connectToVibrator(id, scheduler);
            };
            auto controller = std::make_unique<HalController>(mCallbackScheduler, connector);
            mVibrators[id] = std::move(controller);
        }
    }
+10 −17
Original line number Diff line number Diff line
@@ -27,27 +27,20 @@ namespace android {

namespace vibrator {

// Handles the connection to he underlying HAL implementation available.
class HalConnector {
public:
    HalConnector() = default;
    virtual ~HalConnector() = default;

    virtual std::shared_ptr<HalWrapper> connect(std::shared_ptr<CallbackScheduler> scheduler);
};
std::shared_ptr<HalWrapper> connectHal(std::shared_ptr<CallbackScheduler> scheduler);

// Controller for Vibrator HAL handle.
// This relies on HalConnector to connect to the underlying Vibrator HAL service and reconnects to
// it after each failed api call. This also ensures connecting to the service is thread-safe.
// This relies on a given Connector to connect to the underlying Vibrator HAL service and reconnects
// after each failed api call. This also ensures connecting to the service is thread-safe.
class HalController : public HalWrapper {
public:
    HalController()
          : HalController(std::make_unique<HalConnector>(), std::make_shared<CallbackScheduler>()) {
    }
    HalController(std::unique_ptr<HalConnector> halConnector,
                  std::shared_ptr<CallbackScheduler> callbackScheduler)
    using Connector =
            std::function<std::shared_ptr<HalWrapper>(std::shared_ptr<CallbackScheduler>)>;

    HalController() : HalController(std::make_shared<CallbackScheduler>(), &connectHal) {}
    HalController(std::shared_ptr<CallbackScheduler> callbackScheduler, Connector connector)
          : HalWrapper(std::move(callbackScheduler)),
            mHalConnector(std::move(halConnector)),
            mConnector(connector),
            mConnectedHal(nullptr) {}
    virtual ~HalController() = default;

@@ -89,7 +82,7 @@ public:
            const std::function<void()>& completionCallback) final override;

private:
    std::unique_ptr<HalConnector> mHalConnector;
    Connector mConnector;
    std::mutex mConnectedHalMutex;
    // Shared pointer to allow local copies to be used by different threads.
    std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex);
+85 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 ANDROID_OS_VIBRATOR_MANAGER_HAL_CONTROLLER_H
#define ANDROID_OS_VIBRATOR_MANAGER_HAL_CONTROLLER_H

#include <android/hardware/vibrator/IVibratorManager.h>
#include <vibratorservice/VibratorHalController.h>
#include <unordered_map>

namespace android {

namespace vibrator {

std::shared_ptr<ManagerHalWrapper> connectManagerHal(std::shared_ptr<CallbackScheduler> scheduler);

// Controller for VibratorManager HAL handle.
class ManagerHalController : public ManagerHalWrapper {
public:
    using Connector =
            std::function<std::shared_ptr<ManagerHalWrapper>(std::shared_ptr<CallbackScheduler>)>;

    ManagerHalController()
          : ManagerHalController(std::make_shared<CallbackScheduler>(), &connectManagerHal) {}
    ManagerHalController(std::shared_ptr<CallbackScheduler> callbackScheduler, Connector connector)
          : mConnector(connector), mConnectedHal(nullptr) {}
    virtual ~ManagerHalController() = default;

    /* Connects to the HAL service, possibly waiting for the registered service to
     * become available. This will automatically be called at the first API usage if it was not
     * manually called beforehand. Calling this manually during the setup phase can avoid slowing
     * the first API call later on. This will fallback to a legacy manager implementation if the
     * service is not available.
     */
    virtual void init();

    /* reloads HAL service instance without waiting. This relies on the HAL found by init()
     * to rapidly reconnect to the specific HAL service, or defers to init() if it was never called.
     */
    void tryReconnect() override final;

    HalResult<void> ping() override final;

    HalResult<ManagerCapabilities> getCapabilities() override final;
    HalResult<std::vector<int32_t>> getVibratorIds() override final;
    HalResult<std::shared_ptr<HalController>> getVibrator(int32_t id) override final;

    HalResult<void> prepareSynced(const std::vector<int32_t>& ids) override final;
    HalResult<void> triggerSynced(const std::function<void()>& completionCallback) override final;
    HalResult<void> cancelSynced() override final;

private:
    Connector mConnector;
    std::mutex mConnectedHalMutex;
    // Shared pointer to allow local copies to be used by different threads.
    std::shared_ptr<HalWrapper> mConnectedHal GUARDED_BY(mConnectedHalMutex);

    template <typename T>
    HalResult<T> processHalResult(HalResult<T> result, const char* functionName);

    template <typename T>
    using hal_fn = std::function<HalResult<T>(std::shared_ptr<ManagerHalWrapper>)>;

    template <typename T>
    HalResult<T> apply(hal_fn<T>& halFn, const char* functionName);
};

}; // namespace vibrator

}; // namespace android

#endif // ANDROID_OS_VIBRATOR_MANAGER_HAL_CONTROLLER_H
Loading