• 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 #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