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

Commit 5e243ddd authored by Jim Shargo's avatar Jim Shargo Committed by Android (Google) Code Review
Browse files

Merge "Surface: Add a death notification to SurfaceListener" into main

parents 4efab5d7 a3da3020
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -77,9 +77,28 @@ bool isInterceptorRegistrationOp(int op) {

} // namespace

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
Surface::ProducerDeathListenerProxy::ProducerDeathListenerProxy(wp<SurfaceListener> surfaceListener)
      : mSurfaceListener(surfaceListener) {}

void Surface::ProducerDeathListenerProxy::binderDied(const wp<IBinder>&) {
    sp<SurfaceListener> surfaceListener = mSurfaceListener.promote();
    if (!surfaceListener) {
        return;
    }

    if (surfaceListener->needsDeathNotify()) {
        surfaceListener->onRemoteDied();
    }
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)

Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
                 const sp<IBinder>& surfaceControlHandle)
      : mGraphicBufferProducer(bufferProducer),
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
        mSurfaceDeathListener(nullptr),
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
        mCrop(Rect::EMPTY_RECT),
        mBufferAge(0),
        mGenerationNumber(0),
@@ -134,6 +153,12 @@ Surface::~Surface() {
    if (mConnectedToCpu) {
        Surface::disconnect(NATIVE_WINDOW_API_CPU);
    }
#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
    if (mSurfaceDeathListener != nullptr) {
        IInterface::asBinder(mGraphicBufferProducer)->unlinkToDeath(mSurfaceDeathListener);
        mSurfaceDeathListener = nullptr;
    }
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
}

sp<ISurfaceComposer> Surface::composerService() const {
@@ -2033,6 +2058,7 @@ int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBu
    Mutex::Autolock lock(mMutex);
    IGraphicBufferProducer::QueueBufferOutput output;
    mReportRemovedBuffers = reportBufferRemoval;

    if (listener != nullptr) {
        mListenerProxy = new ProducerListenerProxy(this, listener);
    }
@@ -2053,6 +2079,13 @@ int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBu
        }

        mConsumerRunningBehind = (output.numPendingBuffers >= 2);

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
        if (listener && listener->needsDeathNotify()) {
            mSurfaceDeathListener = sp<ProducerDeathListenerProxy>::make(listener);
            IInterface::asBinder(mGraphicBufferProducer)->linkToDeath(mSurfaceDeathListener);
        }
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
    }
    if (!err && api == NATIVE_WINDOW_API_CPU) {
        mConnectedToCpu = true;
@@ -2093,6 +2126,14 @@ int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
            mConnectedToCpu = false;
        }
    }

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
    if (mSurfaceDeathListener != nullptr) {
        IInterface::asBinder(mGraphicBufferProducer)->unlinkToDeath(mSurfaceDeathListener);
        mSurfaceDeathListener = nullptr;
    }
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)

    return err;
}

+32 −0
Original line number Diff line number Diff line
@@ -66,6 +66,16 @@ public:
    virtual void onBufferAttached() {}
    virtual bool needsAttachNotify() { return false; }
#endif

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
    // Called if this Surface is connected to a remote implementation and it
    // dies or becomes unavailable.
    virtual void onRemoteDied() {}

    // Clients will overwrite this if they want to receive a notification
    // via onRemoteDied. This should return a constant value.
    virtual bool needsDeathNotify() { return false; }
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
};

class StubSurfaceListener : public SurfaceListener {
@@ -471,6 +481,21 @@ protected:
        sp<SurfaceListener> mSurfaceListener;
    };

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
    class ProducerDeathListenerProxy : public IBinder::DeathRecipient {
    public:
        ProducerDeathListenerProxy(wp<SurfaceListener> surfaceListener);
        ProducerDeathListenerProxy(ProducerDeathListenerProxy&) = delete;

        // IBinder::DeathRecipient
        virtual void binderDied(const wp<IBinder>&) override;

    private:
        wp<SurfaceListener> mSurfaceListener;
    };
    friend class ProducerDeathListenerProxy;
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)

    void querySupportedTimestampsLocked() const;

    void freeAllBuffers();
@@ -502,6 +527,13 @@ protected:
    // TODO: rename to mBufferProducer
    sp<IGraphicBufferProducer> mGraphicBufferProducer;

#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
    // mSurfaceDeathListener gets registered as mGraphicBufferProducer's
    // DeathRecipient when SurfaceListener::needsDeathNotify returns true and
    // gets notified when it dies.
    sp<ProducerDeathListenerProxy> mSurfaceDeathListener;
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)

    // mSlots stores the buffers that have been allocated for each buffer slot.
    // It is initialized to null pointers, and gets filled in with the result of
    // IGraphicBufferProducer::requestBuffer when the client dequeues a buffer from a
+48 −0
Original line number Diff line number Diff line
@@ -50,7 +50,10 @@
#include <utils/Errors.h>
#include <utils/String8.h>

#include <chrono>
#include <cstddef>
#include <cstdint>
#include <future>
#include <limits>
#include <thread>

@@ -108,6 +111,18 @@ private:
    std::vector<sp<GraphicBuffer>> mDiscardedBuffers;
};

class DeathWatcherListener : public StubSurfaceListener {
public:
    virtual void onRemoteDied() { mDiedPromise.set_value(true); }

    virtual bool needsDeathNotify() { return true; }

    std::future<bool> getDiedFuture() { return mDiedPromise.get_future(); }

private:
    std::promise<bool> mDiedPromise;
};

class SurfaceTest : public ::testing::Test {
protected:
    SurfaceTest() {
@@ -2374,6 +2389,39 @@ TEST_F(SurfaceTest, ViewSurface_toString) {
    surface.name = String16("name");
    EXPECT_EQ("name", surface.toString());
}

TEST_F(SurfaceTest, TestRemoteSurfaceDied_CallbackCalled) {
    sp<TestServerClient> testServer = TestServerClient::Create();
    sp<IGraphicBufferProducer> producer = testServer->CreateProducer();
    EXPECT_NE(nullptr, producer);

    sp<Surface> surface = sp<Surface>::make(producer);
    sp<DeathWatcherListener> deathWatcher = sp<DeathWatcherListener>::make();
    EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, deathWatcher));

    auto diedFuture = deathWatcher->getDiedFuture();
    EXPECT_EQ(OK, testServer->Kill());

    diedFuture.wait();
    EXPECT_TRUE(diedFuture.get());
}

TEST_F(SurfaceTest, TestRemoteSurfaceDied_Disconnect_CallbackNotCalled) {
    sp<TestServerClient> testServer = TestServerClient::Create();
    sp<IGraphicBufferProducer> producer = testServer->CreateProducer();
    EXPECT_NE(nullptr, producer);

    sp<Surface> surface = sp<Surface>::make(producer);
    sp<DeathWatcherListener> deathWatcher = sp<DeathWatcherListener>::make();
    EXPECT_EQ(OK, surface->connect(NATIVE_WINDOW_API_CPU, deathWatcher));
    EXPECT_EQ(OK, surface->disconnect(NATIVE_WINDOW_API_CPU));

    auto watcherDiedFuture = deathWatcher->getDiedFuture();
    EXPECT_EQ(OK, testServer->Kill());

    std::future_status status = watcherDiedFuture.wait_for(std::chrono::seconds(1));
    EXPECT_EQ(std::future_status::timeout, status);
}
#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)

} // namespace android