From cfb187b458858013453019f62c8cbf29a0a8d623 Mon Sep 17 00:00:00 2001 From: rongliu Date: Wed, 14 Mar 2018 12:26:23 -0700 Subject: Manual merge of ag/3738015 because of conflicts. Conflicts are in layers.proto, LayerProtoParser.h and LayerProtoPraser.cpp as master has more fields in layer proto than pi-dev. Original cl: Pass correct window type and app id to hw composer. 1. Set -1 as default value for window type and app id. 2. When send layer information to hal, layers inherit type and app id from parent node when parent node has valid type/appId. 3. Add window type and app id to SurfaceFlinger dumpsys. Bug: 74622357 Test: Manual test. Several things verified: 1. Android settings layer, status bar layer, nav bar layer have valid window type and appId when start android settings. 2. Layers without buffer have window type -1 and app id -1. 3. When send layers to hal, Chrome SurfaceView layer inherit type and app id from its parent (MainActivity layer). Change-Id: I8d6ad274ca18b61d1bbf6b28f7def5160b55b1e7 --- libs/gui/ISurfaceComposerClient.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'libs/gui/ISurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 679f44b57b..a6890eeb19 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -47,8 +47,8 @@ public: ~BpSurfaceComposerClient() override; status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, - uint32_t flags, const sp& parent, uint32_t windowType, - uint32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, -- cgit v1.2.3-59-g8ed1b From 6fb1a7e9627df030667304d88a3292f91e790ea9 Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Tue, 11 Dec 2018 12:07:25 -0800 Subject: SurfaceFlinger: Remove removeLayer We remove explicit layer destruction and replace it with reparent->null, completing the transition to a reference counted model. Test: Manual Bug: 62536731 Bug: 111373437 Bug: 111297488 Change-Id: I8ac7c5c5125e1c8daf84b42db00e1dd93a544bb5 --- cmds/surfacereplayer/replayer/Replayer.cpp | 41 ------------ cmds/surfacereplayer/replayer/Replayer.h | 3 - libs/gui/ISurfaceComposerClient.cpp | 8 --- libs/gui/SurfaceComposerClient.cpp | 34 +++++----- libs/gui/SurfaceControl.cpp | 10 ++- libs/gui/include/gui/ISurfaceComposerClient.h | 5 -- libs/gui/include/gui/SurfaceComposerClient.h | 11 ++-- services/surfaceflinger/Client.cpp | 24 ------- services/surfaceflinger/Client.h | 5 +- services/surfaceflinger/Layer.cpp | 49 +++++++++----- services/surfaceflinger/SurfaceFlinger.cpp | 77 ++++------------------ services/surfaceflinger/SurfaceFlinger.h | 12 +--- services/surfaceflinger/tests/Stress_test.cpp | 2 +- .../tests/SurfaceInterceptor_test.cpp | 12 ---- services/surfaceflinger/tests/Transaction_test.cpp | 8 +-- 15 files changed, 82 insertions(+), 219 deletions(-) (limited to 'libs/gui/ISurfaceComposerClient.cpp') diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp index 384f21ff17..34886a99e9 100644 --- a/cmds/surfacereplayer/replayer/Replayer.cpp +++ b/cmds/surfacereplayer/replayer/Replayer.cpp @@ -286,10 +286,6 @@ status_t Replayer::dispatchEvent(int index) { std::thread(&Replayer::createSurfaceControl, this, increment.surface_creation(), event) .detach(); } break; - case increment.kSurfaceDeletion: { - std::thread(&Replayer::deleteSurfaceControl, this, increment.surface_deletion(), event) - .detach(); - } break; case increment.kBufferUpdate: { std::lock_guard lock1(mLayerLock); std::lock_guard lock2(mBufferQueueSchedulerLock); @@ -628,47 +624,10 @@ status_t Replayer::createSurfaceControl( return NO_ERROR; } -status_t Replayer::deleteSurfaceControl( - const SurfaceDeletion& delete_, const std::shared_ptr& event) { - ALOGV("Deleting %d Surface Control", delete_.id()); - event->readyToExecute(); - - std::lock_guard lock1(mPendingLayersLock); - - mLayersPendingRemoval.push_back(delete_.id()); - - const auto& iterator = mBufferQueueSchedulers.find(delete_.id()); - if (iterator != mBufferQueueSchedulers.end()) { - (*iterator).second->stopScheduling(); - } - - std::lock_guard lock2(mLayerLock); - if (mLayers[delete_.id()] != nullptr) { - mComposerClient->destroySurface(mLayers[delete_.id()]->getHandle()); - } - - return NO_ERROR; -} - -void Replayer::doDeleteSurfaceControls() { - std::lock_guard lock1(mPendingLayersLock); - std::lock_guard lock2(mLayerLock); - if (!mLayersPendingRemoval.empty()) { - for (int id : mLayersPendingRemoval) { - mLayers.erase(id); - mColors.erase(id); - mBufferQueueSchedulers.erase(id); - } - mLayersPendingRemoval.clear(); - } -} - status_t Replayer::injectVSyncEvent( const VSyncEvent& vSyncEvent, const std::shared_ptr& event) { ALOGV("Injecting VSync Event"); - doDeleteSurfaceControls(); - event->readyToExecute(); SurfaceComposerClient::injectVSync(vSyncEvent.when()); diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h index 120dd9babd..ad807ee950 100644 --- a/cmds/surfacereplayer/replayer/Replayer.h +++ b/cmds/surfacereplayer/replayer/Replayer.h @@ -70,8 +70,6 @@ class Replayer { status_t doTransaction(const Transaction& transaction, const std::shared_ptr& event); status_t createSurfaceControl(const SurfaceCreation& create, const std::shared_ptr& event); - status_t deleteSurfaceControl(const SurfaceDeletion& delete_, - const std::shared_ptr& event); status_t injectVSyncEvent(const VSyncEvent& vsyncEvent, const std::shared_ptr& event); void createDisplay(const DisplayCreation& create, const std::shared_ptr& event); void deleteDisplay(const DisplayDeletion& delete_, const std::shared_ptr& event); @@ -120,7 +118,6 @@ class Replayer { void setDisplayProjection(SurfaceComposerClient::Transaction& t, display_id id, const ProjectionChange& pc); - void doDeleteSurfaceControls(); void waitUntilTimestamp(int64_t timestamp); void waitUntilDeferredTransactionLayerExists( const DeferredTransactionChange& dtc, std::unique_lock& lock); diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index a6890eeb19..369f523ea4 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -31,7 +31,6 @@ namespace { // Anonymous enum class Tag : uint32_t { CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, - DESTROY_SURFACE, CLEAR_LAYER_FRAME_STATS, GET_LAYER_FRAME_STATS, LAST = GET_LAYER_FRAME_STATS, @@ -57,11 +56,6 @@ public: handle, gbp); } - status_t destroySurface(const sp& handle) override { - return callRemote(Tag::DESTROY_SURFACE, - handle); - } - status_t clearLayerFrameStats(const sp& handle) const override { return callRemote(Tag::CLEAR_LAYER_FRAME_STATS, @@ -92,8 +86,6 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, switch (tag) { case Tag::CREATE_SURFACE: return callLocal(data, reply, &ISurfaceComposerClient::createSurface); - case Tag::DESTROY_SURFACE: - return callLocal(data, reply, &ISurfaceComposerClient::destroySurface); case Tag::CLEAR_LAYER_FRAME_STATS: return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats); case Tag::GET_LAYER_FRAME_STATS: diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 824e43fb07..6c39d6f1b8 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -205,6 +205,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::merge(Tr return *this; } +void SurfaceComposerClient::doDropReferenceTransaction(const sp& handle, + const sp& client) { + sp sf(ComposerService::getComposerService()); + Vector composerStates; + Vector displayStates; + + ComposerState s; + s.client = client; + s.state.surface = handle; + s.state.what |= layer_state_t::eReparent; + s.state.parentHandleForChild = nullptr; + + composerStates.add(s); + sf->setTransactionState(composerStates, displayStates, 0, nullptr, {}); +} + status_t SurfaceComposerClient::Transaction::apply(bool synchronous) { if (mStatus != NO_ERROR) { return mStatus; @@ -819,17 +835,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::transfer #endif -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::destroySurface( - const sp& sc) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eDestroySurface; - return *this; -} - SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform( const sp& sc, const mat3& matrix, const vec3& translation) { layer_state_t* s = getLayerState(sc); @@ -1004,13 +1009,6 @@ status_t SurfaceComposerClient::createSurfaceChecked( return err; } -status_t SurfaceComposerClient::destroySurface(const sp& sid) { - if (mStatus != NO_ERROR) - return mStatus; - status_t err = mClient->destroySurface(sid); - return err; -} - status_t SurfaceComposerClient::clearLayerFrameStats(const sp& token) const { if (mStatus != NO_ERROR) { return mStatus; diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index b6ef286fd4..8e500a4f9b 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -63,7 +63,13 @@ SurfaceControl::SurfaceControl(const sp& other) { SurfaceControl::~SurfaceControl() { - destroy(); + if (mClient != nullptr && mHandle != nullptr && mOwned) { + SurfaceComposerClient::doDropReferenceTransaction(mHandle, mClient->getClient()); + } + mClient.clear(); + mHandle.clear(); + mGraphicBufferProducer.clear(); + IPCThreadState::self()->flushCommands(); } void SurfaceControl::destroy() @@ -71,7 +77,7 @@ void SurfaceControl::destroy() // Avoid destroying the server-side surface if we are not the owner of it, meaning that we // retrieved it from another process. if (isValid() && mOwned) { - mClient->destroySurface(mHandle); + SurfaceComposerClient::Transaction().reparent(this, nullptr).apply(); } // clear all references and trigger an IPC now, to make sure things // happen without delay, since these resources are quite heavy. diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 82b01b8cf0..56ca197ff9 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -55,11 +55,6 @@ public: int32_t ownerUid, sp* handle, sp* gbp) = 0; - /* - * Requires ACCESS_SURFACE_FLINGER permission - */ - virtual status_t destroySurface(const sp& handle) = 0; - /* * Requires ACCESS_SURFACE_FLINGER permission */ diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 4a8e01bec1..e0cbb705c7 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -145,6 +145,13 @@ public: ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat); + /** + * Called from SurfaceControl d'tor to 'destroy' the surface (or rather, reparent it + * to null), but without needing an sp to avoid infinite ressurection. + */ + static void doDropReferenceTransaction(const sp& handle, + const sp& client); + // ------------------------------------------------------------------------ // surface creation / destruction @@ -338,8 +345,6 @@ public: Transaction& transferTouchFocus(const sp& fromToken, const sp& toToken); #endif - Transaction& destroySurface(const sp& sc); - // Set a color transform matrix on the given layer on the built-in display. Transaction& setColorTransform(const sp& sc, const mat3& matrix, const vec3& translation); @@ -368,8 +373,6 @@ public: void setEarlyWakeup(); }; - status_t destroySurface(const sp& id); - status_t clearLayerFrameStats(const sp& token) const; status_t getLayerFrameStats(const sp& token, FrameStats* outStats) const; static status_t clearAnimationFrameStats(); diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index ee4ec506f7..4f6fb1cca6 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -39,26 +39,6 @@ Client::Client(const sp& flinger) { } -Client::~Client() -{ - // We need to post a message to remove our remaining layers rather than - // do so directly by acquiring the SurfaceFlinger lock. If we were to - // attempt to directly call the lock it becomes effectively impossible - // to use sp while holding the SF lock as descoping it could - // then trigger a dead-lock. - - const size_t count = mLayers.size(); - for (size_t i=0 ; i l = mLayers.valueAt(i).promote(); - if (l == nullptr) { - continue; - } - mFlinger->postMessageAsync(new LambdaMessage([flinger = mFlinger, l]() { - flinger->removeLayer(l); - })); - } -} - status_t Client::initCheck() const { return NO_ERROR; } @@ -115,10 +95,6 @@ status_t Client::createSurface( ownerUid, handle, gbp, &parent); } -status_t Client::destroySurface(const sp& handle) { - return mFlinger->onLayerRemoved(this, handle); -} - status_t Client::clearLayerFrameStats(const sp& handle) const { sp layer = getLayerUser(handle); if (layer == nullptr) { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 4a74739a10..d0051dee1a 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -39,13 +39,12 @@ class Client : public BnSurfaceComposerClient { public: explicit Client(const sp& flinger); - ~Client(); + ~Client() = default; status_t initCheck() const; // protected by SurfaceFlinger::mStateLock void attachLayer(const sp& handle, const sp& layer); - void detachLayer(const Layer* layer); sp getLayerUser(const sp& handle) const; @@ -59,8 +58,6 @@ private: sp* handle, sp* gbp); - virtual status_t destroySurface(const sp& handle); - virtual status_t clearLayerFrameStats(const sp& handle) const; virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index b1827c191c..3f2d10a45b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -179,6 +179,8 @@ void Layer::onRemovedFromCurrentState() { for (const auto& child : mCurrentChildren) { child->onRemovedFromCurrentState(); } + + mFlinger->markLayerPendingRemovalLocked(this); } void Layer::addToCurrentState() { @@ -1571,6 +1573,7 @@ void Layer::addChild(const sp& layer) { ssize_t Layer::removeChild(const sp& layer) { layer->setParent(nullptr); + return mCurrentChildren.remove(layer); } @@ -1605,14 +1608,14 @@ void Layer::setChildrenDrawingParent(const sp& newParent) { } bool Layer::reparent(const sp& newParentHandle) { - if (newParentHandle == nullptr) { - return false; - } - - auto handle = static_cast(newParentHandle.get()); - sp newParent = handle->owner.promote(); - if (newParent == nullptr) { - ALOGE("Unable to promote Layer handle"); + bool callSetTransactionFlags = false; + + // While layers are detached, we allow most operations + // and simply halt performing the actual transaction. However + // for reparent != null we would enter the mRemovedFromCurrentState + // state, regardless of whether doTransaction was called, and + // so we need to prevent the update here. + if (mLayerDetached && newParentHandle == nullptr) { return false; } @@ -1620,17 +1623,31 @@ bool Layer::reparent(const sp& newParentHandle) { if (parent != nullptr) { parent->removeChild(this); } - newParent->addChild(this); - if (!newParent->isRemovedFromCurrentState()) { - addToCurrentState(); - } + if (newParentHandle != nullptr) { + auto handle = static_cast(newParentHandle.get()); + sp newParent = handle->owner.promote(); + if (newParent == nullptr) { + ALOGE("Unable to promote Layer handle"); + return false; + } - if (mLayerDetached) { - mLayerDetached = false; - setTransactionFlags(eTransactionNeeded); + newParent->addChild(this); + if (!newParent->isRemovedFromCurrentState()) { + addToCurrentState(); + } else { + onRemovedFromCurrentState(); + } + + if (mLayerDetached) { + mLayerDetached = false; + callSetTransactionFlags = true; + } + } else { + onRemovedFromCurrentState(); } - if (attachChildren()) { + + if (callSetTransactionFlags || attachChildren()) { setTransactionFlags(eTransactionNeeded); } return true; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fd25abf1a5..3648be49ec 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2799,10 +2799,8 @@ void SurfaceFlinger::commitTransaction() // showing at its last configured state until we eventually // abandon the buffer queue. if (l->isRemovedFromCurrentState()) { - l->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* child) { - child->destroyHwcLayersForAllDisplays(); - latchAndReleaseBuffer(child); - }); + l->destroyHwcLayersForAllDisplays(); + latchAndReleaseBuffer(l); } } mLayersPendingRemoval.clear(); @@ -3276,30 +3274,6 @@ status_t SurfaceFlinger::addClientLayer(const sp& client, return NO_ERROR; } -status_t SurfaceFlinger::removeLayer(const sp& layer) { - Mutex::Autolock _l(mStateLock); - return removeLayerLocked(mStateLock, layer); -} - -status_t SurfaceFlinger::removeLayerLocked(const Mutex& lock, const sp& layer) { - if (layer->isLayerDetached()) { - return NO_ERROR; - } - - const auto& p = layer->getParent(); - ssize_t index; - if (p != nullptr) { - index = p->removeChild(layer); - } else { - index = mCurrentState.layersSortedByZ.remove(layer); - } - - layer->onRemovedFromCurrentState(); - - markLayerPendingRemovalLocked(lock, layer); - return NO_ERROR; -} - uint32_t SurfaceFlinger::peekTransactionFlags() { return mTransactionFlags; } @@ -3434,14 +3408,6 @@ void SurfaceFlinger::applyTransactionState(const Vector& states, } transactionFlags |= clientStateFlags; - // Iterate through all layers again to determine if any need to be destroyed. Marking layers - // as destroyed should only occur after setting all other states. This is to allow for a - // child re-parent to happen before marking its original parent as destroyed (which would - // then mark the child as destroyed). - for (const ComposerState& state : states) { - setDestroyStateLocked(state); - } - transactionFlags |= addInputWindowCommands(inputWindowCommands); // If a synchronous transaction is explicitly requested without any changes, force a transaction @@ -3767,20 +3733,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState return flags; } -void SurfaceFlinger::setDestroyStateLocked(const ComposerState& composerState) { - const layer_state_t& state = composerState.state; - sp client(static_cast(composerState.client.get())); - - sp layer(client->getLayerUser(state.surface)); - if (layer == nullptr) { - return; - } - - if (state.what & layer_state_t::eDestroySurface) { - removeLayerLocked(mStateLock, layer); - } -} - uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) { uint32_t flags = 0; if (!inputWindowCommands.transferTouchFocusCommands.empty()) { @@ -3960,21 +3912,7 @@ status_t SurfaceFlinger::createContainerLayer(const sp& client, } -status_t SurfaceFlinger::onLayerRemoved(const sp& client, const sp& handle) -{ - // called by a client when it wants to remove a Layer - status_t err = NO_ERROR; - sp l(client->getLayerUser(handle)); - if (l != nullptr) { - mInterceptor->saveSurfaceDeletion(l); - err = removeLayer(l); - ALOGE_IF(err<0 && err != NAME_NOT_FOUND, - "error removing layer=%p (%s)", l.get(), strerror(-err)); - } - return err; -} - -void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp& layer) { +void SurfaceFlinger::markLayerPendingRemovalLocked(const sp& layer) { mLayersPendingRemoval.add(layer); mLayersRemoved = true; setTransactionFlags(eTransactionNeeded); @@ -3983,7 +3921,14 @@ void SurfaceFlinger::markLayerPendingRemovalLocked(const Mutex&, const sp void SurfaceFlinger::onHandleDestroyed(sp& layer) { Mutex::Autolock lock(mStateLock); - markLayerPendingRemovalLocked(mStateLock, layer); + // If a layer has a parent, we allow it to out-live it's handle + // with the idea that the parent holds a reference and will eventually + // be cleaned up. However no one cleans up the top-level so we do so + // here. + if (layer->getParent() == nullptr) { + mCurrentState.layersSortedByZ.remove(layer); + } + markLayerPendingRemovalLocked(layer); layer.clear(); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index bfc87a02eb..b8bfcf1f9e 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -569,7 +569,6 @@ private: bool composerStateContainsUnsignaledFences(const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState); uint32_t setDisplayStateLocked(const DisplayState& s); - void setDestroyStateLocked(const ComposerState& composerState); uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands); /* ------------------------------------------------------------------------ @@ -599,20 +598,11 @@ private: String8 getUniqueLayerName(const String8& name); - // called in response to the window-manager calling - // ISurfaceComposerClient::destroySurface() - status_t onLayerRemoved(const sp& client, const sp& handle); - - void markLayerPendingRemovalLocked(const Mutex& /* mStateLock */, const sp& layer); - // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all // resources associated to this layer. void onHandleDestroyed(sp& layer); - - // remove a layer from SurfaceFlinger immediately - status_t removeLayer(const sp& layer); - status_t removeLayerLocked(const Mutex&, const sp& layer); + void markLayerPendingRemovalLocked(const sp& layer); // add a layer to SurfaceFlinger status_t addClientLayer(const sp& client, diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index 3e1be8e288..89c26f4a98 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -34,7 +34,7 @@ TEST(SurfaceFlingerStress, create_and_destroy) { auto surf = client->createSurface(String8("t"), 100, 100, PIXEL_FORMAT_RGBA_8888, 0); ASSERT_TRUE(surf != nullptr); - client->destroySurface(surf->getHandle()); + surf->clear(); } }; diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index e506757867..8ec3e154e3 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -806,18 +806,6 @@ TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) { Increment::IncrementCase::kSurfaceCreation); } -TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) { - enableInterceptor(); - sp layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME), - SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0); - mComposerClient->destroySurface(layerToDelete->getHandle()); - disableInterceptor(); - - Trace capturedTrace; - ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace)); - ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceDeletion)); -} - TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) { captureTest(&SurfaceInterceptorTest::displayCreation, Increment::IncrementCase::kDisplayCreation); diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index d118ad6402..991ea36a3c 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -1023,7 +1023,7 @@ TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) { .setRelativeLayer(layerG, layerR->getHandle(), 1) .apply(); - mClient->destroySurface(layerG->getHandle()); + layerG->clear(); // layerG should have been removed screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED); } @@ -4030,9 +4030,9 @@ TEST_F(ChildLayerTest, ReparentToNoParent) { asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); }); { mCapture = screenshot(); - // Nothing should have changed. + // The surface should now be offscreen. mCapture->expectFGColor(64, 64); - mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(74, 74); mCapture->expectFGColor(84, 84); } } @@ -4610,7 +4610,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); auto redLayerHandle = redLayer->getHandle(); - mClient->destroySurface(redLayerHandle); + redLayer->clear(); SurfaceComposerClient::Transaction().apply(true); sp outBuffer; -- cgit v1.2.3-59-g8ed1b From 35187b32107eff2ded94adf29c19192524537ee1 Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Tue, 8 Jan 2019 10:08:52 -0800 Subject: blast: [FIXED] create SurfaceControl from Surface parent Create a child SurfaceControl from a parent Surface. This is done by sending the parent IGBP to SurfaceFlinger who gets the parent Layer information. This is change is necessary for public SurfaceControl because createScopedConnection is deprecated. [Previous version used Layer::mStateMutex which was removed hours before this patch went in. Presubmit did not catch the conflict so the patch was immediately reverted. This version does not have that conflict.] Test: atest CtsViewTestCases:android.view.cts.ASurfaceControlTest Bug: 80477568 Change-Id: Ibbfb2851ff71c21cce1761cab434b85735e35515 --- libs/gui/ISurfaceComposerClient.cpp | 15 +++++++++++++++ libs/gui/SurfaceComposerClient.cpp | 24 ++++++++++++++++++++++++ libs/gui/include/gui/ISurfaceComposerClient.h | 10 ++++++++++ libs/gui/include/gui/SurfaceComposerClient.h | 24 ++++++++++++++++++------ services/surfaceflinger/Client.cpp | 20 ++++++++++++++++++++ services/surfaceflinger/Client.h | 6 ++++++ 6 files changed, 93 insertions(+), 6 deletions(-) (limited to 'libs/gui/ISurfaceComposerClient.cpp') diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 369f523ea4..928ef95aa8 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -31,6 +31,7 @@ namespace { // Anonymous enum class Tag : uint32_t { CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION, + CREATE_WITH_SURFACE_PARENT, CLEAR_LAYER_FRAME_STATS, GET_LAYER_FRAME_STATS, LAST = GET_LAYER_FRAME_STATS, @@ -56,6 +57,18 @@ public: handle, gbp); } + status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height, + PixelFormat format, uint32_t flags, + const sp& parent, int32_t windowType, + int32_t ownerUid, sp* handle, + sp* gbp) override { + return callRemote(Tag::CREATE_WITH_SURFACE_PARENT, + name, width, height, format, + flags, parent, windowType, + ownerUid, handle, gbp); + } + status_t clearLayerFrameStats(const sp& handle) const override { return callRemote(Tag::CLEAR_LAYER_FRAME_STATS, @@ -86,6 +99,8 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, switch (tag) { case Tag::CREATE_SURFACE: return callLocal(data, reply, &ISurfaceComposerClient::createSurface); + case Tag::CREATE_WITH_SURFACE_PARENT: + return callLocal(data, reply, &ISurfaceComposerClient::createWithSurfaceParent); case Tag::CLEAR_LAYER_FRAME_STATS: return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats); case Tag::GET_LAYER_FRAME_STATS: diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6c39d6f1b8..8b9e4d7fee 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -977,6 +977,29 @@ sp SurfaceComposerClient::createSurface( return s; } +sp SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w, + uint32_t h, PixelFormat format, + uint32_t flags, Surface* parent, + int32_t windowType, + int32_t ownerUid) { + sp sur; + status_t err = mStatus; + + if (mStatus == NO_ERROR) { + sp handle; + sp parentGbp = parent->getIGraphicBufferProducer(); + sp gbp; + + err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType, + ownerUid, &handle, &gbp); + ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err)); + if (err == NO_ERROR) { + return new SurfaceControl(this, handle, gbp, true /* owned */); + } + } + return nullptr; +} + status_t SurfaceComposerClient::createSurfaceChecked( const String8& name, uint32_t w, @@ -1132,6 +1155,7 @@ status_t SurfaceComposerClient::getDisplayedContentSample(const sp& dis return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames, timestamp, outStats); } + // ---------------------------------------------------------------------------- status_t ScreenshotClient::capture(const sp& display, const ui::Dataspace reqDataSpace, diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 56ca197ff9..f443df8533 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -55,6 +55,16 @@ public: int32_t ownerUid, sp* handle, sp* gbp) = 0; + /* + * Requires ACCESS_SURFACE_FLINGER permission + */ + virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + const sp& parent, + int32_t windowType, int32_t ownerUid, + sp* handle, + sp* gbp) = 0; + /* * Requires ACCESS_SURFACE_FLINGER permission */ diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e0cbb705c7..f16f7814e2 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -168,15 +168,27 @@ public: ); status_t createSurfaceChecked( - const String8& name,// name of the surface - uint32_t w, // width in pixel - uint32_t h, // height in pixel - PixelFormat format, // pixel-format desired + const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired sp* outSurface, - uint32_t flags = 0, // usage flags + uint32_t flags = 0, // usage flags SurfaceControl* parent = nullptr, // parent int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - int32_t ownerUid = -1 // UID of the task + int32_t ownerUid = -1 // UID of the task + ); + + //! Create a surface + sp createWithSurfaceParent( + const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + uint32_t flags = 0, // usage flags + Surface* parent = nullptr, // parent + int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) + int32_t ownerUid = -1 // UID of the task ); //! Create a virtual display diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 4f6fb1cca6..0e447d87f2 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -95,6 +95,26 @@ status_t Client::createSurface( ownerUid, handle, gbp, &parent); } +status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + const sp& parent, + int32_t windowType, int32_t ownerUid, sp* handle, + sp* gbp) { + if (mFlinger->authenticateSurfaceTexture(parent) == false) { + return BAD_VALUE; + } + + const auto& layer = (static_cast(parent.get()))->getLayer(); + if (layer == nullptr) { + return BAD_VALUE; + } + + sp parentHandle = layer->getHandle(); + + return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle, + gbp); +} + status_t Client::clearLayerFrameStats(const sp& handle) const { sp layer = getLayerUser(handle); if (layer == nullptr) { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index d0051dee1a..0f5ee4c85c 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -58,6 +58,12 @@ private: sp* handle, sp* gbp); + virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + const sp& parent, + int32_t windowType, int32_t ownerUid, + sp* handle, sp* gbp); + virtual status_t clearLayerFrameStats(const sp& handle) const; virtual status_t getLayerFrameStats(const sp& handle, FrameStats* outStats) const; -- cgit v1.2.3-59-g8ed1b From 1f6d6d5db93ef4c3bbaeb5241eede30635fa5ff1 Mon Sep 17 00:00:00 2001 From: Evan Rosky Date: Thu, 6 Dec 2018 10:47:26 -0800 Subject: Add metadata store to surfaces This adds a key/value metadata storage mechanism to surfaces that allows the windowmanager to pass information to the surfaceflinger frontend. This then moves the existing metadata (window type and ownerUID) into this metadata structure. Bug: 122925737 Test: Phone boots and surfaces fling. Some unittests Change-Id: I72c574737b7f75be2311a341812b15d385f507ed --- libs/gui/Android.bp | 1 + libs/gui/ISurfaceComposerClient.cpp | 16 +-- libs/gui/LayerMetadata.cpp | 114 +++++++++++++++++++++ libs/gui/LayerState.cpp | 6 ++ libs/gui/SurfaceComposerClient.cpp | 58 ++++++----- libs/gui/include/gui/ISurfaceComposerClient.h | 10 +- libs/gui/include/gui/LayerMetadata.h | 49 +++++++++ libs/gui/include/gui/LayerState.h | 4 + libs/gui/include/gui/SurfaceComposerClient.h | 52 +++++----- services/surfaceflinger/Client.cpp | 21 ++-- services/surfaceflinger/Client.h | 14 ++- services/surfaceflinger/Layer.cpp | 30 +++--- services/surfaceflinger/Layer.h | 5 +- services/surfaceflinger/SurfaceFlinger.cpp | 25 +++-- services/surfaceflinger/SurfaceFlinger.h | 8 +- services/surfaceflinger/layerproto/Android.bp | 2 +- .../surfaceflinger/layerproto/LayerProtoParser.cpp | 17 ++- .../include/layerproto/LayerProtoParser.h | 4 +- services/surfaceflinger/layerproto/layers.proto | 6 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/LayerMetadataTest.cpp | 86 ++++++++++++++++ 21 files changed, 401 insertions(+), 128 deletions(-) create mode 100644 libs/gui/LayerMetadata.cpp create mode 100644 libs/gui/include/gui/LayerMetadata.h create mode 100644 services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp (limited to 'libs/gui/ISurfaceComposerClient.cpp') diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 3521e89ae6..b148015c14 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -108,6 +108,7 @@ cc_library_shared { "ISurfaceComposerClient.cpp", "ITransactionCompletedListener.cpp", "LayerDebugInfo.cpp", + "LayerMetadata.cpp", "LayerState.cpp", "OccupancyTracker.cpp", "StreamSplitter.cpp", diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 928ef95aa8..129558bd15 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -47,26 +47,26 @@ public: ~BpSurfaceComposerClient() override; status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, - uint32_t flags, const sp& parent, int32_t windowType, - int32_t ownerUid, sp* handle, - sp* gbp) override { + uint32_t flags, const sp& parent, LayerMetadata metadata, + sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_SURFACE, name, width, height, format, flags, parent, - windowType, ownerUid, + std::move(metadata), handle, gbp); } status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, - const sp& parent, int32_t windowType, - int32_t ownerUid, sp* handle, + const sp& parent, + LayerMetadata metadata, sp* handle, sp* gbp) override { return callRemote(Tag::CREATE_WITH_SURFACE_PARENT, name, width, height, format, - flags, parent, windowType, - ownerUid, handle, gbp); + flags, parent, + std::move(metadata), handle, + gbp); } status_t clearLayerFrameStats(const sp& handle) const override { diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp new file mode 100644 index 0000000000..c8a2b0754b --- /dev/null +++ b/libs/gui/LayerMetadata.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2019 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. + */ + +#include +#include +#include + +using android::base::StringPrintf; + +namespace android { + +LayerMetadata::LayerMetadata() = default; + +LayerMetadata::LayerMetadata(std::unordered_map> map) + : mMap(std::move(map)) {} + +LayerMetadata::LayerMetadata(const LayerMetadata& other) = default; + +LayerMetadata::LayerMetadata(LayerMetadata&& other) = default; + +void LayerMetadata::merge(const LayerMetadata& other) { + for (const auto& entry : other.mMap) { + mMap[entry.first] = entry.second; + } +} + +status_t LayerMetadata::writeToParcel(Parcel* parcel) const { + parcel->writeInt32(static_cast(mMap.size())); + status_t status = OK; + for (const auto& entry : mMap) { + status = parcel->writeUint32(entry.first); + if (status != OK) { + break; + } + status = parcel->writeByteVector(entry.second); + if (status != OK) { + break; + } + } + return status; +} + +status_t LayerMetadata::readFromParcel(const Parcel* parcel) { + int size = parcel->readInt32(); + status_t status = OK; + mMap.clear(); + for (int i = 0; i < size; ++i) { + uint32_t key = parcel->readUint32(); + status = parcel->readByteVector(&mMap[key]); + if (status != OK) { + break; + } + } + return status; +} + +LayerMetadata& LayerMetadata::operator=(const LayerMetadata& other) { + mMap = other.mMap; + return *this; +} + +LayerMetadata& LayerMetadata::operator=(LayerMetadata&& other) { + mMap = std::move(other.mMap); + return *this; +} + +bool LayerMetadata::has(uint32_t key) const { + return mMap.count(key); +} + +int32_t LayerMetadata::getInt32(uint32_t key, int32_t fallback) const { + if (!has(key)) return fallback; + const std::vector& data = mMap.at(key); + if (data.size() < sizeof(uint32_t)) return fallback; + Parcel p; + p.setData(data.data(), data.size()); + return p.readInt32(); +} + +void LayerMetadata::setInt32(uint32_t key, int32_t value) { + std::vector& data = mMap[key]; + Parcel p; + p.writeInt32(value); + data.resize(p.dataSize()); + memcpy(data.data(), p.data(), p.dataSize()); +} + +std::string LayerMetadata::itemToString(uint32_t key, const char* separator) const { + if (!has(key)) return std::string(); + switch (key) { + case METADATA_OWNER_UID: + return StringPrintf("ownerUID%s%d", separator, getInt32(key, 0)); + case METADATA_WINDOW_TYPE: + return StringPrintf("windowType%s%d", separator, getInt32(key, 0)); + default: + return StringPrintf("%d%s%dbytes", key, separator, + static_cast(mMap.at(key).size())); + } +} + +} // namespace android diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index ab929731f3..6091d3f08a 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -96,6 +96,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeStrongBinder(cachedBuffer.token); output.writeInt32(cachedBuffer.bufferId); + output.writeParcelable(metadata); output.writeFloat(colorAlpha); output.writeUint32(static_cast(colorDataspace)); @@ -172,6 +173,7 @@ status_t layer_state_t::read(const Parcel& input) cachedBuffer.token = input.readStrongBinder(); cachedBuffer.bufferId = input.readInt32(); + input.readParcelable(&metadata); colorAlpha = input.readFloat(); colorDataspace = static_cast(input.readUint32()); @@ -396,6 +398,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eColorDataspaceChanged; colorDataspace = other.colorDataspace; } + if (other.what & eMetadataChanged) { + what |= eMetadataChanged; + metadata.merge(other.metadata); + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 6c1c52e1bd..67d936100e 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -539,6 +539,20 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setLayer return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMetadata( + const sp& sc, uint32_t key, std::vector data) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eMetadataChanged; + s->metadata.mMap[key] = std::move(data); + + registerSurfaceControlForCallback(sc); + return *this; +} + SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setMatrix( const sp& sc, float dsdx, float dtdx, float dtdy, float dsdy) { @@ -1141,26 +1155,19 @@ void SurfaceComposerClient::dispose() { mStatus = NO_INIT; } -sp SurfaceComposerClient::createSurface( - const String8& name, - uint32_t w, - uint32_t h, - PixelFormat format, - uint32_t flags, - SurfaceControl* parent, - int32_t windowType, - int32_t ownerUid) -{ +sp SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, + SurfaceControl* parent, + LayerMetadata metadata) { sp s; - createSurfaceChecked(name, w, h, format, &s, flags, parent, windowType, ownerUid); + createSurfaceChecked(name, w, h, format, &s, flags, parent, std::move(metadata)); return s; } sp SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, Surface* parent, - int32_t windowType, - int32_t ownerUid) { + LayerMetadata metadata) { sp sur; status_t err = mStatus; @@ -1169,8 +1176,8 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& sp parentGbp = parent->getIGraphicBufferProducer(); sp gbp; - err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, windowType, - ownerUid, &handle, &gbp); + err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp, + std::move(metadata), &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err)); if (err == NO_ERROR) { return new SurfaceControl(this, handle, gbp, true /* owned */); @@ -1179,17 +1186,11 @@ sp SurfaceComposerClient::createWithSurfaceParent(const String8& return nullptr; } -status_t SurfaceComposerClient::createSurfaceChecked( - const String8& name, - uint32_t w, - uint32_t h, - PixelFormat format, - sp* outSurface, - uint32_t flags, - SurfaceControl* parent, - int32_t windowType, - int32_t ownerUid) -{ +status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h, + PixelFormat format, + sp* outSurface, uint32_t flags, + SurfaceControl* parent, + LayerMetadata metadata) { sp sur; status_t err = mStatus; @@ -1201,8 +1202,9 @@ status_t SurfaceComposerClient::createSurfaceChecked( if (parent != nullptr) { parentHandle = parent->getHandle(); } - err = mClient->createSurface(name, w, h, format, flags, parentHandle, - windowType, ownerUid, &handle, &gbp); + + err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), + &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { *outSurface = new SurfaceControl(this, handle, gbp, true /* owned */); diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index f443df8533..32ac9e8928 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -18,8 +18,11 @@ #include #include +#include #include +#include + namespace android { class FrameStats; @@ -51,8 +54,8 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags, const sp& parent, int32_t windowType, - int32_t ownerUid, sp* handle, + uint32_t flags, const sp& parent, + LayerMetadata metadata, sp* handle, sp* gbp) = 0; /* @@ -61,8 +64,7 @@ public: virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, - int32_t windowType, int32_t ownerUid, - sp* handle, + LayerMetadata metadata, sp* handle, sp* gbp) = 0; /* diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h new file mode 100644 index 0000000000..50121817d5 --- /dev/null +++ b/libs/gui/include/gui/LayerMetadata.h @@ -0,0 +1,49 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include + +#include + +namespace android { + +enum { METADATA_OWNER_UID = 1, METADATA_WINDOW_TYPE = 2 }; + +struct LayerMetadata : public Parcelable { + std::unordered_map> mMap; + + LayerMetadata(); + LayerMetadata(const LayerMetadata& other); + LayerMetadata(LayerMetadata&& other); + explicit LayerMetadata(std::unordered_map> map); + LayerMetadata& operator=(const LayerMetadata& other); + LayerMetadata& operator=(LayerMetadata&& other); + + void merge(const LayerMetadata& other); + + status_t writeToParcel(Parcel* parcel) const override; + status_t readFromParcel(const Parcel* parcel) override; + + bool has(uint32_t key) const; + int32_t getInt32(uint32_t key, int32_t fallback) const; + void setInt32(uint32_t key, int32_t value); + + std::string itemToString(uint32_t key, const char* separator) const; +}; + +} // namespace android diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 9063e7fbb4..afd843f09e 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -30,6 +30,7 @@ #include #endif +#include #include #include #include @@ -87,6 +88,7 @@ struct layer_state_t { eCachedBufferChanged = 0x2'00000000, eColorAlphaChanged = 0x4'00000000, eColorDataspaceChanged = 0x8'00000000, + eMetadataChanged = 0x10'00000000, }; layer_state_t() @@ -187,6 +189,8 @@ struct layer_state_t { float colorAlpha; ui::Dataspace colorDataspace; + + LayerMetadata metadata; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 24b656b543..bffe3f98e0 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -159,39 +159,33 @@ public: static sp getDefault(); //! Create a surface - sp createSurface( - const String8& name,// name of the surface - uint32_t w, // width in pixel - uint32_t h, // height in pixel - PixelFormat format, // pixel-format desired - uint32_t flags = 0, // usage flags - SurfaceControl* parent = nullptr, // parent - int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - int32_t ownerUid = -1 // UID of the task + sp createSurface(const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + uint32_t flags = 0, // usage flags + SurfaceControl* parent = nullptr, // parent + LayerMetadata metadata = LayerMetadata() // metadata ); - status_t createSurfaceChecked( - const String8& name, // name of the surface - uint32_t w, // width in pixel - uint32_t h, // height in pixel - PixelFormat format, // pixel-format desired - sp* outSurface, - uint32_t flags = 0, // usage flags - SurfaceControl* parent = nullptr, // parent - int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - int32_t ownerUid = -1 // UID of the task + status_t createSurfaceChecked(const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + sp* outSurface, + uint32_t flags = 0, // usage flags + SurfaceControl* parent = nullptr, // parent + LayerMetadata metadata = LayerMetadata() // metadata ); //! Create a surface - sp createWithSurfaceParent( - const String8& name, // name of the surface - uint32_t w, // width in pixel - uint32_t h, // height in pixel - PixelFormat format, // pixel-format desired - uint32_t flags = 0, // usage flags - Surface* parent = nullptr, // parent - int32_t windowType = -1, // from WindowManager.java (STATUS_BAR, INPUT_METHOD, etc.) - int32_t ownerUid = -1 // UID of the task + sp createWithSurfaceParent(const String8& name, // name of the surface + uint32_t w, // width in pixel + uint32_t h, // height in pixel + PixelFormat format, // pixel-format desired + uint32_t flags = 0, // usage flags + Surface* parent = nullptr, // parent + LayerMetadata metadata = LayerMetadata() // metadata ); //! Create a virtual display @@ -302,6 +296,8 @@ public: Transaction& setCrop_legacy(const sp& sc, const Rect& crop); Transaction& setCornerRadius(const sp& sc, float cornerRadius); Transaction& setLayerStack(const sp& sc, uint32_t layerStack); + Transaction& setMetadata(const sp& sc, uint32_t key, + std::vector data); // Defers applying any changes made in this transaction until the Layer // identified by handle reaches the given frameNumber. If the Layer identified // by handle is removed, then we will apply this transaction regardless of diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 0e447d87f2..0ca3759f07 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -73,14 +73,10 @@ sp Client::getLayerUser(const sp& handle) const return lbc; } - -status_t Client::createSurface( - const String8& name, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - const sp& parentHandle, int32_t windowType, int32_t ownerUid, - sp* handle, - sp* gbp) -{ +status_t Client::createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, + uint32_t flags, const sp& parentHandle, + LayerMetadata metadata, sp* handle, + sp* gbp) { sp parent = nullptr; if (parentHandle != nullptr) { auto layerHandle = reinterpret_cast(parentHandle.get()); @@ -91,14 +87,14 @@ status_t Client::createSurface( } // We rely on createLayer to check permissions. - return mFlinger->createLayer(name, this, w, h, format, flags, windowType, - ownerUid, handle, gbp, &parent); + return mFlinger->createLayer(name, this, w, h, format, flags, std::move(metadata), handle, gbp, + &parent); } status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, - int32_t windowType, int32_t ownerUid, sp* handle, + LayerMetadata metadata, sp* handle, sp* gbp) { if (mFlinger->authenticateSurfaceTexture(parent) == false) { return BAD_VALUE; @@ -111,8 +107,7 @@ status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32 sp parentHandle = layer->getHandle(); - return createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, handle, - gbp); + return createSurface(name, w, h, format, flags, parentHandle, std::move(metadata), handle, gbp); } status_t Client::clearLayerFrameStats(const sp& handle) const { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 0f5ee4c85c..74e48188d6 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -51,18 +51,16 @@ public: private: // ISurfaceComposerClient interface - virtual status_t createSurface( - const String8& name, - uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, - const sp& parent, int32_t windowType, int32_t ownerUid, - sp* handle, - sp* gbp); + virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format, + uint32_t flags, const sp& parent, + LayerMetadata metadata, sp* handle, + sp* gbp); virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, const sp& parent, - int32_t windowType, int32_t ownerUid, - sp* handle, sp* gbp); + LayerMetadata metadata, sp* handle, + sp* gbp); virtual status_t clearLayerFrameStats(const sp& handle) const; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ef77590761..272793a7b1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -94,8 +94,6 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.layerStack = 0; mCurrentState.sequence = 0; mCurrentState.requested_legacy = mCurrentState.active_legacy; - mCurrentState.appId = 0; - mCurrentState.type = 0; mCurrentState.active.w = UINT32_MAX; mCurrentState.active.h = UINT32_MAX; mCurrentState.active.transform.set(0, 0); @@ -600,14 +598,16 @@ void Layer::setGeometry(const sp& display, uint32_t z) { to_string(error).c_str(), static_cast(error)); getBE().compositionInfo.hwc.z = z; - int type = s.type; - int appId = s.appId; + int type = s.metadata.getInt32(METADATA_WINDOW_TYPE, 0); + int appId = s.metadata.getInt32(METADATA_OWNER_UID, 0); sp parent = mDrawingParent.promote(); if (parent.get()) { auto& parentState = parent->getDrawingState(); - if (parentState.type >= 0 || parentState.appId >= 0) { - type = parentState.type; - appId = parentState.appId; + const int parentType = parentState.metadata.getInt32(METADATA_WINDOW_TYPE, 0); + const int parentAppId = parentState.metadata.getInt32(METADATA_OWNER_UID, 0); + if (parentType >= 0 || parentAppId >= 0) { + type = parentType; + appId = parentAppId; } } @@ -1316,11 +1316,14 @@ bool Layer::setOverrideScalingMode(int32_t scalingMode) { return true; } -void Layer::setInfo(int32_t type, int32_t appId) { - mCurrentState.appId = appId; - mCurrentState.type = type; +bool Layer::setMetadata(LayerMetadata data) { + bool changed = data.mMap != mCurrentState.metadata.mMap; + if (!changed) return false; + mCurrentState.metadata = std::move(data); + mCurrentState.sequence++; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); + return true; } bool Layer::setLayerStack(uint32_t layerStack) { @@ -2088,8 +2091,6 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); - layerInfo->set_window_type(state.type); - layerInfo->set_app_id(state.appId); layerInfo->set_curr_frame(mCurrentFrameNumber); layerInfo->set_effective_scaling_mode(getEffectiveScalingMode()); @@ -2101,6 +2102,11 @@ void Layer::writeToProto(LayerProto* layerInfo, LayerVector::StateSet stateSet) barrierLayerProto->set_frame_number(pendingState.frameNumber_legacy); } } + + auto protoMap = layerInfo->mutable_metadata(); + for (const auto& entry : state.metadata.mMap) { + (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend()); + } } void Layer::writeToProto(LayerProto* layerInfo, DisplayId displayId) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 685f419d4a..b0efb54f97 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -167,8 +167,7 @@ public: Region activeTransparentRegion_legacy; Region requestedTransparentRegion_legacy; - int32_t appId; - int32_t type; + LayerMetadata metadata; // If non-null, a Surface this Surface's Z-order is interpreted relative to. wp zOrderRelativeOf; @@ -284,7 +283,7 @@ public: uint64_t frameNumber); virtual void deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber); virtual bool setOverrideScalingMode(int32_t overrideScalingMode); - virtual void setInfo(int32_t type, int32_t appId); + virtual bool setMetadata(LayerMetadata data); virtual bool reparentChildren(const sp& layer); virtual void setChildrenDrawingParent(const sp& layer); virtual bool reparent(const sp& newParentHandle); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 299499da12..04c1ba0ade 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3983,6 +3983,9 @@ uint32_t SurfaceFlinger::setClientStateLocked(const ComposerState& composerState ALOGE("Attempt to update InputWindowInfo without permission ACCESS_SURFACE_FLINGER"); } } + if (what & layer_state_t::eMetadataChanged) { + if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded; + } std::vector> callbackHandles; if ((what & layer_state_t::eListenerCallbacksChanged) && (!s.listenerCallbacks.empty())) { mTransactionCompletedThread.run(); @@ -4011,13 +4014,10 @@ uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& input return flags; } -status_t SurfaceFlinger::createLayer( - const String8& name, - const sp& client, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - int32_t windowType, int32_t ownerUid, sp* handle, - sp* gbp, sp* parent) -{ +status_t SurfaceFlinger::createLayer(const String8& name, const sp& client, uint32_t w, + uint32_t h, PixelFormat format, uint32_t flags, + LayerMetadata metadata, sp* handle, + sp* gbp, sp* parent) { if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); @@ -4073,12 +4073,15 @@ status_t SurfaceFlinger::createLayer( // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java // TODO b/64227542 - if (windowType == 441731) { - windowType = 2024; // TYPE_NAVIGATION_BAR_PANEL - layer->setPrimaryDisplayOnly(); + if (metadata.has(METADATA_WINDOW_TYPE)) { + int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0); + if (windowType == 441731) { + metadata.setInt32(METADATA_WINDOW_TYPE, 2024); // TYPE_NAVIGATION_BAR_PANEL + layer->setPrimaryDisplayOnly(); + } } - layer->setInfo(windowType, ownerUid); + layer->setMetadata(std::move(metadata)); bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess(); result = addClientLayer(client, *handle, *gbp, layer, *parent, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 68a602cf61..5219e2fdb8 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -141,7 +141,6 @@ enum class DisplayColorSetting : int32_t { ENHANCED = 2, }; - class SurfaceFlingerBE { public: @@ -556,10 +555,9 @@ private: /* ------------------------------------------------------------------------ * Layer management */ - status_t createLayer(const String8& name, const sp& client, - uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - int32_t windowType, int32_t ownerUid, sp* handle, - sp* gbp, sp* parent); + status_t createLayer(const String8& name, const sp& client, uint32_t w, uint32_t h, + PixelFormat format, uint32_t flags, LayerMetadata metadata, + sp* handle, sp* gbp, sp* parent); status_t createBufferQueueLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp index ac147fe182..cb368b0886 100644 --- a/services/surfaceflinger/layerproto/Android.bp +++ b/services/surfaceflinger/layerproto/Android.bp @@ -1,6 +1,5 @@ cc_library_shared { name: "liblayers_proto", - vendor_available: true, export_include_dirs: ["include"], srcs: [ @@ -11,6 +10,7 @@ cc_library_shared { shared_libs: [ "android.hardware.graphics.common@1.1", + "libgui", "libui", "libprotobuf-cpp-lite", "libbase", diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp index d020a394ce..5c72fea375 100644 --- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp +++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp @@ -117,11 +117,15 @@ LayerProtoParser::Layer LayerProtoParser::generateLayer(const LayerProto& layerP layer.hwcFrame = generateRect(layerProto.hwc_frame()); layer.hwcCrop = generateFloatRect(layerProto.hwc_crop()); layer.hwcTransform = layerProto.hwc_transform(); - layer.windowType = layerProto.window_type(); - layer.appId = layerProto.app_id(); layer.hwcCompositionType = layerProto.hwc_composition_type(); layer.isProtected = layerProto.is_protected(); layer.cornerRadius = layerProto.corner_radius(); + for (const auto& entry : layerProto.metadata()) { + const std::string& dataStr = entry.second; + std::vector& outData = layer.metadata.mMap[entry.first]; + outData.resize(dataStr.size()); + memcpy(outData.data(), dataStr.data(), dataStr.size()); + } return layer; } @@ -310,7 +314,14 @@ std::string LayerProtoParser::Layer::to_string() const { StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str()); StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str()); StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending); - StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId); + StringAppendF(&result, " metadata={"); + bool first = true; + for (const auto& entry : metadata.mMap) { + if (!first) result.append(", "); + first = false; + result.append(metadata.itemToString(entry.first, ":")); + } + result.append("}"); return result; } diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h index a794ca57a3..d1b2b1ffed 100644 --- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h +++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h @@ -17,6 +17,7 @@ #include +#include #include #include @@ -110,11 +111,10 @@ public: LayerProtoParser::Rect hwcFrame; LayerProtoParser::FloatRect hwcCrop; int32_t hwcTransform; - int32_t windowType; - int32_t appId; int32_t hwcCompositionType; bool isProtected; float cornerRadius; + LayerMetadata metadata; std::string to_string() const; }; diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto index b10043877c..4c756d93bb 100644 --- a/services/surfaceflinger/layerproto/layers.proto +++ b/services/surfaceflinger/layerproto/layers.proto @@ -74,8 +74,8 @@ message LayerProto { optional FloatRectProto hwc_crop = 31; // The layer's composer backend transform optional int32 hwc_transform = 32; - optional int32 window_type = 33; - optional int32 app_id = 34; + optional int32 window_type = 33 [deprecated=true]; + optional int32 app_id = 34 [deprecated=true]; // The layer's composition type optional int32 hwc_composition_type = 35; // If it's a buffer layer, indicate if the content is protected @@ -89,6 +89,8 @@ message LayerProto { optional int32 effective_scaling_mode = 40; // Layer's corner radius. optional float corner_radius = 41; + // Metadata map. May be empty. + map metadata = 42; } message PositionProto { diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index e34e568132..b2bcb45945 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -42,6 +42,7 @@ cc_test { "EventThreadTest.cpp", "IdleTimerTest.cpp", "LayerHistoryTest.cpp", + "LayerMetadataTest.cpp", "SchedulerTest.cpp", "SchedulerUtilsTest.cpp", "RefreshRateStatsTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp new file mode 100644 index 0000000000..92c9f92bf1 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 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. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include +#include +#include +#include + +namespace android { +namespace { + +class LayerMetadataTest : public testing::Test { +public: + LayerMetadataTest(); + ~LayerMetadataTest() override; +}; + +LayerMetadataTest::LayerMetadataTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +LayerMetadataTest::~LayerMetadataTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); +} + +TEST_F(LayerMetadataTest, testLayerMetadata) { + LayerMetadata metadata; + + ASSERT_EQ(0, metadata.mMap.size()); + + // Test non-set + ASSERT_EQ(3, metadata.getInt32(4, 3)); + + // Make sure it's still unset + ASSERT_EQ(5, metadata.getInt32(4, 5)); + + metadata.setInt32(4, 2); + ASSERT_EQ(2, metadata.getInt32(4, 0)); + + // data is too small + metadata.mMap[2] = std::vector{'a', 'b'}; + ASSERT_EQ(0, metadata.getInt32(2, 0)); + + LayerMetadata second; + std::vector someData{'c', 'd', '\0'}; + second.mMap[2] = someData; + second.setInt32(6, 5); + metadata.merge(second); + + ASSERT_EQ(3, metadata.mMap.size()); + ASSERT_EQ(someData, second.mMap[2]); + ASSERT_EQ(5, metadata.getInt32(6, 0)); + ASSERT_EQ(2, metadata.getInt32(4, 0)); + + Parcel p; + metadata.writeToParcel(&p); + LayerMetadata reconstructed; + reconstructed.setInt32(3, 1); // to make sure it gets replaced + p.setDataPosition(0); + reconstructed.readFromParcel(&p); + ASSERT_EQ(metadata.mMap, reconstructed.mMap); +} + +} // namespace +} // namespace android -- cgit v1.2.3-59-g8ed1b