1 /* 2 * Copyright (C) 2015 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 #define LOG_TAG "DisplayEventDispatcher" 18 19 #include <cinttypes> 20 #include <cstdint> 21 22 #include <androidfw/DisplayEventDispatcher.h> 23 #include <gui/DisplayEventReceiver.h> 24 #include <utils/Log.h> 25 #include <utils/Looper.h> 26 27 #include <utils/Timers.h> 28 29 namespace android { 30 31 // Number of events to read at a time from the DisplayEventDispatcher pipe. 32 // The value should be large enough that we can quickly drain the pipe 33 // using just a few large reads. 34 static const size_t EVENT_BUFFER_SIZE = 100; 35 36 DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper) : 37 mLooper(looper), mWaitingForVsync(false) { 38 ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this); 39 } 40 41 status_t DisplayEventDispatcher::initialize() { 42 status_t result = mReceiver.initCheck(); 43 if (result) { 44 ALOGW("Failed to initialize display event receiver, status=%d", result); 45 return result; 46 } 47 48 int rc = mLooper->addFd(mReceiver.getFd(), 0, Looper::EVENT_INPUT, 49 this, NULL); 50 if (rc < 0) { 51 return UNKNOWN_ERROR; 52 } 53 return OK; 54 } 55 56 void DisplayEventDispatcher::dispose() { 57 ALOGV("dispatcher %p ~ Disposing display event dispatcher.", this); 58 59 if (!mReceiver.initCheck()) { 60 mLooper->removeFd(mReceiver.getFd()); 61 } 62 } 63 64 status_t DisplayEventDispatcher::scheduleVsync() { 65 if (!mWaitingForVsync) { 66 ALOGV("dispatcher %p ~ Scheduling vsync.", this); 67 68 // Drain all pending events. 69 nsecs_t vsyncTimestamp; 70 int32_t vsyncDisplayId; 71 uint32_t vsyncCount; 72 if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { 73 ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", 74 this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp))); 75 } 76 77 status_t status = mReceiver.requestNextVsync(); 78 if (status) { 79 ALOGW("Failed to request next vsync, status=%d", status); 80 return status; 81 } 82 83 mWaitingForVsync = true; 84 } 85 return OK; 86 } 87 88 int DisplayEventDispatcher::handleEvent(int, int events, void*) { 89 if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { 90 ALOGE("Display event receiver pipe was closed or an error occurred. " 91 "events=0x%x", events); 92 return 0; // remove the callback 93 } 94 95 if (!(events & Looper::EVENT_INPUT)) { 96 ALOGW("Received spurious callback for unhandled poll event. " 97 "events=0x%x", events); 98 return 1; // keep the callback 99 } 100 101 // Drain all pending events, keep the last vsync. 102 nsecs_t vsyncTimestamp; 103 int32_t vsyncDisplayId; 104 uint32_t vsyncCount; 105 if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) { 106 ALOGV("dispatcher %p ~ Vsync pulse: timestamp=%" PRId64 ", id=%d, count=%d", 107 this, ns2ms(vsyncTimestamp), vsyncDisplayId, vsyncCount); 108 mWaitingForVsync = false; 109 dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount); 110 } 111 112 return 1; // keep the callback 113 } 114 115 bool DisplayEventDispatcher::processPendingEvents( 116 nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) { 117 bool gotVsync = false; 118 DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE]; 119 ssize_t n; 120 while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) { 121 ALOGV("dispatcher %p ~ Read %d events.", this, int(n)); 122 for (ssize_t i = 0; i < n; i++) { 123 const DisplayEventReceiver::Event& ev = buf[i]; 124 switch (ev.header.type) { 125 case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: 126 // Later vsync events will just overwrite the info from earlier 127 // ones. That's fine, we only care about the most recent. 128 gotVsync = true; 129 *outTimestamp = ev.header.timestamp; 130 *outId = ev.header.id; 131 *outCount = ev.vsync.count; 132 break; 133 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: 134 dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected); 135 break; 136 default: 137 ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type); 138 break; 139 } 140 } 141 } 142 if (n < 0) { 143 ALOGW("Failed to get events from display event dispatcher, status=%d", status_t(n)); 144 } 145 return gotVsync; 146 } 147 } 148