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

Commit bbe7855e authored by Harpreet \"Eli\" Sangha's avatar Harpreet \"Eli\" Sangha
Browse files

idlcli: vibrator: Add Blocking Options



Test: Manually on Pixel CS40L25 and DRV2624 Targets
Signed-off-by: default avatarHarpreet \"Eli\" Sangha <eliptus@google.com>
Change-Id: I3fbe889b82e80c48cc1a4ffd16f2efe0aa4672c5
parent eb9f16c6
Loading
Loading
Loading
Loading
+16 −0
Original line number Original line Diff line number Diff line
@@ -16,8 +16,12 @@
#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
#ifndef FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_
#define FRAMEWORK_NATIVE_CMDS_IDLCLI_VIBRATOR_H_


#include <future>

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


#include "utils.h"
#include "utils.h"
@@ -101,6 +105,18 @@ namespace V1_2 = ::android::hardware::vibrator::V1_2;
namespace V1_3 = ::android::hardware::vibrator::V1_3;
namespace V1_3 = ::android::hardware::vibrator::V1_3;
namespace aidl = ::aidl::android::hardware::vibrator;
namespace aidl = ::aidl::android::hardware::vibrator;


class VibratorCallback : public aidl::BnVibratorCallback {
public:
    ndk::ScopedAStatus onComplete() override {
        mPromise.set_value();
        return ndk::ScopedAStatus::ok();
    }
    void waitForComplete() { mPromise.get_future().wait(); }

private:
    std::promise<void> mPromise;
};

} // namespace vibrator
} // namespace vibrator
} // namespace idlcli
} // namespace idlcli


+36 −10
Original line number Original line Diff line number Diff line
@@ -28,10 +28,13 @@ using aidl::CompositeEffect;
class CommandCompose : public Command {
class CommandCompose : public Command {
    std::string getDescription() const override { return "Compose vibration."; }
    std::string getDescription() const override { return "Compose vibration."; }


    std::string getUsageSummary() const override { return "<delay> <primitive> <scale> ..."; }
    std::string getUsageSummary() const override {
        return "[options] <delay> <primitive> <scale> ...";
    }


    UsageDetails getUsageDetails() const override {
    UsageDetails getUsageDetails() const override {
        UsageDetails details{
        UsageDetails details{
                {"-b", {"Block for duration of vibration."}},
                {"<delay>", {"In milliseconds"}},
                {"<delay>", {"In milliseconds"}},
                {"<primitive>", {"Primitive ID."}},
                {"<primitive>", {"Primitive ID."}},
                {"<scale>", {"0.0 (exclusive) - 1.0 (inclusive)."}},
                {"<scale>", {"0.0 (exclusive) - 1.0 (inclusive)."}},
@@ -41,6 +44,17 @@ class CommandCompose : public Command {
    }
    }


    Status doArgs(Args &args) override {
    Status doArgs(Args &args) override {
        while (args.get<std::string>().value_or("").find("-") == 0) {
            auto opt = *args.pop<std::string>();
            if (opt == "--") {
                break;
            } else if (opt == "-b") {
                mBlocking = true;
            } else {
                std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
                return USAGE;
            }
        }
        while (!args.empty()) {
        while (!args.empty()) {
            CompositeEffect effect;
            CompositeEffect effect;
            if (auto delay = args.pop<decltype(effect.delayMs)>()) {
            if (auto delay = args.pop<decltype(effect.delayMs)>()) {
@@ -76,21 +90,33 @@ class CommandCompose : public Command {
    }
    }


    Status doMain(Args && /*args*/) override {
    Status doMain(Args && /*args*/) override {
        std::string statusStr;
        auto hal = getHal<aidl::IVibrator>();
        Status ret;

        if (auto hal = getHal<aidl::IVibrator>()) {
        if (!hal) {
            auto status = hal->call(&aidl::IVibrator::compose, mComposite, nullptr);
            statusStr = status.getDescription();
            ret = status.isOk() ? OK : ERROR;
        } else {
            return UNAVAILABLE;
            return UNAVAILABLE;
        }
        }


        std::cout << "Status: " << statusStr << std::endl;
        ABinderProcess_setThreadPoolMaxThreadCount(1);
        ABinderProcess_startThreadPool();

        std::shared_ptr<VibratorCallback> callback;

        if (mBlocking) {
            callback = ndk::SharedRefBase::make<VibratorCallback>();
        }

        auto status = hal->call(&aidl::IVibrator::compose, mComposite, callback);

        if (status.isOk() && callback) {
            callback->waitForComplete();
        }

        std::cout << "Status: " << status.getDescription() << std::endl;


        return ret;
        return status.isOk() ? OK : ERROR;
    }
    }


    bool mBlocking;
    std::vector<CompositeEffect> mComposite;
    std::vector<CompositeEffect> mComposite;
};
};


+40 −2
Original line number Original line Diff line number Diff line
@@ -13,9 +13,14 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#include <thread>

#include "utils.h"
#include "utils.h"
#include "vibrator.h"
#include "vibrator.h"


using std::chrono::milliseconds;
using std::this_thread::sleep_for;

namespace android {
namespace android {
namespace idlcli {
namespace idlcli {


@@ -26,16 +31,28 @@ namespace vibrator {
class CommandOn : public Command {
class CommandOn : public Command {
    std::string getDescription() const override { return "Turn on vibrator."; }
    std::string getDescription() const override { return "Turn on vibrator."; }


    std::string getUsageSummary() const override { return "<duration>"; }
    std::string getUsageSummary() const override { return "[options] <duration>"; }


    UsageDetails getUsageDetails() const override {
    UsageDetails getUsageDetails() const override {
        UsageDetails details{
        UsageDetails details{
                {"-b", {"Block for duration of vibration."}},
                {"<duration>", {"In milliseconds."}},
                {"<duration>", {"In milliseconds."}},
        };
        };
        return details;
        return details;
    }
    }


    Status doArgs(Args &args) override {
    Status doArgs(Args &args) override {
        while (args.get<std::string>().value_or("").find("-") == 0) {
            auto opt = *args.pop<std::string>();
            if (opt == "--") {
                break;
            } else if (opt == "-b") {
                mBlocking = true;
            } else {
                std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
                return USAGE;
            }
        }
        if (auto duration = args.pop<decltype(mDuration)>()) {
        if (auto duration = args.pop<decltype(mDuration)>()) {
            mDuration = *duration;
            mDuration = *duration;
        } else {
        } else {
@@ -52,9 +69,21 @@ class CommandOn : public Command {
    Status doMain(Args && /*args*/) override {
    Status doMain(Args && /*args*/) override {
        std::string statusStr;
        std::string statusStr;
        Status ret;
        Status ret;
        std::shared_ptr<VibratorCallback> callback;


        if (auto hal = getHal<aidl::IVibrator>()) {
        if (auto hal = getHal<aidl::IVibrator>()) {
            auto status = hal->call(&aidl::IVibrator::on, mDuration, nullptr);
            ABinderProcess_setThreadPoolMaxThreadCount(1);
            ABinderProcess_startThreadPool();

            int32_t cap;
            hal->call(&aidl::IVibrator::getCapabilities, &cap);

            if (mBlocking && (cap & aidl::IVibrator::CAP_ON_CALLBACK)) {
                callback = ndk::SharedRefBase::make<VibratorCallback>();
            }

            auto status = hal->call(&aidl::IVibrator::on, mDuration, callback);

            statusStr = status.getDescription();
            statusStr = status.getDescription();
            ret = status.isOk() ? OK : ERROR;
            ret = status.isOk() ? OK : ERROR;
        } else if (auto hal = getHal<V1_0::IVibrator>()) {
        } else if (auto hal = getHal<V1_0::IVibrator>()) {
@@ -65,11 +94,20 @@ class CommandOn : public Command {
            return UNAVAILABLE;
            return UNAVAILABLE;
        }
        }


        if (ret == OK && mBlocking) {
            if (callback) {
                callback->waitForComplete();
            } else {
                sleep_for(milliseconds(mDuration));
            }
        }

        std::cout << "Status: " << statusStr << std::endl;
        std::cout << "Status: " << statusStr << std::endl;


        return ret;
        return ret;
    }
    }


    bool mBlocking;
    uint32_t mDuration;
    uint32_t mDuration;
};
};


+42 −4
Original line number Original line Diff line number Diff line
@@ -13,9 +13,14 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


#include <thread>

#include "utils.h"
#include "utils.h"
#include "vibrator.h"
#include "vibrator.h"


using std::chrono::milliseconds;
using std::this_thread::sleep_for;

namespace android {
namespace android {
namespace idlcli {
namespace idlcli {


@@ -57,10 +62,11 @@ using V1_3::Effect;
class CommandPerform : public Command {
class CommandPerform : public Command {
    std::string getDescription() const override { return "Perform vibration effect."; }
    std::string getDescription() const override { return "Perform vibration effect."; }


    std::string getUsageSummary() const override { return "<effect> <strength>"; }
    std::string getUsageSummary() const override { return "[options] <effect> <strength>"; }


    UsageDetails getUsageDetails() const override {
    UsageDetails getUsageDetails() const override {
        UsageDetails details{
        UsageDetails details{
                {"-b", {"Block for duration of vibration."}},
                {"<effect>", {"Effect ID."}},
                {"<effect>", {"Effect ID."}},
                {"<strength>", {"0-2."}},
                {"<strength>", {"0-2."}},
        };
        };
@@ -68,6 +74,17 @@ class CommandPerform : public Command {
    }
    }


    Status doArgs(Args &args) override {
    Status doArgs(Args &args) override {
        while (args.get<std::string>().value_or("").find("-") == 0) {
            auto opt = *args.pop<std::string>();
            if (opt == "--") {
                break;
            } else if (opt == "-b") {
                mBlocking = true;
            } else {
                std::cerr << "Invalid Option '" << opt << "'!" << std::endl;
                return USAGE;
            }
        }
        if (auto effect = args.pop<decltype(mEffect)>()) {
        if (auto effect = args.pop<decltype(mEffect)>()) {
            mEffect = *effect;
            mEffect = *effect;
            std::cout << "Effect: " << toString(mEffect) << std::endl;
            std::cout << "Effect: " << toString(mEffect) << std::endl;
@@ -93,12 +110,24 @@ class CommandPerform : public Command {
        std::string statusStr;
        std::string statusStr;
        uint32_t lengthMs;
        uint32_t lengthMs;
        Status ret;
        Status ret;
        std::shared_ptr<VibratorCallback> callback;


        if (auto hal = getHal<aidl::IVibrator>()) {
        if (auto hal = getHal<aidl::IVibrator>()) {
            ABinderProcess_setThreadPoolMaxThreadCount(1);
            ABinderProcess_startThreadPool();

            int32_t cap;
            hal->call(&aidl::IVibrator::getCapabilities, &cap);

            if (mBlocking && (cap & aidl::IVibrator::CAP_PERFORM_CALLBACK)) {
                callback = ndk::SharedRefBase::make<VibratorCallback>();
            }

            int32_t aidlLengthMs;
            int32_t aidlLengthMs;
            auto status =
            auto status = hal->call(&aidl::IVibrator::perform, static_cast<aidl::Effect>(mEffect),
                    hal->call(&aidl::IVibrator::perform, static_cast<aidl::Effect>(mEffect),
                                    static_cast<aidl::EffectStrength>(mStrength), callback,
                              static_cast<aidl::EffectStrength>(mStrength), nullptr, &aidlLengthMs);
                                    &aidlLengthMs);

            statusStr = status.getDescription();
            statusStr = status.getDescription();
            lengthMs = static_cast<uint32_t>(aidlLengthMs);
            lengthMs = static_cast<uint32_t>(aidlLengthMs);
            ret = status.isOk() ? OK : ERROR;
            ret = status.isOk() ? OK : ERROR;
@@ -130,12 +159,21 @@ class CommandPerform : public Command {
            ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
            ret = hidlRet.isOk() && status == V1_0::Status::OK ? OK : ERROR;
        }
        }


        if (ret == OK && mBlocking) {
            if (callback) {
                callback->waitForComplete();
            } else {
                sleep_for(milliseconds(lengthMs));
            }
        }

        std::cout << "Status: " << statusStr << std::endl;
        std::cout << "Status: " << statusStr << std::endl;
        std::cout << "Length: " << lengthMs << std::endl;
        std::cout << "Length: " << lengthMs << std::endl;


        return ret;
        return ret;
    }
    }


    bool mBlocking;
    Effect mEffect;
    Effect mEffect;
    EffectStrength mStrength;
    EffectStrength mStrength;
};
};