blob: 2d7e22b011129d45848160884203f8443fae2027 [file] [log] [blame]
Liam Harringtonc782be62020-07-17 19:48:24 +00001/*
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
20namespace {
21// Time to wait before starting the fade when the pointer is inactive.
22const nsecs_t INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL = 15 * 1000 * 1000000LL; // 15 seconds
23const 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.
26const int EVENT_BUFFER_SIZE = 100;
27} // namespace
28
29namespace android {
30
31// --- PointerControllerContext ---
32
33PointerControllerContext::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 std::scoped_lock lock(mLock);
43 mLocked.inactivityTimeout = InactivityTimeout::NORMAL;
44 mLocked.animationPending = false;
45}
46
47PointerControllerContext::~PointerControllerContext() {
48 mLooper->removeMessages(mHandler);
49}
50
51void 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
60void PointerControllerContext::startAnimation() {
61 std::scoped_lock lock(mLock);
62 if (!mLocked.animationPending) {
63 mLocked.animationPending = true;
64 mLocked.animationTime = systemTime(SYSTEM_TIME_MONOTONIC);
65 mDisplayEventReceiver.requestNextVsync();
66 }
67}
68
69void PointerControllerContext::resetInactivityTimeout() {
70 std::scoped_lock lock(mLock);
71 resetInactivityTimeoutLocked();
72}
73
74void PointerControllerContext::resetInactivityTimeoutLocked() REQUIRES(mLock) {
75 mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
76
77 nsecs_t timeout = mLocked.inactivityTimeout == InactivityTimeout::SHORT
78 ? INACTIVITY_TIMEOUT_DELAY_TIME_SHORT
79 : INACTIVITY_TIMEOUT_DELAY_TIME_NORMAL;
80 mLooper->sendMessageDelayed(timeout, mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
81}
82
83void PointerControllerContext::removeInactivityTimeout() {
84 std::scoped_lock lock(mLock);
85 mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT);
86}
87
88void PointerControllerContext::setAnimationPending(bool animationPending) {
89 std::scoped_lock lock(mLock);
90 mLocked.animationPending = animationPending;
91}
92
93nsecs_t PointerControllerContext::getAnimationTime() {
94 std::scoped_lock lock(mLock);
95 return mLocked.animationTime;
96}
97
98void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) {
99 mHandler->pointerController = controller;
100}
101
102void PointerControllerContext::setCallbackController(
103 std::shared_ptr<PointerController> controller) {
104 mCallback->pointerController = controller;
105}
106
107sp<PointerControllerPolicyInterface> PointerControllerContext::getPolicy() {
108 return mPolicy;
109}
110
111sp<SpriteController> PointerControllerContext::getSpriteController() {
112 return mSpriteController;
113}
114
115void PointerControllerContext::initializeDisplayEventReceiver() {
116 if (mDisplayEventReceiver.initCheck() == NO_ERROR) {
117 mLooper->addFd(mDisplayEventReceiver.getFd(), Looper::POLL_CALLBACK, Looper::EVENT_INPUT,
118 mCallback, nullptr);
119 } else {
120 ALOGE("Failed to initialize DisplayEventReceiver.");
121 }
122}
123
124void PointerControllerContext::handleDisplayEvents() {
125 bool gotVsync = false;
126 ssize_t n;
127 nsecs_t timestamp;
128 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
129 while ((n = mDisplayEventReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
130 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
131 if (buf[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
132 timestamp = buf[i].header.timestamp;
133 gotVsync = true;
134 }
135 }
136 }
137 if (gotVsync) {
138 mController.doAnimate(timestamp);
139 }
140}
141
142void PointerControllerContext::MessageHandler::handleMessage(const Message& message) {
143 std::shared_ptr<PointerController> controller = pointerController.lock();
144
145 if (controller == nullptr) {
146 ALOGE("PointerController instance was released before processing message: what=%d",
147 message.what);
148 return;
149 }
150 switch (message.what) {
151 case MSG_INACTIVITY_TIMEOUT:
152 controller->doInactivityTimeout();
153 break;
154 }
155}
156
157int PointerControllerContext::LooperCallback::handleEvent(int /* fd */, int events,
158 void* /* data */) {
159 std::shared_ptr<PointerController> controller = pointerController.lock();
160 if (controller == nullptr) {
161 ALOGW("PointerController instance was released with pending callbacks. events=0x%x",
162 events);
163 return 0; // Remove the callback, the PointerController is gone anyways
164 }
165 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
166 ALOGE("Display event receiver pipe was closed or an error occurred. events=0x%x", events);
167 return 0; // remove the callback
168 }
169
170 if (!(events & Looper::EVENT_INPUT)) {
171 ALOGW("Received spurious callback for unhandled poll event. events=0x%x", events);
172 return 1; // keep the callback
173 }
174
175 controller->mContext.handleDisplayEvents();
176 return 1; // keep the callback
177}
178
179} // namespace android