Merge "Switch to callback animation" am: 51060f3f7a am: 5267d92272

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1399752

Change-Id: I3e4d82a9a2f9e9f4f1232a2de21a55cc19a2168a
This commit is contained in:
Treehugger Robot
2020-08-24 11:28:48 +00:00
committed by Automerger Merge Worker
8 changed files with 221 additions and 88 deletions

View File

@@ -168,7 +168,7 @@ void MouseCursorController::fade(PointerControllerInterface::Transition transiti
updatePointerLocked(); updatePointerLocked();
} else { } else {
mLocked.pointerFadeDirection = -1; mLocked.pointerFadeDirection = -1;
mContext.startAnimation(); startAnimationLocked();
} }
} }
@@ -185,7 +185,7 @@ void MouseCursorController::unfade(PointerControllerInterface::Transition transi
updatePointerLocked(); updatePointerLocked();
} else { } else {
mLocked.pointerFadeDirection = 1; mLocked.pointerFadeDirection = 1;
mContext.startAnimation(); startAnimationLocked();
} }
} }
@@ -312,10 +312,9 @@ void MouseCursorController::setCustomPointerIcon(const SpriteIcon& icon) {
updatePointerLocked(); updatePointerLocked();
} }
bool MouseCursorController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) { bool MouseCursorController::doFadingAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
nsecs_t frameDelay = timestamp - mContext.getAnimationTime(); nsecs_t frameDelay = timestamp - mContext.getAnimationTime();
bool keepAnimating = false;
std::scoped_lock lock(mLock);
// Animate pointer fade. // Animate pointer fade.
if (mLocked.pointerFadeDirection < 0) { if (mLocked.pointerFadeDirection < 0) {
@@ -337,13 +336,10 @@ bool MouseCursorController::doFadingAnimation(nsecs_t timestamp, bool keepAnimat
} }
updatePointerLocked(); updatePointerLocked();
} }
return keepAnimating; return keepAnimating;
} }
bool MouseCursorController::doBitmapAnimation(nsecs_t timestamp) { bool MouseCursorController::doBitmapAnimationLocked(nsecs_t timestamp) REQUIRES(mLock) {
std::scoped_lock lock(mLock);
std::map<int32_t, PointerAnimation>::const_iterator iter = std::map<int32_t, PointerAnimation>::const_iterator iter =
mLocked.animationResources.find(mLocked.requestedPointerType); mLocked.animationResources.find(mLocked.requestedPointerType);
if (iter == mLocked.animationResources.end()) { if (iter == mLocked.animationResources.end()) {
@@ -364,7 +360,6 @@ bool MouseCursorController::doBitmapAnimation(nsecs_t timestamp) {
spriteController->closeTransaction(); spriteController->closeTransaction();
} }
// Keep animating. // Keep animating.
return true; return true;
} }
@@ -399,7 +394,7 @@ void MouseCursorController::updatePointerLocked() REQUIRES(mLock) {
if (anim_iter != mLocked.animationResources.end()) { if (anim_iter != mLocked.animationResources.end()) {
mLocked.animationFrameIndex = 0; mLocked.animationFrameIndex = 0;
mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC); mLocked.lastFrameUpdatedTime = systemTime(SYSTEM_TIME_MONOTONIC);
mContext.startAnimation(); startAnimationLocked();
} }
mLocked.pointerSprite->setIcon(iter->second); mLocked.pointerSprite->setIcon(iter->second);
} else { } else {
@@ -457,4 +452,38 @@ bool MouseCursorController::resourcesLoaded() {
return mLocked.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 } // namespace android

View File

@@ -25,6 +25,7 @@
#include <utils/Looper.h> #include <utils/Looper.h>
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <functional>
#include <map> #include <map>
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -61,8 +62,7 @@ public:
void getAdditionalMouseResources(); void getAdditionalMouseResources();
bool isViewportValid(); bool isViewportValid();
bool doBitmapAnimation(nsecs_t timestamp); bool doAnimations(nsecs_t timestamp);
bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating);
bool resourcesLoaded(); bool resourcesLoaded();
@@ -96,6 +96,8 @@ private:
int32_t buttonState; int32_t buttonState;
bool animating{false};
} mLocked GUARDED_BY(mLock); } mLocked GUARDED_BY(mLock);
bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const; bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
@@ -104,6 +106,11 @@ private:
void updatePointerLocked(); void updatePointerLocked();
void loadResourcesLocked(bool getAdditionalMouseResources); void loadResourcesLocked(bool getAdditionalMouseResources);
bool doBitmapAnimationLocked(nsecs_t timestamp);
bool doFadingAnimationLocked(nsecs_t timestamp);
void startAnimationLocked();
}; };
} // namespace android } // namespace android

View File

@@ -57,7 +57,6 @@ std::shared_ptr<PointerController> PointerController::create(
controller->mContext.setHandlerController(controller); controller->mContext.setHandlerController(controller);
controller->mContext.setCallbackController(controller); controller->mContext.setCallbackController(controller);
controller->mContext.initializeDisplayEventReceiver();
return controller; return controller;
} }
@@ -189,24 +188,6 @@ void PointerController::setCustomPointerIcon(const SpriteIcon& icon) {
mCursorController.setCustomPointerIcon(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() { void PointerController::doInactivityTimeout() {
fade(Transition::GRADUAL); fade(Transition::GRADUAL);
} }
@@ -221,6 +202,11 @@ void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>&
for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) { for (auto it = mLocked.spotControllers.begin(); it != mLocked.spotControllers.end();) {
int32_t displayID = it->first; int32_t displayID = it->first;
if (!displayIdSet.count(displayID)) { 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); it = mLocked.spotControllers.erase(it);
} else { } else {
++it; ++it;

View File

@@ -70,7 +70,6 @@ public:
void setCustomPointerIcon(const SpriteIcon& icon); void setCustomPointerIcon(const SpriteIcon& icon);
void setInactivityTimeout(InactivityTimeout inactivityTimeout); void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void doInactivityTimeout(); void doInactivityTimeout();
void doAnimate(nsecs_t timestamp);
void reloadPointerResources(); void reloadPointerResources();
void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports); void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports);

View File

@@ -38,10 +38,10 @@ PointerControllerContext::PointerControllerContext(
mSpriteController(spriteController), mSpriteController(spriteController),
mHandler(new MessageHandler()), mHandler(new MessageHandler()),
mCallback(new LooperCallback()), mCallback(new LooperCallback()),
mController(controller) { mController(controller),
mAnimator(*this) {
std::scoped_lock lock(mLock); std::scoped_lock lock(mLock);
mLocked.inactivityTimeout = InactivityTimeout::NORMAL; mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
mLocked.animationPending = false;
} }
PointerControllerContext::~PointerControllerContext() { 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() { void PointerControllerContext::resetInactivityTimeout() {
std::scoped_lock lock(mLock); std::scoped_lock lock(mLock);
resetInactivityTimeoutLocked(); resetInactivityTimeoutLocked();
@@ -85,14 +76,8 @@ void PointerControllerContext::removeInactivityTimeout() {
mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT); mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
} }
void PointerControllerContext::setAnimationPending(bool animationPending) { nsecs_t PointerControllerContext::getAnimationTime() REQUIRES(mAnimator.mLock) {
std::scoped_lock lock(mLock); return mAnimator.getAnimationTimeLocked();
mLocked.animationPending = animationPending;
}
nsecs_t PointerControllerContext::getAnimationTime() {
std::scoped_lock lock(mLock);
return mLocked.animationTime;
} }
void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) { void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) {
@@ -112,31 +97,8 @@ sp<SpriteController> PointerControllerContext::getSpriteController() {
return mSpriteController; 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() { void PointerControllerContext::handleDisplayEvents() {
bool gotVsync = false; mAnimator.handleVsyncEvents();
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);
}
} }
void PointerControllerContext::MessageHandler::handleMessage(const Message& message) { void PointerControllerContext::MessageHandler::handleMessage(const Message& message) {
@@ -176,4 +138,91 @@ int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int even
return 1; // keep the callback 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 } // namespace android

View File

@@ -26,6 +26,7 @@
#include <utils/Looper.h> #include <utils/Looper.h>
#include <utils/RefBase.h> #include <utils/RefBase.h>
#include <functional>
#include <map> #include <map>
#include <memory> #include <memory>
#include <vector> #include <vector>
@@ -35,6 +36,8 @@
namespace android { namespace android {
class PointerController; class PointerController;
class MouseCursorController;
class TouchSpotController;
/* /*
* Pointer resources. * Pointer resources.
@@ -96,7 +99,6 @@ public:
void startAnimation(); void startAnimation();
void setInactivityTimeout(InactivityTimeout inactivityTimeout); void setInactivityTimeout(InactivityTimeout inactivityTimeout);
void setAnimationPending(bool animationPending);
nsecs_t getAnimationTime(); nsecs_t getAnimationTime();
void clearSpotsByDisplay(int32_t displayId); void clearSpotsByDisplay(int32_t displayId);
@@ -107,9 +109,11 @@ public:
sp<PointerControllerPolicyInterface> getPolicy(); sp<PointerControllerPolicyInterface> getPolicy();
sp<SpriteController> getSpriteController(); sp<SpriteController> getSpriteController();
void initializeDisplayEventReceiver();
void handleDisplayEvents(); void handleDisplayEvents();
void addAnimationCallback(int32_t displayId, std::function<bool(nsecs_t)> callback);
void removeAnimationCallback(int32_t displayId);
class MessageHandler : public virtual android::MessageHandler { class MessageHandler : public virtual android::MessageHandler {
public: public:
enum { enum {
@@ -127,22 +131,47 @@ public:
}; };
private: 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<PointerControllerPolicyInterface> mPolicy;
sp<Looper> mLooper; sp<Looper> mLooper;
sp<SpriteController> mSpriteController; sp<SpriteController> mSpriteController;
sp<MessageHandler> mHandler; sp<MessageHandler> mHandler;
sp<LooperCallback> mCallback; sp<LooperCallback> mCallback;
DisplayEventReceiver mDisplayEventReceiver;
PointerController& mController; PointerController& mController;
PointerAnimator mAnimator;
mutable std::mutex mLock; mutable std::mutex mLock;
struct Locked { struct Locked {
bool animationPending;
nsecs_t animationTime;
InactivityTimeout inactivityTimeout; InactivityTimeout inactivityTimeout;
} mLocked GUARDED_BY(mLock); } mLocked GUARDED_BY(mLock);

View File

@@ -142,7 +142,8 @@ TouchSpotController::Spot* TouchSpotController::getSpot(uint32_t id,
} }
TouchSpotController::Spot* TouchSpotController::createAndAddSpotLocked(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. // Remove spots until we have fewer than MAX_SPOTS remaining.
while (spots.size() >= MAX_SPOTS) { while (spots.size() >= MAX_SPOTS) {
Spot* spot = removeFirstFadingSpotLocked(spots); Spot* spot = removeFirstFadingSpotLocked(spots);
@@ -186,14 +187,13 @@ void TouchSpotController::releaseSpotLocked(Spot* spot) REQUIRES(mLock) {
if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) { if (mLocked.recycledSprites.size() < MAX_RECYCLED_SPRITES) {
mLocked.recycledSprites.push_back(spot->sprite); mLocked.recycledSprites.push_back(spot->sprite);
} }
delete spot; delete spot;
} }
void TouchSpotController::fadeOutAndReleaseSpotLocked(Spot* spot) REQUIRES(mLock) { void TouchSpotController::fadeOutAndReleaseSpotLocked(Spot* spot) REQUIRES(mLock) {
if (spot->id != Spot::INVALID_ID) { if (spot->id != Spot::INVALID_ID) {
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); mContext.getPolicy()->loadPointerResources(&mResources, mDisplayId);
} }
bool TouchSpotController::doFadingAnimation(nsecs_t timestamp, bool keepAnimating) { bool TouchSpotController::doAnimations(nsecs_t timestamp) {
std::scoped_lock lock(mLock); 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 animationTime = mContext.getAnimationTime();
nsecs_t frameDelay = timestamp - animationTime; nsecs_t frameDelay = timestamp - animationTime;
size_t numSpots = mLocked.displaySpots.size(); size_t numSpots = mLocked.displaySpots.size();
@@ -233,4 +249,16 @@ bool TouchSpotController::doFadingAnimation(nsecs_t timestamp, bool keepAnimatin
return keepAnimating; 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 } // namespace android

View File

@@ -17,6 +17,8 @@
#ifndef _UI_TOUCH_SPOT_CONTROLLER_H #ifndef _UI_TOUCH_SPOT_CONTROLLER_H
#define _UI_TOUCH_SPOT_CONTROLLER_H #define _UI_TOUCH_SPOT_CONTROLLER_H
#include <functional>
#include "PointerControllerContext.h" #include "PointerControllerContext.h"
namespace android { namespace android {
@@ -34,7 +36,7 @@ public:
void clearSpots(); void clearSpots();
void reloadSpotResources(); void reloadSpotResources();
bool doFadingAnimation(nsecs_t timestamp, bool keepAnimating); bool doAnimations(nsecs_t timestamp);
private: private:
struct Spot { struct Spot {
@@ -76,6 +78,8 @@ private:
std::vector<Spot*> displaySpots; std::vector<Spot*> displaySpots;
std::vector<sp<Sprite>> recycledSprites; std::vector<sp<Sprite>> recycledSprites;
bool animating{false};
} mLocked GUARDED_BY(mLock); } mLocked GUARDED_BY(mLock);
Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots); Spot* getSpot(uint32_t id, const std::vector<Spot*>& spots);
@@ -84,6 +88,8 @@ private:
void releaseSpotLocked(Spot* spot); void releaseSpotLocked(Spot* spot);
void fadeOutAndReleaseSpotLocked(Spot* spot); void fadeOutAndReleaseSpotLocked(Spot* spot);
void fadeOutAndReleaseAllSpotsLocked(); void fadeOutAndReleaseAllSpotsLocked();
bool doFadingAnimationLocked(nsecs_t timestamp);
void startAnimationLocked();
}; };
} // namespace android } // namespace android