163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright/* 263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * Copyright (C) 2015 The Android Open Source Project 363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * 463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * Licensed under the Apache License, Version 2.0 (the "License"); 563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * you may not use this file except in compliance with the License. 663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * You may obtain a copy of the License at 763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * 863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * http://www.apache.org/licenses/LICENSE-2.0 963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * 1063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * Unless required by applicable law or agreed to in writing, software 1163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * distributed under the License is distributed on an "AS IS" BASIS, 1263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * See the License for the specific language governing permissions and 1463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright * limitations under the License. 1563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright */ 1663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 1763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#define LOG_TAG "Choreographer" 1863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright//#define LOG_NDEBUG 0 1963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 2063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <cinttypes> 2163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <queue> 2263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <thread> 2363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 2463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <android/choreographer.h> 2563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <androidfw/DisplayEventDispatcher.h> 2663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <gui/ISurfaceComposer.h> 2763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <utils/Looper.h> 2863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <utils/Mutex.h> 2963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright#include <utils/Timers.h> 3063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 3163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightnamespace android { 3263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 3363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightstatic inline const char* toString(bool value) { 3463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return value ? "true" : "false"; 3563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 3663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 3763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightstruct FrameCallback { 3863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AChoreographer_frameCallback callback; 3963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright void* data; 4063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright nsecs_t dueTime; 4163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 4263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright inline bool operator<(const FrameCallback& rhs) const { 4363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright // Note that this is intentionally flipped because we want callbacks due sooner to be at 4463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright // the head of the queue 4563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return dueTime > rhs.dueTime; 4663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 4763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright}; 4863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 4963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 5063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightclass Choreographer : public DisplayEventDispatcher, public MessageHandler { 5163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightpublic: 5263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright void postFrameCallback(AChoreographer_frameCallback cb, void* data); 5363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright void postFrameCallbackDelayed(AChoreographer_frameCallback cb, void* data, nsecs_t delay); 5463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 5563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright enum { 5663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright MSG_SCHEDULE_CALLBACKS = 0, 5763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright MSG_SCHEDULE_VSYNC = 1 5863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright }; 5963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright virtual void handleMessage(const Message& message) override; 6063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 6163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright static Choreographer* getForThread(); 6263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 6363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightprotected: 6463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright virtual ~Choreographer() = default; 6563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 6663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightprivate: 67c6baf563ba6aa207a48317c177b29f1d2b70cf3dChih-Hung Hsieh explicit Choreographer(const sp<Looper>& looper); 6863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright Choreographer(const Choreographer&) = delete; 6963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 7063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright virtual void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count); 7163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright virtual void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected); 7263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 7363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright void scheduleCallbacks(); 7463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 7563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright // Protected by mLock 7663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright std::priority_queue<FrameCallback> mCallbacks; 7763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 7863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright mutable Mutex mLock; 7963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 8063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright const sp<Looper> mLooper; 8163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright const std::thread::id mThreadId; 8263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright}; 8363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 8463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 85c0d3d3f80588c1bef5acd7d56ae701ac7271c7c6Michael Wrightstatic thread_local Choreographer* gChoreographer; 8663c168acf7a99a0120566a0a09a40ae04c789c5aMichael WrightChoreographer* Choreographer::getForThread() { 8763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (gChoreographer == nullptr) { 8863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright sp<Looper> looper = Looper::getForThread(); 8963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (!looper.get()) { 9063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright ALOGW("No looper prepared for thread"); 9163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return nullptr; 9263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 9363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright gChoreographer = new Choreographer(looper); 9463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright status_t result = gChoreographer->initialize(); 9563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (result != OK) { 9663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright ALOGW("Failed to initialize"); 9763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return nullptr; 9863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 9963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 10063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return gChoreographer; 10163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 10263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 10363c168acf7a99a0120566a0a09a40ae04c789c5aMichael WrightChoreographer::Choreographer(const sp<Looper>& looper) : 10463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright DisplayEventDispatcher(looper), mLooper(looper), mThreadId(std::this_thread::get_id()) { 10563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 10663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 10763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid Choreographer::postFrameCallback(AChoreographer_frameCallback cb, void* data) { 10863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright postFrameCallbackDelayed(cb, data, 0); 10963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 11063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 11163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid Choreographer::postFrameCallbackDelayed( 11263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AChoreographer_frameCallback cb, void* data, nsecs_t delay) { 11363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 11463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright FrameCallback callback{cb, data, now + delay}; 11563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright { 11663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AutoMutex _l{mLock}; 11763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright mCallbacks.push(callback); 11863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 11963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (callback.dueTime <= now) { 12063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (std::this_thread::get_id() != mThreadId) { 12163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright Message m{MSG_SCHEDULE_VSYNC}; 12263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright mLooper->sendMessage(this, m); 12363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } else { 12463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright scheduleVsync(); 12563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 12663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } else { 12763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright Message m{MSG_SCHEDULE_CALLBACKS}; 12863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright mLooper->sendMessageDelayed(delay, this, m); 12963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 13063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 13163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 13263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid Choreographer::scheduleCallbacks() { 13363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AutoMutex _{mLock}; 13463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 13563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (mCallbacks.top().dueTime <= now) { 13663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright ALOGV("choreographer %p ~ scheduling vsync", this); 13763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright scheduleVsync(); 13863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return; 13963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 14063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 14163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 14263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 14363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid Choreographer::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t) { 14463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright if (id != ISurfaceComposer::eDisplayIdMain) { 14563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright ALOGV("choreographer %p ~ ignoring vsync signal for non-main display (id=%d)", this, id); 14663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright scheduleVsync(); 14763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return; 14863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 14963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright std::vector<FrameCallback> callbacks{}; 15063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright { 15163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AutoMutex _l{mLock}; 15263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); 15363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright while (!mCallbacks.empty() && mCallbacks.top().dueTime < now) { 15463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright callbacks.push_back(mCallbacks.top()); 15563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright mCallbacks.pop(); 15663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 15763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 15863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright for (const auto& cb : callbacks) { 15963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright cb.callback(timestamp, cb.data); 16063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 16163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 16263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 16363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid Choreographer::dispatchHotplug(nsecs_t, int32_t id, bool connected) { 16463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright ALOGV("choreographer %p ~ received hotplug event (id=%" PRId32 ", connected=%s), ignoring.", 16563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright this, id, toString(connected)); 16663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 16763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 16863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid Choreographer::handleMessage(const Message& message) { 16963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright switch (message.what) { 17063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright case MSG_SCHEDULE_CALLBACKS: 17163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright scheduleCallbacks(); 17263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright break; 17363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright case MSG_SCHEDULE_VSYNC: 17463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright scheduleVsync(); 17563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright break; 17663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright } 17763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 17863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 17963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 18063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 18163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright/* Glue for the NDK interface */ 18263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 18363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightusing android::Choreographer; 18463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 18563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightstatic inline Choreographer* AChoreographer_to_Choreographer(AChoreographer* choreographer) { 18663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return reinterpret_cast<Choreographer*>(choreographer); 18763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 18863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 18963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightstatic inline AChoreographer* Choreographer_to_AChoreographer(Choreographer* choreographer) { 19063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return reinterpret_cast<AChoreographer*>(choreographer); 19163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 19263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 19363c168acf7a99a0120566a0a09a40ae04c789c5aMichael WrightAChoreographer* AChoreographer_getInstance() { 19463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright return Choreographer_to_AChoreographer(Choreographer::getForThread()); 19563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 19663c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright 19763c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid AChoreographer_postFrameCallback(AChoreographer* choreographer, 19863c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AChoreographer_frameCallback callback, void* data) { 19963c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AChoreographer_to_Choreographer(choreographer)->postFrameCallback(callback, data); 20063c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 20163c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wrightvoid AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, 20263c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AChoreographer_frameCallback callback, void* data, long delayMillis) { 20363c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright AChoreographer_to_Choreographer(choreographer)->postFrameCallbackDelayed( 20463c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright callback, data, ms2ns(delayMillis)); 20563c168acf7a99a0120566a0a09a40ae04c789c5aMichael Wright} 206