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

Commit 5c7e4702 authored by Harpreet \"Eli\" Sangha's avatar Harpreet \"Eli\" Sangha Committed by android-build-merger
Browse files

Merge "vibrator: Add Composition APIs"

am: 677cdb4b

Change-Id: I359fc3ba7d10b926b807e1f1bafdd632967d0b85
parents 0942e330 677cdb4b
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package android.hardware.vibrator;

import android.hardware.vibrator.CompositePrimitive;

@VintfStability
parcelable CompositeEffect {
    /* Period of silence preceding primitive. */
    int delayMs;
    CompositePrimitive primitive;
    /* 0.0 (exclusive) - 1.0 (inclusive) */
    float scale;
}
+29 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

package android.hardware.vibrator;

@VintfStability
@Backing(type="int")
enum CompositePrimitive {
    NOOP,
    CLICK,
    THUD,
    SPIN,
    QUICK_RISE,
    SLOW_RISE,
    QUICK_FALL,
}
+41 −4
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.hardware.vibrator;
import android.hardware.vibrator.IVibratorCallback;
import android.hardware.vibrator.Effect;
import android.hardware.vibrator.EffectStrength;
import android.hardware.vibrator.CompositeEffect;
import android.hardware.vibrator.CompositePrimitive;

@VintfStability
interface IVibrator {
@@ -42,6 +44,10 @@ interface IVibrator {
     * Whether setAmplitude is supported (when external control is enabled)
     */
    const int CAP_EXTERNAL_AMPLITUDE_CONTROL = 1 << 4;
    /**
     * Whether compose is supported.
     */
    const int CAP_COMPOSE_EFFECTS = 1 << 5;

    /**
     * Determine capabilities of the vibrator HAL (CAP_* mask)
@@ -107,11 +113,10 @@ interface IVibrator {
     * CAP_EXTERNAL_AMPLITUDE_CONTROL.
     *
     * @param amplitude The unitless force setting. Note that this number must
     *                  be between 1 and 255, inclusive. If the motor does not
     *                  have exactly 255 steps, it must do it's best to map it
     *                  onto the number of steps it does have.
     *                  be between 0.0 (exclusive) and 1.0 (inclusive). It must
     *                  do it's best to map it onto the number of steps it does have.
     */
    void setAmplitude(in int amplitude);
    void setAmplitude(in float amplitude);

    /**
     * Enables/disables control override of vibrator to audio.
@@ -128,4 +133,36 @@ interface IVibrator {
     * @param enabled Whether external control should be enabled or disabled.
     */
    void setExternalControl(in boolean enabled);

    /**
     * Retrieve composition delay limit.
     *
     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
     *
     * @return Maximum delay for a single CompositeEffect[] entry.
     */
    int getCompositionDelayMax();

    /**
     * Retrieve composition size limit.
     *
     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
     *
     * @return Maximum number of entries in CompositeEffect[].
     * @param maxDelayMs Maximum delay for a single CompositeEffect[] entry.
     */
    int getCompositionSizeMax();

    /**
     * Fire off a string of effect primitives, combined to perform richer effects.
     *
     * Support is reflected in getCapabilities (CAP_COMPOSE_EFFECTS).
     *
     * Doing this operation while the vibrator is already on is undefined behavior. Clients should
     * explicitly call off.
     *
     * @param composite Array of composition parameters.
     */
    void compose(in CompositeEffect[] composite, in IVibratorCallback callback);

}
+55 −3
Original line number Diff line number Diff line
@@ -24,11 +24,14 @@ namespace android {
namespace hardware {
namespace vibrator {

static constexpr int32_t kComposeDelayMaxMs = 1000;
static constexpr int32_t kComposeSizeMax = 256;

ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) {
    LOG(INFO) << "Vibrator reporting capabilities";
    *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK |
                    IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL |
                    IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL;
                    IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS;
    return ndk::ScopedAStatus::ok();
}

@@ -84,9 +87,9 @@ ndk::ScopedAStatus Vibrator::getSupportedEffects(std::vector<Effect>* _aidl_retu
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Vibrator::setAmplitude(int32_t amplitude) {
ndk::ScopedAStatus Vibrator::setAmplitude(float amplitude) {
    LOG(INFO) << "Vibrator set amplitude: " << amplitude;
    if (amplitude <= 0 || amplitude > 255) {
    if (amplitude <= 0.0f || amplitude > 1.0f) {
        return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
    }
    return ndk::ScopedAStatus::ok();
@@ -97,6 +100,55 @@ ndk::ScopedAStatus Vibrator::setExternalControl(bool enabled) {
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Vibrator::getCompositionDelayMax(int32_t* maxDelayMs) {
    *maxDelayMs = kComposeDelayMaxMs;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Vibrator::getCompositionSizeMax(int32_t* maxSize) {
    *maxSize = kComposeSizeMax;
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Vibrator::compose(const std::vector<CompositeEffect>& composite,
                                     const std::shared_ptr<IVibratorCallback>& callback) {
    if (composite.size() > kComposeSizeMax) {
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
    }

    for (auto& e : composite) {
        if (e.delayMs > kComposeDelayMaxMs) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
        }
        if (e.scale <= 0.0f || e.scale > 1.0f) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
        }
        if (e.primitive < CompositePrimitive::NOOP ||
            e.primitive > CompositePrimitive::QUICK_FALL) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
        }
    }

    std::thread([=] {
        LOG(INFO) << "Starting compose on another thread";

        for (auto& e : composite) {
            if (e.delayMs) {
                usleep(e.delayMs * 1000);
            }
            LOG(INFO) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
                      << e.scale;
        }

        if (callback != nullptr) {
            LOG(INFO) << "Notifying perform complete";
            callback->onComplete();
        }
    }).detach();

    return ndk::ScopedAStatus::ok();
}

}  // namespace vibrator
}  // namespace hardware
}  // namespace android
+5 −1
Original line number Diff line number Diff line
@@ -32,8 +32,12 @@ class Vibrator : public BnVibrator {
                               const std::shared_ptr<IVibratorCallback>& callback,
                               int32_t* _aidl_return) override;
    ndk::ScopedAStatus getSupportedEffects(std::vector<Effect>* _aidl_return) override;
    ndk::ScopedAStatus setAmplitude(int32_t amplitude) override;
    ndk::ScopedAStatus setAmplitude(float amplitude) override;
    ndk::ScopedAStatus setExternalControl(bool enabled) override;
    ndk::ScopedAStatus getCompositionDelayMax(int32_t* maxDelayMs);
    ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize);
    ndk::ScopedAStatus compose(const std::vector<CompositeEffect>& composite,
                               const std::shared_ptr<IVibratorCallback>& callback) override;
};

}  // namespace vibrator
Loading