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

Commit 076acace authored by Chavi Weingarten's avatar Chavi Weingarten
Browse files

SurfaceFlinger: Add TrustedPresentationListener API

TrustedPresentationListener is intended to allow the producer
of a buffer layer to gain a trusted signal on whether and to
what extent a layer is presented. A strawman design would be to
provide the producer details on it's presentation (alpha,
position, scale, final crop, covered region, etc). In the strawman
design the client end would then decide itself whether each of these
parameters were in an acceptable range.

However providing the client feedback on it's per frame position would have
a negative system health impact. Furthermore in some of the target use cases
we can't even be sure the layer of interest is actively producing buffers
and so there may be no existing callback to piggy-back on.

Because of this we use a server side thresholding approach, where the client
expresses some visibility threshold and a time stability constraint. See
SurfaceComposerClient.h comment for details on these thresholds and their
computation.

Bug: 256993331
Test: LayerTrustedPresentationListener_test.cpp
Change-Id: If4bef60dc6b22ce4959c353fa2a19b0994a00f5c
parent 39bf1d61
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ enum class Tag : uint32_t {
    ON_TRANSACTION_COMPLETED = IBinder::FIRST_CALL_TRANSACTION,
    ON_RELEASE_BUFFER,
    ON_TRANSACTION_QUEUE_STALLED,
    LAST = ON_TRANSACTION_QUEUE_STALLED,
    ON_TRUSTED_PRESENTATION_CHANGED,
    LAST = ON_TRUSTED_PRESENTATION_CHANGED,
};

} // Anonymous namespace
@@ -302,6 +303,11 @@ public:
                                 onTransactionQueueStalled)>(Tag::ON_TRANSACTION_QUEUE_STALLED,
                                                             reason);
    }

    void onTrustedPresentationChanged(int id, bool inTrustedPresentationState) override {
        callRemoteAsync<decltype(&ITransactionCompletedListener::onTrustedPresentationChanged)>(
                Tag::ON_TRUSTED_PRESENTATION_CHANGED, id, inTrustedPresentationState);
    }
};

// Out-of-line virtual method definitions to trigger vtable emission in this translation unit (see
@@ -325,6 +331,9 @@ status_t BnTransactionCompletedListener::onTransact(uint32_t code, const Parcel&
        case Tag::ON_TRANSACTION_QUEUE_STALLED:
            return callLocalAsync(data, reply,
                                  &ITransactionCompletedListener::onTransactionQueueStalled);
        case Tag::ON_TRUSTED_PRESENTATION_CHANGED:
            return callLocalAsync(data, reply,
                                  &ITransactionCompletedListener::onTrustedPresentationChanged);
    }
}

+27 −0
Original line number Diff line number Diff line
@@ -185,6 +185,8 @@ status_t layer_state_t::write(Parcel& output) const
    if (hasBufferData) {
        SAFE_PARCEL(output.writeParcelable, *bufferData);
    }
    SAFE_PARCEL(output.writeParcelable, trustedPresentationThresholds);
    SAFE_PARCEL(output.writeParcelable, trustedPresentationListener);
    return NO_ERROR;
}

@@ -315,6 +317,10 @@ status_t layer_state_t::read(const Parcel& input)
    } else {
        bufferData = nullptr;
    }

    SAFE_PARCEL(input.readParcelable, &trustedPresentationThresholds);
    SAFE_PARCEL(input.readParcelable, &trustedPresentationListener);

    return NO_ERROR;
}

@@ -553,6 +559,11 @@ void layer_state_t::merge(const layer_state_t& other) {
        what |= eBufferChanged;
        bufferData = other.bufferData;
    }
    if (other.what & eTrustedPresentationInfoChanged) {
        what |= eTrustedPresentationInfoChanged;
        trustedPresentationListener = other.trustedPresentationListener;
        trustedPresentationThresholds = other.trustedPresentationThresholds;
    }
    if (other.what & eDataspaceChanged) {
        what |= eDataspaceChanged;
        dataspace = other.dataspace;
@@ -998,4 +1009,20 @@ status_t BufferData::readFromParcel(const Parcel* input) {
    return NO_ERROR;
}

status_t TrustedPresentationListener::writeToParcel(Parcel* parcel) const {
    SAFE_PARCEL(parcel->writeStrongBinder, callbackInterface);
    SAFE_PARCEL(parcel->writeInt32, callbackId);
    return NO_ERROR;
}

status_t TrustedPresentationListener::readFromParcel(const Parcel* parcel) {
    sp<IBinder> tmpBinder = nullptr;
    SAFE_PARCEL(parcel->readNullableStrongBinder, &tmpBinder);
    if (tmpBinder) {
        callbackInterface = checked_interface_cast<ITransactionCompletedListener>(tmpBinder);
    }
    SAFE_PARCEL(parcel->readInt32, &callbackId);
    return NO_ERROR;
}

}; // namespace android
+80 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <android/gui/DisplayState.h>
#include <android/gui/ISurfaceComposerClient.h>
#include <android/gui/IWindowInfosListener.h>
#include <android/gui/TrustedPresentationThresholds.h>
#include <android/os/IInputConstants.h>
#include <gui/TraceUtils.h>
#include <utils/Errors.h>
@@ -63,6 +64,7 @@ namespace android {
using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
using gui::FocusRequest;
using gui::IRegionSamplingListener;
using gui::TrustedPresentationThresholds;
using gui::WindowInfo;
using gui::WindowInfoHandle;
using gui::WindowInfosListener;
@@ -518,6 +520,45 @@ void TransactionCompletedListener::removeReleaseBufferCallback(
    }
}

SurfaceComposerClient::PresentationCallbackRAII::PresentationCallbackRAII(
        TransactionCompletedListener* tcl, int id) {
    mTcl = tcl;
    mId = id;
}

SurfaceComposerClient::PresentationCallbackRAII::~PresentationCallbackRAII() {
    mTcl->clearTrustedPresentationCallback(mId);
}

sp<SurfaceComposerClient::PresentationCallbackRAII>
TransactionCompletedListener::addTrustedPresentationCallback(TrustedPresentationCallback tpc,
                                                             int id, void* context) {
    std::scoped_lock<std::mutex> lock(mMutex);
    mTrustedPresentationCallbacks[id] =
            std::tuple<TrustedPresentationCallback, void*>(tpc, context);
    return new SurfaceComposerClient::PresentationCallbackRAII(this, id);
}

void TransactionCompletedListener::clearTrustedPresentationCallback(int id) {
    std::scoped_lock<std::mutex> lock(mMutex);
    mTrustedPresentationCallbacks.erase(id);
}

void TransactionCompletedListener::onTrustedPresentationChanged(int id,
                                                                bool presentedWithinThresholds) {
    TrustedPresentationCallback tpc;
    void* context;
    {
        std::scoped_lock<std::mutex> lock(mMutex);
        auto it = mTrustedPresentationCallbacks.find(id);
        if (it == mTrustedPresentationCallbacks.end()) {
            return;
        }
        std::tie(tpc, context) = it->second;
    }
    tpc(context, presentedWithinThresholds);
}

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

void removeDeadBufferCallback(void* /*context*/, uint64_t graphicBufferId);
@@ -2098,6 +2139,45 @@ void SurfaceComposerClient::Transaction::clearFrameTimelineInfo(FrameTimelineInf
    t.startTimeNanos = 0;
}

SurfaceComposerClient::Transaction&
SurfaceComposerClient::Transaction::setTrustedPresentationCallback(
        const sp<SurfaceControl>& sc, TrustedPresentationCallback cb,
        const TrustedPresentationThresholds& thresholds, void* context,
        sp<SurfaceComposerClient::PresentationCallbackRAII>& outCallbackRef) {
    auto listener = TransactionCompletedListener::getInstance();
    outCallbackRef = listener->addTrustedPresentationCallback(cb, sc->getLayerId(), context);

    layer_state_t* s = getLayerState(sc);
    if (!s) {
        mStatus = BAD_INDEX;
        return *this;
    }
    s->what |= layer_state_t::eTrustedPresentationInfoChanged;
    s->trustedPresentationThresholds = thresholds;
    s->trustedPresentationListener.callbackInterface = TransactionCompletedListener::getIInstance();
    s->trustedPresentationListener.callbackId = sc->getLayerId();

    return *this;
}

SurfaceComposerClient::Transaction&
SurfaceComposerClient::Transaction::clearTrustedPresentationCallback(const sp<SurfaceControl>& sc) {
    auto listener = TransactionCompletedListener::getInstance();
    listener->clearTrustedPresentationCallback(sc->getLayerId());

    layer_state_t* s = getLayerState(sc);
    if (!s) {
        mStatus = BAD_INDEX;
        return *this;
    }
    s->what |= layer_state_t::eTrustedPresentationInfoChanged;
    s->trustedPresentationThresholds = TrustedPresentationThresholds();
    s->trustedPresentationListener.callbackInterface = nullptr;
    s->trustedPresentationListener.callbackId = -1;

    return *this;
}

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

SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT) {}
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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.
 */

package android.gui;

parcelable TrustedPresentationThresholds {
    float minAlpha = -1.0f;
    float minFractionRendered = -1.0f;

    int stabilityRequirementMs = 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -196,6 +196,8 @@ public:
                                 uint32_t currentMaxAcquiredBufferCount) = 0;

    virtual void onTransactionQueueStalled(const String8& name) = 0;

    virtual void onTrustedPresentationChanged(int id, bool inTrustedPresentationState) = 0;
};

class BnTransactionCompletedListener : public SafeBnInterface<ITransactionCompletedListener> {
Loading