Loading libs/gui/Surface.cpp +41 −0 Original line number Diff line number Diff line Loading @@ -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), Loading Loading @@ -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 { Loading Loading @@ -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); } Loading @@ -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; Loading Loading @@ -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; } Loading libs/gui/include/gui/Surface.h +32 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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(); Loading Loading @@ -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 Loading libs/gui/tests/Surface_test.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -50,7 +50,10 @@ #include <utils/Errors.h> #include <utils/String8.h> #include <chrono> #include <cstddef> #include <cstdint> #include <future> #include <limits> #include <thread> Loading Loading @@ -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() { Loading Loading @@ -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 Loading
libs/gui/Surface.cpp +41 −0 Original line number Diff line number Diff line Loading @@ -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), Loading Loading @@ -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 { Loading Loading @@ -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); } Loading @@ -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; Loading Loading @@ -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; } Loading
libs/gui/include/gui/Surface.h +32 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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(); Loading Loading @@ -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 Loading
libs/gui/tests/Surface_test.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -50,7 +50,10 @@ #include <utils/Errors.h> #include <utils/String8.h> #include <chrono> #include <cstddef> #include <cstdint> #include <future> #include <limits> #include <thread> Loading Loading @@ -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() { Loading Loading @@ -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