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

Commit 51060f3f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Switch to callback animation"

parents cde76928 ce637139
Loading
Loading
Loading
Loading
+40 −11
Original line number Diff line number Diff line
@@ -168,7 +168,7 @@ void MouseCursorController::fade(PointerControllerInterface::Transition transiti
        updatePointerLocked();
    } else {
        mLocked.pointerFadeDirection = -1;
        mContext.startAnimation();
        startAnimationLocked();
    }
}

@@ -185,7 +185,7 @@ void MouseCursorController::unfade(PointerControllerInterface::Transition transi
        updatePointerLocked();
    } else {
        mLocked.pointerFadeDirection = 1;
        mContext.startAnimation();
        startAnimationLocked();
    }
}

@@ -312,10 +312,9 @@ void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
    updatePointerLocked();
}

bool MouseCursorController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) {
bool MouseCursorController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
    nsecs_t frameDelay = timestamp - mContext.getAnimationTime();

    std::scoped_lock lock(mLock);
    bool keepAnimating = false;

    // Animate pointer fade.
    if (mLocked.pointerFadeDirection < 0) {
@@ -337,13 +336,10 @@ bool MouseCursorController::doFadingAnimation(nsecs_t timestamp, bool keepAnimat
        }
        updatePointerLocked();
    }

    return keepAnimating;
}

bool MouseCursorController::doBitmapAnimation(nsecs_t timestamp) {
    std::scoped_lock lock(mLock);

bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
    std::map<int32_t, PointerAnimation>::const_iterator iter =
            mLocked.animationResources.find(mLocked.requestedPointerType);
    if (iter == mLocked.animationResources.end()) {
@@ -364,7 +360,6 @@ bool MouseCursorController::doBitmapAnimation(nsecs_t timestamp) {

        spriteController->closeTransaction();
    }

    // Keep animating.
    return true;
}
@@ -399,7 +394,7 @@ void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
                if (anim_iter != mLocked.animationResources.end()) {
                    mLocked.animationFrameIndex = 0;
                    mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
                    mContext.startAnimation();
                    startAnimationLocked();
                }
                mLocked.pointerSprite->setIcon(iter->second);
            } else {
@@ -457,4 +452,38 @@ bool MouseCursorController::resourcesLoaded() {
    return mLocked.resourcesLoaded;
}

bool MouseCursorController::doAnimations(nsecs_t timestamp) {
    std::scoped_lock lock(mLock);
    bool keepFading = doFadingAnimationLocked(timestamp);
    bool keepBitmap = doBitmapAnimationLocked(timestamp);
    bool keepAnimating = keepFading || keepBitmap;
    if (!keepAnimating) {
        /*
         * We know that this callback will be removed before another
         * is added. mLock in PointerAnimator will not be released
         * until after this is removed, and adding another callback
         * requires that lock. Thus it's safe to set mLocked.animating
         * here.
         */
        mLocked.animating = false;
    }
    return keepAnimating;
}

void MouseCursorController::startAnimationLocked() REQUIRES(mLock) {
    using namespace std::placeholders;

    if (mLocked.animating) {
        return;
    }
    mLocked.animating = true;

    std::function<bool(nsecs_t)> func = std::bind(&MouseCursorController::doAnimations, this, _1);
    /*
     * Using -1 for displayId here to avoid removing the callback
     * if a TouchSpotController with the same display is removed.
     */
    mContext.addAnimationCallback(-1, func);
}

} // namespace android
+9 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <utils/Looper.h>
#include <utils/RefBase.h>

#include <functional>
#include <map>
#include <memory>
#include <vector>
@@ -61,8 +62,7 @@ public:
    void getAdditionalMouseResources();
    bool isViewportValid();

    bool doBitmapAnimation(nsecs_t timestamp);
    bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating);
    bool doAnimations(nsecs_t timestamp);

    bool resourcesLoaded();

@@ -96,6 +96,8 @@ private:

        int32_t buttonState;

        bool animating{false};

    } mLocked GUARDED_BY(mLock);

    bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
@@ -104,6 +106,11 @@ private:
    void updatePointerLocked();

    void loadResourcesLocked(bool getAdditionalMouseResources);

    bool doBitmapAnimationLocked(nsecs_t timestamp);
    bool doFadingAnimationLocked(nsecs_t timestamp);

    void startAnimationLocked();
};

} // namespace android
+5 −19
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ std::shared_ptr<PointerController> PointerController::create(

    controller->mContext.setHandlerController(controller);
    controller->mContext.setCallbackController(controller);
    controller->mContext.initializeDisplayEventReceiver();
    return controller;
}

@@ -189,24 +188,6 @@ void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
    mCursorController.setCustomPointerIcon(icon);
}

void PointerController::doAnimate(nsecs_t timestamp) {
    std::scoped_lock lock(mLock);

    mContext.setAnimationPending(false);

    bool keepFading = false;
    keepFading = mCursorController.doFadingAnimation(timestamp, keepFading);

    for (auto& [displayID, spotController] : mLocked.spotControllers) {
        keepFading = spotController.doFadingAnimation(timestamp, keepFading);
    }

    bool keepBitmapFlipping = mCursorController.doBitmapAnimation(timestamp);
    if (keepFading || keepBitmapFlipping) {
        mContext.startAnimation();
    }
}

void PointerController::doInactivityTimeout() {
    fade(Transition::GRADUAL);
}
@@ -221,6 +202,11 @@ void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>&
    for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
        int32_t displayID = it->first;
        if (!displayIdSet.count(displayID)) {
            /*
             * Ensures that an in-progress animation won't dereference
             * a null pointer to TouchSpotController.
             */
            mContext.removeAnimationCallback(displayID);
            it = mLocked.spotControllers.erase(it);
        } else {
            ++it;
+0 −1
Original line number Diff line number Diff line
@@ -70,7 +70,6 @@ public:
    void setCustomPointerIcon(const SpriteIcon& icon);
    void setInactivityTimeout(InactivityTimeout inactivityTimeout);
    void doInactivityTimeout();
    void doAnimate(nsecs_t timestamp);
    void reloadPointerResources();
    void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports);

+92 −43
Original line number Diff line number Diff line
@@ -38,10 +38,10 @@ PointerControllerContext::PointerControllerContext(
        mSpriteController(spriteController),
        mHandler(new MessageHandler()),
        mCallback(new LooperCallback()),
        mController(controller) {
        mController(controller),
        mAnimator(*this) {
    std::scoped_lock lock(mLock);
    mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
    mLocked.animationPending = false;
}

PointerControllerContext::~PointerControllerContext() {
@@ -57,15 +57,6 @@ void PointerControllerContext::setInactivityTimeout(InactivityTimeout inactivity
    }
}

void PointerControllerContext::startAnimation() {
    std::scoped_lock lock(mLock);
    if (!mLocked.animationPending) {
        mLocked.animationPending = true;
        mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
        mDisplayEventReceiver.requestNextVsync();
    }
}

void PointerControllerContext::resetInactivityTimeout() {
    std::scoped_lock lock(mLock);
    resetInactivityTimeoutLocked();
@@ -85,14 +76,8 @@ void PointerControllerContext::removeInactivityTimeout() {
    mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
}

void PointerControllerContext::setAnimationPending(bool animationPending) {
    std::scoped_lock lock(mLock);
    mLocked.animationPending = animationPending;
}

nsecs_t PointerControllerContext::getAnimationTime() {
    std::scoped_lock lock(mLock);
    return mLocked.animationTime;
nsecs_t PointerControllerContext::getAnimationTime() REQUIRES(mAnimator.mLock) {
    return mAnimator.getAnimationTimeLocked();
}

void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) {
@@ -112,31 +97,8 @@ sp<SpriteController> PointerControllerContext::getSpriteController() {
    return mSpriteController;
}

void PointerControllerContext::initializeDisplayEventReceiver() {
    if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
        mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK, Looper::EVENT_INPUT,
                       mCallback, nullptr);
    } else {
        ALOGE("Failed to initialize DisplayEventReceiver.");
    }
}

void PointerControllerContext::handleDisplayEvents() {
    bool gotVsync = false;
    ssize_t n;
    nsecs_t timestamp;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
            if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                timestamp = buf[i].header.timestamp;
                gotVsync = true;
            }
        }
    }
    if (gotVsync) {
        mController.doAnimate(timestamp);
    }
    mAnimator.handleVsyncEvents();
}

void PointerControllerContext::MessageHandler::handleMessage(const Message& message) {
@@ -176,4 +138,91 @@ int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int even
    return 1; // keep the callback
}

void PointerControllerContext::addAnimationCallback(int32_t displayId,
                                                    std::function<bool(nsecs_t)> callback) {
    mAnimator.addCallback(displayId, callback);
}

void PointerControllerContext::removeAnimationCallback(int32_t displayId) {
    mAnimator.removeCallback(displayId);
}

PointerControllerContext::PointerAnimator::PointerAnimator(PointerControllerContext& context)
      : mContext(context) {
    initializeDisplayEventReceiver();
}

void PointerControllerContext::PointerAnimator::initializeDisplayEventReceiver() {
    if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
        mContext.mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT, mContext.mCallback, nullptr);
    } else {
        ALOGE("Failed to initialize DisplayEventReceiver.");
    }
}

void PointerControllerContext::PointerAnimator::addCallback(int32_t displayId,
                                                            std::function<bool(nsecs_t)> callback) {
    std::scoped_lock lock(mLock);
    mLocked.callbacks[displayId] = callback;
    startAnimationLocked();
}

void PointerControllerContext::PointerAnimator::removeCallback(int32_t displayId) {
    std::scoped_lock lock(mLock);
    auto it = mLocked.callbacks.find(displayId);
    if (it == mLocked.callbacks.end()) {
        return;
    }
    mLocked.callbacks.erase(it);
}

void PointerControllerContext::PointerAnimator::handleVsyncEvents() {
    bool gotVsync = false;
    ssize_t n;
    nsecs_t timestamp;
    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
    while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
        for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
            if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                timestamp = buf[i].header.timestamp;
                gotVsync = true;
            }
        }
    }
    if (gotVsync) {
        std::scoped_lock lock(mLock);
        mLocked.animationPending = false;
        handleCallbacksLocked(timestamp);
    }
}

nsecs_t PointerControllerContext::PointerAnimator::getAnimationTimeLocked() REQUIRES(mLock) {
    return mLocked.animationTime;
}

void PointerControllerContext::PointerAnimator::startAnimationLocked() REQUIRES(mLock) {
    if (!mLocked.animationPending) {
        mLocked.animationPending = true;
        mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
        mDisplayEventReceiver.requestNextVsync();
    }
}

void PointerControllerContext::PointerAnimator::handleCallbacksLocked(nsecs_t timestamp)
        REQUIRES(mLock) {
    for (auto it = mLocked.callbacks.begin(); it != mLocked.callbacks.end();) {
        bool keepCallback = it->second(timestamp);
        if (!keepCallback) {
            it = mLocked.callbacks.erase(it);
        } else {
            ++it;
        }
    }

    if (!mLocked.callbacks.empty()) {
        startAnimationLocked();
    }
}

} // namespace android
Loading