diff options
| author | 2024-08-23 16:02:46 +0000 | |
|---|---|---|
| committer | 2024-08-23 16:02:46 +0000 | |
| commit | 5e243dddc489d56e89a6383b66a74c127b934a13 (patch) | |
| tree | bef2ffb6a6545b05df3c89e3113a93eace31dcc3 | |
| parent | 4efab5d7614f1b809ea89c6226d0a0555f79b255 (diff) | |
| parent | a3da302041614624faefd7a4ec8d156dae418043 (diff) | |
Merge "Surface: Add a death notification to SurfaceListener" into main
| -rw-r--r-- | libs/gui/Surface.cpp | 41 | ||||
| -rw-r--r-- | libs/gui/include/gui/Surface.h | 32 | ||||
| -rw-r--r-- | libs/gui/tests/Surface_test.cpp | 48 |
3 files changed, 121 insertions, 0 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index da3886ccf0..76d74fef88 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -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; } diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 0f51f2dc13..5ea81c4c25 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -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 diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index ab09dfc58d..0c3859ebe0 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -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 |