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