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 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 47 PointerControllerContext::~PointerControllerContext() { 48 mLooper->removeMessages(mHandler); 49 } 50 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 60 void PointerControllerContext::resetInactivityTimeout() { 61 std::scoped_lock lock(mLock); 62 resetInactivityTimeoutLocked(); 63 } 64 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 74 void PointerControllerContext::removeInactivityTimeout() { 75 std::scoped_lock lock(mLock); 76 mLooper->removeMessages(mHandler, MessageHandler::MSG_INACTIVITY_TIMEOUT); 77 } 78 79 nsecs_t PointerControllerContext::getAnimationTime() REQUIRES(mAnimator.mLock) { 80 return mAnimator.getAnimationTimeLocked(); 81 } 82 83 void PointerControllerContext::setHandlerController(std::shared_ptr<PointerController> controller) { 84 mHandler->pointerController = controller; 85 } 86 87 void PointerControllerContext::setCallbackController( 88 std::shared_ptr<PointerController> controller) { 89 mCallback->pointerController = controller; 90 } 91 92 sp<PointerControllerPolicyInterface> PointerControllerContext::getPolicy() { 93 return mPolicy; 94 } 95 96 sp<SpriteController> PointerControllerContext::getSpriteController() { 97 return mSpriteController; 98 } 99 100 void PointerControllerContext::handleDisplayEvents() { 101 mAnimator.handleVsyncEvents(); 102 } 103 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 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 141 void PointerControllerContext::addAnimationCallback(int32_t displayId, 142 std::function<bool(nsecs_t)> callback) { 143 mAnimator.addCallback(displayId, callback); 144 } 145 146 void PointerControllerContext::removeAnimationCallback(int32_t displayId) { 147 mAnimator.removeCallback(displayId); 148 } 149 150 PointerControllerContext::PointerAnimator::PointerAnimator(PointerControllerContext& context) 151 : mContext(context) { 152 initializeDisplayEventReceiver(); 153 } 154 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 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 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 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 200 nsecs_t PointerControllerContext::PointerAnimator::getAnimationTimeLocked() REQUIRES(mLock) { 201 return mLocked.animationTime; 202 } 203 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 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