Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f51775db authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Add GPU completion to FrameMetrics (2/3)

- Add SurfaceStatsCallback to TransactionCompletedListener
- Register a callback in RenderProxy to be called when we have
surface stats from SF via the BLAST callback.
- Instead of finishing a frame for frame metrics reporting
immediately, wait until BLAST callback fires, note GPU completion
time and finish frame.
- Expose GPU_COMPLETION in FrameMetrics
- Modify TOTAL_DURATION to also include GPU_COMPLETION

Test: FrameMetricsListenerTest
Fixes: 171046219
Change-Id: If4b63c6a4c49c9ce2f31410d7f33541b0e6bf594
parent e06403fa
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -43,3 +43,8 @@ filegroup {
        ":framework_native_aidl_gui",
        ":framework_native_aidl_gui",
    ],
    ],
}
}

cc_library_headers{
    name: "libandroid_headers_private",
    export_include_dirs: ["include/private"],
}
 No newline at end of file
+71 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H
#define ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H

#include <stdint.h>

__BEGIN_DECLS

struct ASurfaceControl;
struct ASurfaceControlStats;

typedef struct ASurfaceControlStats ASurfaceControlStats;

/**
 * Callback to be notified when surface stats for a specific surface control are available.
 */
typedef void (*ASurfaceControl_SurfaceStatsListener)(void* context,
        ASurfaceControl* control, ASurfaceControlStats* stats);

/**
 * Registers a callback to be invoked when surface stats from a specific surface are available.
 *
 * \param context Optional context provided by the client that is passed into
 * the callback.
 *
 * \param control The surface to retrieve callbacks for.
 *
 * \param func The callback to be invoked when surface stats are available.
 */
void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, void* context,
        ASurfaceControl_SurfaceStatsListener func);

/**
 * Unregisters a callback to be invoked when surface stats from a specific surface are available.
 *
 * \param context The context passed into ASurfaceControl_registerSurfaceStatsListener
 *
 * \param func The callback passed into ASurfaceControl_registerSurfaceStatsListener
 */
void ASurfaceControl_unregisterSurfaceStatsListener(void* context,
                                       ASurfaceControl_SurfaceStatsListener func);

/**
 * Returns the timestamp of when the buffer was acquired for a specific frame with frame number
 * obtained from ASurfaceControlStats_getFrameNumber.
 */
int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats);

/**
 * Returns the frame number of the surface stats object passed into the callback.
 */
uint64_t ASurfaceControlStats_getFrameNumber(ASurfaceControlStats* stats);

__END_DECLS

#endif //ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H
+30 −2
Original line number Original line Diff line number Diff line
@@ -194,6 +194,25 @@ void TransactionCompletedListener::removeJankListener(const sp<JankDataListener>
    }
    }
}
}


void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie,
        sp<SurfaceControl> surfaceControl, SurfaceStatsCallback listener) {
    std::lock_guard<std::mutex> lock(mMutex);
    mSurfaceStatsListeners.insert({surfaceControl->getHandle(),
            SurfaceStatsCallbackEntry(context, cookie, listener)});
}

void TransactionCompletedListener::removeSurfaceStatsListener(void* context, void* cookie) {
    std::lock_guard<std::mutex> lock(mMutex);
    for (auto it = mSurfaceStatsListeners.begin(); it != mSurfaceStatsListeners.end();) {
        auto [itContext, itCookie, itListener] = it->second;
        if (itContext == context && itCookie == cookie) {
            it = mSurfaceStatsListeners.erase(it);
        } else {
            it++;
        }
    }
}

void TransactionCompletedListener::addSurfaceControlToCallbacks(
void TransactionCompletedListener::addSurfaceControlToCallbacks(
        const sp<SurfaceControl>& surfaceControl,
        const sp<SurfaceControl>& surfaceControl,
        const std::unordered_set<CallbackId>& callbackIds) {
        const std::unordered_set<CallbackId>& callbackIds) {
@@ -210,6 +229,7 @@ void TransactionCompletedListener::addSurfaceControlToCallbacks(
void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
    std::unordered_map<CallbackId, CallbackTranslation> callbacksMap;
    std::unordered_map<CallbackId, CallbackTranslation> callbacksMap;
    std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap;
    std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap;
    std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry> surfaceListeners;
    {
    {
        std::lock_guard<std::mutex> lock(mMutex);
        std::lock_guard<std::mutex> lock(mMutex);


@@ -226,6 +246,7 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener
         */
         */
        callbacksMap = mCallbacks;
        callbacksMap = mCallbacks;
        jankListenersMap = mJankListeners;
        jankListenersMap = mJankListeners;
        surfaceListeners = mSurfaceStatsListeners;
        for (const auto& transactionStats : listenerStats.transactionStats) {
        for (const auto& transactionStats : listenerStats.transactionStats) {
            for (auto& callbackId : transactionStats.callbackIds) {
            for (auto& callbackId : transactionStats.callbackIds) {
                mCallbacks.erase(callbackId);
                mCallbacks.erase(callbackId);
@@ -259,9 +280,16 @@ void TransactionCompletedListener::onTransactionCompleted(ListenerStats listener
                             surfaceControlStats);
                             surfaceControlStats);
        }
        }
        for (const auto& surfaceStats : transactionStats.surfaceStats) {
        for (const auto& surfaceStats : transactionStats.surfaceStats) {
            auto listenerRange = surfaceListeners.equal_range(surfaceStats.surfaceControl);
            for (auto it = listenerRange.first; it != listenerRange.second; it++) {
                auto entry = it->second;
                entry.callback(entry.context, transactionStats.latchTime,
                    transactionStats.presentFence, surfaceStats);
            }

            if (surfaceStats.jankData.empty()) continue;
            if (surfaceStats.jankData.empty()) continue;
            for (auto it = jankListenersMap.find(surfaceStats.surfaceControl);
            auto jankRange = jankListenersMap.equal_range(surfaceStats.surfaceControl);
                    it != jankListenersMap.end(); it++) {
            for (auto it = jankRange.first; it != jankRange.second; it++) {
                it->second->onJankDataAvailable(surfaceStats.jankData);
                it->second->onJankDataAvailable(surfaceStats.jankData);
            }
            }
        }
        }
+21 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,10 @@ using TransactionCompletedCallbackTakesContext =
using TransactionCompletedCallback =
using TransactionCompletedCallback =
        std::function<void(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
        std::function<void(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
                           const std::vector<SurfaceControlStats>& /*stats*/)>;
                           const std::vector<SurfaceControlStats>& /*stats*/)>;
using SurfaceStatsCallback =
        std::function<void(void* /*context*/, nsecs_t /*latchTime*/,
                           const sp<Fence>& /*presentFence*/,
                           const SurfaceStats& /*stats*/)>;


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------


@@ -650,8 +654,21 @@ class TransactionCompletedListener : public BnTransactionCompletedListener {
                surfaceControls;
                surfaceControls;
    };
    };


    struct SurfaceStatsCallbackEntry {
        SurfaceStatsCallbackEntry(void* context, void* cookie, SurfaceStatsCallback callback)
                : context(context),
                cookie(cookie),
                callback(callback) {}

        void* context;
        void* cookie;
        SurfaceStatsCallback callback;
    };

    std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex);
    std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex);
    std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex);
    std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex);
    std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry>
                mSurfaceStatsListeners GUARDED_BY(mMutex);


public:
public:
    static sp<TransactionCompletedListener> getInstance();
    static sp<TransactionCompletedListener> getInstance();
@@ -679,6 +696,10 @@ public:
     */
     */
    void removeJankListener(const sp<JankDataListener>& listener);
    void removeJankListener(const sp<JankDataListener>& listener);


    void addSurfaceStatsListener(void* context, void* cookie, sp<SurfaceControl> surfaceControl,
                SurfaceStatsCallback listener);
    void removeSurfaceStatsListener(void* context, void* cookie);

    // Overrides BnTransactionCompletedListener's onTransactionCompleted
    // Overrides BnTransactionCompletedListener's onTransactionCompleted
    void onTransactionCompleted(ListenerStats stats) override;
    void onTransactionCompleted(ListenerStats stats) override;
};
};