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