Home | History | Annotate | Download | only in Scheduler
      1 /*
      2  * Copyright (C) 2011 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 ATRACE_TAG ATRACE_TAG_GRAPHICS
     18 
     19 #include <pthread.h>
     20 #include <sched.h>
     21 #include <sys/types.h>
     22 
     23 #include <chrono>
     24 #include <cstdint>
     25 #include <optional>
     26 #include <type_traits>
     27 
     28 #include <android-base/stringprintf.h>
     29 
     30 #include <cutils/compiler.h>
     31 #include <cutils/sched_policy.h>
     32 
     33 #include <gui/DisplayEventReceiver.h>
     34 
     35 #include <utils/Errors.h>
     36 #include <utils/Trace.h>
     37 
     38 #include "EventThread.h"
     39 
     40 using namespace std::chrono_literals;
     41 
     42 namespace android {
     43 
     44 using base::StringAppendF;
     45 using base::StringPrintf;
     46 
     47 namespace {
     48 
     49 auto vsyncPeriod(VSyncRequest request) {
     50     return static_cast<std::underlying_type_t<VSyncRequest>>(request);
     51 }
     52 
     53 std::string toString(VSyncRequest request) {
     54     switch (request) {
     55         case VSyncRequest::None:
     56             return "VSyncRequest::None";
     57         case VSyncRequest::Single:
     58             return "VSyncRequest::Single";
     59         default:
     60             return StringPrintf("VSyncRequest::Periodic{period=%d}", vsyncPeriod(request));
     61     }
     62 }
     63 
     64 std::string toString(const EventThreadConnection& connection) {
     65     return StringPrintf("Connection{%p, %s}", &connection,
     66                         toString(connection.vsyncRequest).c_str());
     67 }
     68 
     69 std::string toString(const DisplayEventReceiver::Event& event) {
     70     switch (event.header.type) {
     71         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
     72             return StringPrintf("Hotplug{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", %s}",
     73                                 event.header.displayId,
     74                                 event.hotplug.connected ? "connected" : "disconnected");
     75         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
     76             return StringPrintf("VSync{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT
     77                                 ", count=%u}",
     78                                 event.header.displayId, event.vsync.count);
     79         default:
     80             return "Event{}";
     81     }
     82 }
     83 
     84 DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t timestamp,
     85                                         bool connected) {
     86     DisplayEventReceiver::Event event;
     87     event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, displayId, timestamp};
     88     event.hotplug.connected = connected;
     89     return event;
     90 }
     91 
     92 DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp,
     93                                       uint32_t count) {
     94     DisplayEventReceiver::Event event;
     95     event.header = {DisplayEventReceiver::DISPLAY_EVENT_VSYNC, displayId, timestamp};
     96     event.vsync.count = count;
     97     return event;
     98 }
     99 
    100 DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, int32_t configId) {
    101     DisplayEventReceiver::Event event;
    102     event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()};
    103     event.config.configId = configId;
    104     return event;
    105 }
    106 
    107 } // namespace
    108 
    109 EventThreadConnection::EventThreadConnection(EventThread* eventThread,
    110                                              ResyncCallback resyncCallback)
    111       : resyncCallback(std::move(resyncCallback)),
    112         mEventThread(eventThread),
    113         mChannel(gui::BitTube::DefaultSize) {}
    114 
    115 EventThreadConnection::~EventThreadConnection() {
    116     // do nothing here -- clean-up will happen automatically
    117     // when the main thread wakes up
    118 }
    119 
    120 void EventThreadConnection::onFirstRef() {
    121     // NOTE: mEventThread doesn't hold a strong reference on us
    122     mEventThread->registerDisplayEventConnection(this);
    123 }
    124 
    125 status_t EventThreadConnection::stealReceiveChannel(gui::BitTube* outChannel) {
    126     outChannel->setReceiveFd(mChannel.moveReceiveFd());
    127     return NO_ERROR;
    128 }
    129 
    130 status_t EventThreadConnection::setVsyncRate(uint32_t rate) {
    131     mEventThread->setVsyncRate(rate, this);
    132     return NO_ERROR;
    133 }
    134 
    135 void EventThreadConnection::requestNextVsync() {
    136     ATRACE_NAME("requestNextVsync");
    137     mEventThread->requestNextVsync(this);
    138 }
    139 
    140 status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
    141     ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    142     return size < 0 ? status_t(size) : status_t(NO_ERROR);
    143 }
    144 
    145 // ---------------------------------------------------------------------------
    146 
    147 EventThread::~EventThread() = default;
    148 
    149 namespace impl {
    150 
    151 EventThread::EventThread(std::unique_ptr<VSyncSource> src,
    152                          InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
    153       : EventThread(nullptr, std::move(src), std::move(interceptVSyncsCallback), threadName) {}
    154 
    155 EventThread::EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
    156                          const char* threadName)
    157       : EventThread(src, nullptr, std::move(interceptVSyncsCallback), threadName) {}
    158 
    159 EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
    160                          InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
    161       : mVSyncSource(src),
    162         mVSyncSourceUnique(std::move(uniqueSrc)),
    163         mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
    164         mThreadName(threadName) {
    165     if (src == nullptr) {
    166         mVSyncSource = mVSyncSourceUnique.get();
    167     }
    168     mVSyncSource->setCallback(this);
    169 
    170     mThread = std::thread([this]() NO_THREAD_SAFETY_ANALYSIS {
    171         std::unique_lock<std::mutex> lock(mMutex);
    172         threadMain(lock);
    173     });
    174 
    175     pthread_setname_np(mThread.native_handle(), threadName);
    176 
    177     pid_t tid = pthread_gettid_np(mThread.native_handle());
    178 
    179     // Use SCHED_FIFO to minimize jitter
    180     constexpr int EVENT_THREAD_PRIORITY = 2;
    181     struct sched_param param = {0};
    182     param.sched_priority = EVENT_THREAD_PRIORITY;
    183     if (pthread_setschedparam(mThread.native_handle(), SCHED_FIFO, &param) != 0) {
    184         ALOGE("Couldn't set SCHED_FIFO for EventThread");
    185     }
    186 
    187     set_sched_policy(tid, SP_FOREGROUND);
    188 }
    189 
    190 EventThread::~EventThread() {
    191     mVSyncSource->setCallback(nullptr);
    192 
    193     {
    194         std::lock_guard<std::mutex> lock(mMutex);
    195         mState = State::Quit;
    196         mCondition.notify_all();
    197     }
    198     mThread.join();
    199 }
    200 
    201 void EventThread::setPhaseOffset(nsecs_t phaseOffset) {
    202     std::lock_guard<std::mutex> lock(mMutex);
    203     mVSyncSource->setPhaseOffset(phaseOffset);
    204 }
    205 
    206 sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
    207     return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
    208 }
    209 
    210 status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
    211     std::lock_guard<std::mutex> lock(mMutex);
    212 
    213     // this should never happen
    214     auto it = std::find(mDisplayEventConnections.cbegin(),
    215             mDisplayEventConnections.cend(), connection);
    216     if (it != mDisplayEventConnections.cend()) {
    217         ALOGW("DisplayEventConnection %p already exists", connection.get());
    218         mCondition.notify_all();
    219         return ALREADY_EXISTS;
    220     }
    221 
    222     mDisplayEventConnections.push_back(connection);
    223     mCondition.notify_all();
    224     return NO_ERROR;
    225 }
    226 
    227 void EventThread::removeDisplayEventConnectionLocked(const wp<EventThreadConnection>& connection) {
    228     auto it = std::find(mDisplayEventConnections.cbegin(),
    229             mDisplayEventConnections.cend(), connection);
    230     if (it != mDisplayEventConnections.cend()) {
    231         mDisplayEventConnections.erase(it);
    232     }
    233 }
    234 
    235 void EventThread::setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) {
    236     if (static_cast<std::underlying_type_t<VSyncRequest>>(rate) < 0) {
    237         return;
    238     }
    239 
    240     std::lock_guard<std::mutex> lock(mMutex);
    241 
    242     const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
    243     if (connection->vsyncRequest != request) {
    244         connection->vsyncRequest = request;
    245         mCondition.notify_all();
    246     }
    247 }
    248 
    249 void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection) {
    250     if (connection->resyncCallback) {
    251         connection->resyncCallback();
    252     }
    253 
    254     std::lock_guard<std::mutex> lock(mMutex);
    255 
    256     if (connection->vsyncRequest == VSyncRequest::None) {
    257         connection->vsyncRequest = VSyncRequest::Single;
    258         mCondition.notify_all();
    259     }
    260 }
    261 
    262 void EventThread::onScreenReleased() {
    263     std::lock_guard<std::mutex> lock(mMutex);
    264     if (!mVSyncState || mVSyncState->synthetic) {
    265         return;
    266     }
    267 
    268     mVSyncState->synthetic = true;
    269     mCondition.notify_all();
    270 }
    271 
    272 void EventThread::onScreenAcquired() {
    273     std::lock_guard<std::mutex> lock(mMutex);
    274     if (!mVSyncState || !mVSyncState->synthetic) {
    275         return;
    276     }
    277 
    278     mVSyncState->synthetic = false;
    279     mCondition.notify_all();
    280 }
    281 
    282 void EventThread::onVSyncEvent(nsecs_t timestamp) {
    283     std::lock_guard<std::mutex> lock(mMutex);
    284 
    285     LOG_FATAL_IF(!mVSyncState);
    286     mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count));
    287     mCondition.notify_all();
    288 }
    289 
    290 void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) {
    291     std::lock_guard<std::mutex> lock(mMutex);
    292 
    293     mPendingEvents.push_back(makeHotplug(displayId, systemTime(), connected));
    294     mCondition.notify_all();
    295 }
    296 
    297 void EventThread::onConfigChanged(PhysicalDisplayId displayId, int32_t configId) {
    298     std::lock_guard<std::mutex> lock(mMutex);
    299 
    300     mPendingEvents.push_back(makeConfigChanged(displayId, configId));
    301     mCondition.notify_all();
    302 }
    303 
    304 void EventThread::threadMain(std::unique_lock<std::mutex>& lock) {
    305     DisplayEventConsumers consumers;
    306 
    307     while (mState != State::Quit) {
    308         std::optional<DisplayEventReceiver::Event> event;
    309 
    310         // Determine next event to dispatch.
    311         if (!mPendingEvents.empty()) {
    312             event = mPendingEvents.front();
    313             mPendingEvents.pop_front();
    314 
    315             switch (event->header.type) {
    316                 case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
    317                     if (event->hotplug.connected && !mVSyncState) {
    318                         mVSyncState.emplace(event->header.displayId);
    319                     } else if (!event->hotplug.connected && mVSyncState &&
    320                                mVSyncState->displayId == event->header.displayId) {
    321                         mVSyncState.reset();
    322                     }
    323                     break;
    324 
    325                 case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
    326                     if (mInterceptVSyncsCallback) {
    327                         mInterceptVSyncsCallback(event->header.timestamp);
    328                     }
    329                     break;
    330             }
    331         }
    332 
    333         bool vsyncRequested = false;
    334 
    335         // Find connections that should consume this event.
    336         auto it = mDisplayEventConnections.begin();
    337         while (it != mDisplayEventConnections.end()) {
    338             if (const auto connection = it->promote()) {
    339                 vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
    340 
    341                 if (event && shouldConsumeEvent(*event, connection)) {
    342                     consumers.push_back(connection);
    343                 }
    344 
    345                 ++it;
    346             } else {
    347                 it = mDisplayEventConnections.erase(it);
    348             }
    349         }
    350 
    351         if (!consumers.empty()) {
    352             dispatchEvent(*event, consumers);
    353             consumers.clear();
    354         }
    355 
    356         State nextState;
    357         if (mVSyncState && vsyncRequested) {
    358             nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync;
    359         } else {
    360             ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected");
    361             nextState = State::Idle;
    362         }
    363 
    364         if (mState != nextState) {
    365             if (mState == State::VSync) {
    366                 mVSyncSource->setVSyncEnabled(false);
    367             } else if (nextState == State::VSync) {
    368                 mVSyncSource->setVSyncEnabled(true);
    369             }
    370 
    371             mState = nextState;
    372         }
    373 
    374         if (event) {
    375             continue;
    376         }
    377 
    378         // Wait for event or client registration/request.
    379         if (mState == State::Idle) {
    380             mCondition.wait(lock);
    381         } else {
    382             // Generate a fake VSYNC after a long timeout in case the driver stalls. When the
    383             // display is off, keep feeding clients at 60 Hz.
    384             const auto timeout = mState == State::SyntheticVSync ? 16ms : 1000ms;
    385             if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) {
    386                 ALOGW_IF(mState == State::VSync, "Faking VSYNC due to driver stall");
    387 
    388                 LOG_FATAL_IF(!mVSyncState);
    389                 mPendingEvents.push_back(makeVSync(mVSyncState->displayId,
    390                                                    systemTime(SYSTEM_TIME_MONOTONIC),
    391                                                    ++mVSyncState->count));
    392             }
    393         }
    394     }
    395 }
    396 
    397 bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
    398                                      const sp<EventThreadConnection>& connection) const {
    399     switch (event.header.type) {
    400         case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
    401         case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
    402             return true;
    403 
    404         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
    405             switch (connection->vsyncRequest) {
    406                 case VSyncRequest::None:
    407                     return false;
    408                 case VSyncRequest::Single:
    409                     connection->vsyncRequest = VSyncRequest::None;
    410                     return true;
    411                 case VSyncRequest::Periodic:
    412                     return true;
    413                 default:
    414                     return event.vsync.count % vsyncPeriod(connection->vsyncRequest) == 0;
    415             }
    416 
    417         default:
    418             return false;
    419     }
    420 }
    421 
    422 void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
    423                                 const DisplayEventConsumers& consumers) {
    424     for (const auto& consumer : consumers) {
    425         switch (consumer->postEvent(event)) {
    426             case NO_ERROR:
    427                 break;
    428 
    429             case -EAGAIN:
    430                 // TODO: Try again if pipe is full.
    431                 ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
    432                       toString(*consumer).c_str());
    433                 break;
    434 
    435             default:
    436                 // Treat EPIPE and other errors as fatal.
    437                 removeDisplayEventConnectionLocked(consumer);
    438         }
    439     }
    440 }
    441 
    442 void EventThread::dump(std::string& result) const {
    443     std::lock_guard<std::mutex> lock(mMutex);
    444 
    445     StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState));
    446     if (mVSyncState) {
    447         StringAppendF(&result, "{displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", count=%u%s}\n",
    448                       mVSyncState->displayId, mVSyncState->count,
    449                       mVSyncState->synthetic ? ", synthetic" : "");
    450     } else {
    451         StringAppendF(&result, "none\n");
    452     }
    453 
    454     StringAppendF(&result, "  pending events (count=%zu):\n", mPendingEvents.size());
    455     for (const auto& event : mPendingEvents) {
    456         StringAppendF(&result, "    %s\n", toString(event).c_str());
    457     }
    458 
    459     StringAppendF(&result, "  connections (count=%zu):\n", mDisplayEventConnections.size());
    460     for (const auto& ptr : mDisplayEventConnections) {
    461         if (const auto connection = ptr.promote()) {
    462             StringAppendF(&result, "    %s\n", toString(*connection).c_str());
    463         }
    464     }
    465 }
    466 
    467 const char* EventThread::toCString(State state) {
    468     switch (state) {
    469         case State::Idle:
    470             return "Idle";
    471         case State::Quit:
    472             return "Quit";
    473         case State::SyntheticVSync:
    474             return "SyntheticVSync";
    475         case State::VSync:
    476             return "VSync";
    477     }
    478 }
    479 
    480 } // namespace impl
    481 } // namespace android
    482