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