1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "PointerControllerContext.h"
18 #include "PointerController.h"
19
20 namespace {
21 // Time to wait before starting the fade when the pointer is inactive.
22 const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
23 const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_SHORT = 3 * 1000 * 1000000LL; // 3 seconds
24
25 // The number of events to be read at once for DisplayEventReceiver.
26 const int EVENT_BUFFER_SIZE = 100;
27 } // namespace
28
29 namespace android {
30
31 // --- PointerControllerContext ---
32
PointerControllerContext(const sp<PointerControllerPolicyInterface> & policy,const sp<Looper> & looper,const sp<SpriteController> & spriteController,PointerController & controller)33 PointerControllerContext::PointerControllerContext(
34 const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
35 const sp<SpriteController>& spriteController, PointerController& controller)
36 : mPolicy(policy),
37 mLooper(looper),
38 mSpriteController(spriteController),
39 mHandler(new MessageHandler()),
40 mCallback(new LooperCallback()),
41 mController(controller),
42 mAnimator(*this) {
43 std::scoped_lock lock(mLock);
44 mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
45 }
46
~PointerControllerContext()47 PointerControllerContext::~PointerControllerContext() {
48 mLooper->removeMessages(mHandler);
49 }
50
setInactivityTimeout(InactivityTimeout inactivityTimeout)51 void PointerControllerContext::setInactivityTimeout(InactivityTimeout inactivityTimeout) {
52 std::scoped_lock lock(mLock);
53
54 if (mLocked.inactivityTimeout != inactivityTimeout) {
55 mLocked.inactivityTimeout = inactivityTimeout;
56 resetInactivityTimeoutLocked();
57 }
58 }
59
resetInactivityTimeout()60 void PointerControllerContext::resetInactivityTimeout() {
61 std::scoped_lock lock(mLock);
62 resetInactivityTimeoutLocked();
63 }
64
resetInactivityTimeoutLocked()65 void PointerControllerContext::resetInactivityTimeoutLocked() REQUIRES(mLock) {
66 mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
67
68 nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT
69 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT
70 : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
71 mLooper->sendMessageDelayed(timeout, mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
72 }
73
removeInactivityTimeout()74 void PointerControllerContext::removeInactivityTimeout() {
75 std::scoped_lock lock(mLock);
76 mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
77 }
78
getAnimationTime()79 nsecs_t PointerControllerContext::getAnimationTime() REQUIRES(mAnimator.mLock) {
80 return mAnimator.getAnimationTimeLocked();
81 }
82
setHandlerController(std::shared_ptr<PointerController> controller)83 void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) {
84 mHandler->pointerController = controller;
85 }
86
setCallbackController(std::shared_ptr<PointerController> controller)87 void PointerControllerContext::setCallbackController(
88 std::shared_ptr<PointerController> controller) {
89 mCallback->pointerController = controller;
90 }
91
getPolicy()92 sp<PointerControllerPolicyInterface> PointerControllerContext::getPolicy() {
93 return mPolicy;
94 }
95
getSpriteController()96 sp<SpriteController> PointerControllerContext::getSpriteController() {
97 return mSpriteController;
98 }
99
handleDisplayEvents()100 void PointerControllerContext::handleDisplayEvents() {
101 mAnimator.handleVsyncEvents();
102 }
103
handleMessage(const Message & message)104 void PointerControllerContext::MessageHandler::handleMessage(const Message& message) {
105 std::shared_ptr<PointerController> controller = pointerController.lock();
106
107 if (controller == nullptr) {
108 ALOGE("PointerController instance was released before processing message: what=%d",
109 message.what);
110 return;
111 }
112 switch (message.what) {
113 case MSG_INACTIVITY_TIMEOUT:
114 controller->doInactivityTimeout();
115 break;
116 }
117 }
118
handleEvent(int,int events,void *)119 int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int events,
120 void* /* data */) {
121 std::shared_ptr<PointerController> controller = pointerController.lock();
122 if (controller == nullptr) {
123 ALOGW("PointerController instance was released with pending callbacks. events=0x%x",
124 events);
125 return 0; // Remove the callback, the PointerController is gone anyways
126 }
127 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
128 ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events);
129 return 0; // remove the callback
130 }
131
132 if (!(events & Looper::EVENT_INPUT)) {
133 ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events);
134 return 1; // keep the callback
135 }
136
137 controller->mContext.handleDisplayEvents();
138 return 1; // keep the callback
139 }
140
addAnimationCallback(int32_t displayId,std::function<bool (nsecs_t)> callback)141 void PointerControllerContext::addAnimationCallback(int32_t displayId,
142 std::function<bool(nsecs_t)> callback) {
143 mAnimator.addCallback(displayId, callback);
144 }
145
removeAnimationCallback(int32_t displayId)146 void PointerControllerContext::removeAnimationCallback(int32_t displayId) {
147 mAnimator.removeCallback(displayId);
148 }
149
PointerAnimator(PointerControllerContext & context)150 PointerControllerContext::PointerAnimator::PointerAnimator(PointerControllerContext& context)
151 : mContext(context) {
152 initializeDisplayEventReceiver();
153 }
154
initializeDisplayEventReceiver()155 void PointerControllerContext::PointerAnimator::initializeDisplayEventReceiver() {
156 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
157 mContext.mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK,
158 Looper::EVENT_INPUT, mContext.mCallback, nullptr);
159 } else {
160 ALOGE("Failed to initialize DisplayEventReceiver.");
161 }
162 }
163
addCallback(int32_t displayId,std::function<bool (nsecs_t)> callback)164 void PointerControllerContext::PointerAnimator::addCallback(int32_t displayId,
165 std::function<bool(nsecs_t)> callback) {
166 std::scoped_lock lock(mLock);
167 mLocked.callbacks[displayId] = callback;
168 startAnimationLocked();
169 }
170
removeCallback(int32_t displayId)171 void PointerControllerContext::PointerAnimator::removeCallback(int32_t displayId) {
172 std::scoped_lock lock(mLock);
173 auto it = mLocked.callbacks.find(displayId);
174 if (it == mLocked.callbacks.end()) {
175 return;
176 }
177 mLocked.callbacks.erase(it);
178 }
179
handleVsyncEvents()180 void PointerControllerContext::PointerAnimator::handleVsyncEvents() {
181 bool gotVsync = false;
182 ssize_t n;
183 nsecs_t timestamp;
184 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
185 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
186 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
187 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
188 timestamp = buf[i].header.timestamp;
189 gotVsync = true;
190 }
191 }
192 }
193 if (gotVsync) {
194 std::scoped_lock lock(mLock);
195 mLocked.animationPending = false;
196 handleCallbacksLocked(timestamp);
197 }
198 }
199
getAnimationTimeLocked()200 nsecs_t PointerControllerContext::PointerAnimator::getAnimationTimeLocked() REQUIRES(mLock) {
201 return mLocked.animationTime;
202 }
203
startAnimationLocked()204 void PointerControllerContext::PointerAnimator::startAnimationLocked() REQUIRES(mLock) {
205 if (!mLocked.animationPending) {
206 mLocked.animationPending = true;
207 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
208 mDisplayEventReceiver.requestNextVsync();
209 }
210 }
211
handleCallbacksLocked(nsecs_t timestamp)212 void PointerControllerContext::PointerAnimator::handleCallbacksLocked(nsecs_t timestamp)
213 REQUIRES(mLock) {
214 for (auto it = mLocked.callbacks.begin(); it != mLocked.callbacks.end();) {
215 bool keepCallback = it->second(timestamp);
216 if (!keepCallback) {
217 it = mLocked.callbacks.erase(it);
218 } else {
219 ++it;
220 }
221 }
222
223 if (!mLocked.callbacks.empty()) {
224 startAnimationLocked();
225 }
226 }
227
228 } // namespace android
229