diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2020-08-24 11:28:48 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-08-24 11:28:48 +0000 |
commit | 42e412b5111f99e6e4813aa9ab7450ec215ca09b (patch) | |
tree | 08eec6c6c1d0725ed35b7db71a1d15f9ea18db6c /libs | |
parent | be053b7e197809408865a2a4989df05d3012385b (diff) | |
parent | 5267d9227289a074aa4c4a972586d182ce4c76a5 (diff) |
Merge "Switch to callback animation" am: 51060f3f7a am: 5267d92272
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1399752
Change-Id: I3e4d82a9a2f9e9f4f1232a2de21a55cc19a2168a
Diffstat (limited to 'libs')
-rw-r--r-- | libs/input/MouseCursorController.cpp | 51 | ||||
-rw-r--r-- | libs/input/MouseCursorController.h | 11 | ||||
-rw-r--r-- | libs/input/PointerController.cpp | 24 | ||||
-rw-r--r-- | libs/input/PointerController.h | 1 | ||||
-rw-r--r-- | libs/input/PointerControllerContext.cpp | 135 | ||||
-rw-r--r-- | libs/input/PointerControllerContext.h | 43 | ||||
-rw-r--r-- | libs/input/TouchSpotController.cpp | 36 | ||||
-rw-r--r-- | libs/input/TouchSpotController.h | 8 |
8 files changed, 221 insertions, 88 deletions
diff --git a/libs/input/MouseCursorController.cpp b/libs/input/MouseCursorController.cpp index 80b555be97dd..45da008c3e8e 100644 --- a/libs/input/MouseCursorController.cpp +++ b/libs/input/MouseCursorController.cpp @@ -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 diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h index 448165b5ac46..e6dfc4c6f99a 100644 --- a/libs/input/MouseCursorController.h +++ b/libs/input/MouseCursorController.h @@ -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 diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index 14c96cefd462..8f04cfb70469 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -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; diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index 1f561da333b1..827fcf1e1bc1 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -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); diff --git a/libs/input/PointerControllerContext.cpp b/libs/input/PointerControllerContext.cpp index 2d7e22b01112..f30e8d8e33a5 100644 --- a/libs/input/PointerControllerContext.cpp +++ b/libs/input/PointerControllerContext.cpp @@ -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 diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h index 92e1bda25f56..98073fea323e 100644 --- a/libs/input/PointerControllerContext.h +++ b/libs/input/PointerControllerContext.h @@ -26,6 +26,7 @@ #include <utils/Looper.h> #include <utils/RefBase.h> +#include <functional> #include <map> #include <memory> #include <vector> @@ -35,6 +36,8 @@ namespace android { class PointerController; +class MouseCursorController; +class TouchSpotController; /* * Pointer resources. @@ -96,7 +99,6 @@ public: void startAnimation(); void setInactivityTimeout(InactivityTimeout inactivityTimeout); - void setAnimationPending(bool animationPending); nsecs_t getAnimationTime(); void clearSpotsByDisplay(int32_t displayId); @@ -107,9 +109,11 @@ public: sp<PointerControllerPolicyInterface> getPolicy(); sp<SpriteController> getSpriteController(); - void initializeDisplayEventReceiver(); void handleDisplayEvents(); + void addAnimationCallback(int32_t displayId, std::function<bool(nsecs_t)> callback); + void removeAnimationCallback(int32_t displayId); + class MessageHandler : public virtual android::MessageHandler { public: enum { @@ -127,22 +131,47 @@ public: }; private: + class PointerAnimator { + public: + PointerAnimator(PointerControllerContext& context); + + void addCallback(int32_t displayId, std::function<bool(nsecs_t)> callback); + void removeCallback(int32_t displayId); + void handleVsyncEvents(); + nsecs_t getAnimationTimeLocked(); + + mutable std::mutex mLock; + + private: + struct Locked { + bool animationPending{false}; + nsecs_t animationTime{systemTime(SYSTEM_TIME_MONOTONIC)}; + + std::unordered_map<int32_t, std::function<bool(nsecs_t)>> callbacks; + } mLocked GUARDED_BY(mLock); + + DisplayEventReceiver mDisplayEventReceiver; + + PointerControllerContext& mContext; + + void initializeDisplayEventReceiver(); + void startAnimationLocked(); + void handleCallbacksLocked(nsecs_t timestamp); + }; + sp<PointerControllerPolicyInterface> mPolicy; sp<Looper> mLooper; sp<SpriteController> mSpriteController; sp<MessageHandler> mHandler; sp<LooperCallback> mCallback; - DisplayEventReceiver mDisplayEventReceiver; - PointerController& mController; + PointerAnimator mAnimator; + mutable std::mutex mLock; struct Locked { - bool animationPending; - nsecs_t animationTime; - InactivityTimeout inactivityTimeout; } mLocked GUARDED_BY(mLock); diff --git a/libs/input/TouchSpotController.cpp b/libs/input/TouchSpotController.cpp index c7430ceead41..f7c685ff8ba6 100644 --- a/libs/input/TouchSpotController.cpp +++ b/libs/input/TouchSpotController.cpp @@ -142,7 +142,8 @@ TouchSpotController::Spot* TouchSpotController::getSpot(uint32_t id, } TouchSpotController::Spot* TouchSpotController::createAndAddSpotLocked(uint32_t id, - std::vector<Spot*>& spots) { + std::vector<Spot*>& spots) + REQUIRES(mLock) { // Remove spots until we have fewer than MAX_SPOTS remaining. while (spots.size() >= MAX_SPOTS) { Spot* spot = removeFirstFadingSpotLocked(spots); @@ -186,14 +187,13 @@ void TouchSpotController::releaseSpotLocked(Spot* spot) REQUIRES(mLock) { if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) { mLocked.recycledSprites.push_back(spot->sprite); } - delete spot; } void TouchSpotController::fadeOutAndReleaseSpotLocked(Spot* spot) REQUIRES(mLock) { if (spot->id != Spot::INVALID_ID) { spot->id = Spot::INVALID_ID; - mContext.startAnimation(); + startAnimationLocked(); } } @@ -209,8 +209,24 @@ void TouchSpotController::reloadSpotResources() { mContext.getPolicy()->loadPointerResources(&mResources, mDisplayId); } -bool TouchSpotController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) { +bool TouchSpotController::doAnimations(nsecs_t timestamp) { std::scoped_lock lock(mLock); + bool keepAnimating = doFadingAnimationLocked(timestamp); + 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; +} + +bool TouchSpotController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) { + bool keepAnimating = false; nsecs_t animationTime = mContext.getAnimationTime(); nsecs_t frameDelay = timestamp - animationTime; size_t numSpots = mLocked.displaySpots.size(); @@ -233,4 +249,16 @@ bool TouchSpotController::doFadingAnimation(nsecs_t timestamp, bool keepAnimatin return keepAnimating; } +void TouchSpotController::startAnimationLocked() REQUIRES(mLock) { + using namespace std::placeholders; + + if (mLocked.animating) { + return; + } + mLocked.animating = true; + + std::function<bool(nsecs_t)> func = std::bind(&TouchSpotController::doAnimations, this, _1); + mContext.addAnimationCallback(mDisplayId, func); +} + } // namespace android diff --git a/libs/input/TouchSpotController.h b/libs/input/TouchSpotController.h index f3b355010bee..703de3603f48 100644 --- a/libs/input/TouchSpotController.h +++ b/libs/input/TouchSpotController.h @@ -17,6 +17,8 @@ #ifndef _UI_TOUCH_SPOT_CONTROLLER_H #define _UI_TOUCH_SPOT_CONTROLLER_H +#include <functional> + #include "PointerControllerContext.h" namespace android { @@ -34,7 +36,7 @@ public: void clearSpots(); void reloadSpotResources(); - bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating); + bool doAnimations(nsecs_t timestamp); private: struct Spot { @@ -76,6 +78,8 @@ private: std::vector<Spot*> displaySpots; std::vector<sp<Sprite>> recycledSprites; + bool animating{false}; + } mLocked GUARDED_BY(mLock); Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots); @@ -84,6 +88,8 @@ private: void releaseSpotLocked(Spot* spot); void fadeOutAndReleaseSpotLocked(Spot* spot); void fadeOutAndReleaseAllSpotsLocked(); + bool doFadingAnimationLocked(nsecs_t timestamp); + void startAnimationLocked(); }; } // namespace android |