diff options
| -rw-r--r-- | aidl/gui/android/view/LayerMetadataKey.aidl | 1 | ||||
| -rw-r--r-- | libs/gui/LayerMetadata.cpp | 2 | ||||
| -rw-r--r-- | libs/gui/include/gui/LayerMetadata.h | 3 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/EffectLayer.cpp | 5 | ||||
| -rw-r--r-- | services/surfaceflinger/FrameTimeline/FrameTimeline.cpp | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 17 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.h | 11 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 14 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/unittests/Android.bp | 1 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/unittests/GameModeTest.cpp | 159 |
12 files changed, 207 insertions, 18 deletions
diff --git a/aidl/gui/android/view/LayerMetadataKey.aidl b/aidl/gui/android/view/LayerMetadataKey.aidl index a1d8ce5962..d6ca3db5d7 100644 --- a/aidl/gui/android/view/LayerMetadataKey.aidl +++ b/aidl/gui/android/view/LayerMetadataKey.aidl @@ -26,4 +26,5 @@ enum LayerMetadataKey { METADATA_ACCESSIBILITY_ID = 5, METADATA_OWNER_PID = 6, METADATA_DEQUEUE_TIME = 7, + METADATA_GAME_MODE = 8, } diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp index 634d8b7df0..189d51a4c1 100644 --- a/libs/gui/LayerMetadata.cpp +++ b/libs/gui/LayerMetadata.cpp @@ -136,6 +136,8 @@ std::string LayerMetadata::itemToString(uint32_t key, const char* separator) con return StringPrintf("ownerPID%s%d", separator, getInt32(key, 0)); case view::LayerMetadataKey::METADATA_DEQUEUE_TIME: return StringPrintf("dequeueTime%s%" PRId64, separator, *getInt64(key)); + case view::LayerMetadataKey::METADATA_GAME_MODE: + return StringPrintf("gameMode%s%d", separator, getInt32(key, 0)); default: return StringPrintf("%d%s%dbytes", key, separator, static_cast<int>(mMap.at(key).size())); diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h index 41982c28a2..de14b3d785 100644 --- a/libs/gui/include/gui/LayerMetadata.h +++ b/libs/gui/include/gui/LayerMetadata.h @@ -29,7 +29,8 @@ enum { METADATA_MOUSE_CURSOR = 4, METADATA_ACCESSIBILITY_ID = 5, METADATA_OWNER_PID = 6, - METADATA_DEQUEUE_TIME = 7 + METADATA_DEQUEUE_TIME = 7, + METADATA_GAME_MODE = 8 }; struct LayerMetadata : public Parcelable { diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 7e069c80d0..cf433c08d9 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -3893,12 +3893,6 @@ void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) { args->xCursorPosition, args->yCursorPosition, args->downTime, args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0); - if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID && - IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER && - !mInputFilterEnabled) { - const bool isDown = args->action == AMOTION_EVENT_ACTION_DOWN; - mLatencyTracker.trackListener(args->id, isDown, args->eventTime, args->readTime); - } needWake = enqueueInboundEventLocked(std::move(newEntry)); mLock.unlock(); diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp index fd18c3bf31..0cc5f33d73 100644 --- a/services/surfaceflinger/EffectLayer.cpp +++ b/services/surfaceflinger/EffectLayer.cpp @@ -66,6 +66,7 @@ std::vector<compositionengine::LayerFE::LayerSettings> EffectLayer::prepareClien layerSettings->source.solidColor = getColor().rgb; results.push_back(*layerSettings); } else if (hasBlur() || drawShadows()) { + layerSettings->skipContentDraw = true; results.push_back(*layerSettings); } @@ -126,7 +127,7 @@ const compositionengine::LayerFECompositionState* EffectLayer::getCompositionSta bool EffectLayer::isOpaque(const Layer::State& s) const { // Consider the layer to be opaque if its opaque flag is set or its effective // alpha (considering the alpha of its parents as well) is 1.0; - return (s.flags & layer_state_t::eLayerOpaque) != 0 || getAlpha() == 1.0_hf; + return (s.flags & layer_state_t::eLayerOpaque) != 0 || (fillsColor() && getAlpha() == 1.0_hf); } ui::Dataspace EffectLayer::getDataSpace() const { @@ -147,7 +148,7 @@ bool EffectLayer::fillsColor() const { } bool EffectLayer::hasBlur() const { - return getBackgroundBlurRadius() > 0; + return getBackgroundBlurRadius() > 0 || getDrawingState().blurRegions.size() > 0; } } // namespace android diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp index f19e2a7863..9b03287242 100644 --- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp +++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp @@ -136,6 +136,10 @@ std::string jankTypeBitmaskToString(int32_t jankType) { janks.emplace_back("Unknown jank"); jankType &= ~JankType::Unknown; } + if (jankType & JankType::SurfaceFlingerStuffing) { + janks.emplace_back("SurfaceFlinger Stuffing"); + jankType &= ~JankType::SurfaceFlingerStuffing; + } // jankType should be 0 if all types of jank were checked for. LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a7c870483b..d720bcb20f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -574,7 +574,8 @@ std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCom layerSettings.geometry.positionTransform = getTransform().asMatrix4(); // skip drawing content if the targetSettings indicate the content will be occluded - layerSettings.skipContentDraw = !targetSettings.realContentIsVisible; + layerSettings.skipContentDraw = + layerSettings.skipContentDraw || !targetSettings.realContentIsVisible; if (hasColorTransform()) { layerSettings.colorTransform = getColorTransform(); @@ -1651,12 +1652,25 @@ size_t Layer::getChildrenCount() const { return count; } +void Layer::setGameModeForTree(int parentGameMode) { + int gameMode = parentGameMode; + auto& currentState = getCurrentState(); + if (currentState.metadata.has(METADATA_GAME_MODE)) { + gameMode = currentState.metadata.getInt32(METADATA_GAME_MODE, 0); + } + setGameMode(gameMode); + for (const sp<Layer>& child : mCurrentChildren) { + child->setGameModeForTree(gameMode); + } +} + void Layer::addChild(const sp<Layer>& layer) { mChildrenChanged = true; setTransactionFlags(eTransactionNeeded); mCurrentChildren.add(layer); layer->setParent(this); + layer->setGameModeForTree(mGameMode); updateTreeHasFrameRateVote(); } @@ -1668,6 +1682,7 @@ ssize_t Layer::removeChild(const sp<Layer>& layer) { const auto removeResult = mCurrentChildren.remove(layer); updateTreeHasFrameRateVote(); + layer->setGameModeForTree(0); layer->updateTreeHasFrameRateVote(); return removeResult; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 66d70185a7..af2604582b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -847,6 +847,13 @@ public: */ bool hasInputInfo() const; + // Sets the parent's gameMode for this layer and all its children. Parent's gameMode is applied + // only to layers that do not have the GAME_MODE_METADATA set by WMShell. Any layer(along with + // its children) that has the metadata set will use the gameMode from the metadata. + void setGameModeForTree(int parentGameMode); + void setGameMode(int gameMode) { mGameMode = gameMode; }; + int getGameMode() const { return mGameMode; } + virtual uid_t getOwnerUid() const { return mOwnerUid; } pid_t getOwnerPid() { return mOwnerPid; } @@ -1089,6 +1096,10 @@ private: // shadow radius is the set shadow radius, otherwise its the parent's shadow radius. float mEffectiveShadowRadius = 0.f; + // Game mode for the layer. Set by WindowManagerShell, game mode is used in + // metrics(SurfaceFlingerStats). + int mGameMode = 0; + // A list of regions on this layer that should have blurs. const std::vector<BlurRegion> getBlurRegions() const; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 881ee5b8f4..a86e0610fb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -789,11 +789,6 @@ void SurfaceFlinger::readPersistentProperties() { property_get("persist.sys.sf.color_mode", value, "0"); mForceColorMode = static_cast<ColorMode>(atoi(value)); - - property_get("persist.sys.sf.disable_blurs", value, "0"); - bool disableBlurs = atoi(value); - mDisableBlurs = disableBlurs; - ALOGI_IF(disableBlurs, "Disabling blur effects, user preference."); } void SurfaceFlinger::startBootAnim() { @@ -3953,7 +3948,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (layer->setCornerRadius(s.cornerRadius)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur) { + if (what & layer_state_t::eBackgroundBlurRadiusChanged && mSupportsBlur) { if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded; } if (what & layer_state_t::eBlurRegionsChanged) { @@ -4018,6 +4013,13 @@ uint32_t SurfaceFlinger::setClientStateLocked( std::optional<nsecs_t> dequeueBufferTimestamp; if (what & layer_state_t::eMetadataChanged) { dequeueBufferTimestamp = s.metadata.getInt64(METADATA_DEQUEUE_TIME); + auto gameMode = s.metadata.getInt32(METADATA_GAME_MODE, -1); + if (gameMode != -1) { + // The transaction will be received on the Task layer and needs to be applied to all + // child layers. Child layers that are added at a later point will obtain the game mode + // info through addChild(). + layer->setGameModeForTree(gameMode); + } if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded; } if (what & layer_state_t::eColorSpaceAgnosticChanged) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index c3820053c1..30d76af61f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1264,8 +1264,6 @@ private: bool mUseHwcVirtualDisplays = false; // If blurs should be enabled on this device. bool mSupportsBlur = false; - // Disable blurs, for debugging - std::atomic<bool> mDisableBlurs = false; // If blurs are considered expensive and should require high GPU frequency. bool mBlursAreExpensive = false; std::atomic<uint32_t> mFrameMissedCount = 0; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 1b25a3684e..736ef30d7c 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -57,6 +57,7 @@ cc_test { "FpsTest.cpp", "FramebufferSurfaceTest.cpp", "FrameTimelineTest.cpp", + "GameModeTest.cpp", "HWComposerTest.cpp", "OneShotTimerTest.cpp", "LayerHistoryTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/GameModeTest.cpp b/services/surfaceflinger/tests/unittests/GameModeTest.cpp new file mode 100644 index 0000000000..3fa1a2c2f5 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/GameModeTest.cpp @@ -0,0 +1,159 @@ +/* + * Copyright 2021 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 <gmock/gmock.h> +#include <gtest/gtest.h> +#include <gui/LayerMetadata.h> +#include <gui/SurfaceComposerClient.h> +#include <log/log.h> + +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/MockEventThread.h" +#include "mock/MockVsyncController.h" + +namespace android { + +using testing::_; +using testing::Mock; +using testing::Return; +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; + +class GameModeTest : public testing::Test { +public: + GameModeTest() { + 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()); + setupScheduler(); + setupComposer(); + } + + ~GameModeTest() { + 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()); + } + + sp<BufferStateLayer> createBufferStateLayer() { + sp<Client> client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0, + LayerMetadata()); + return new BufferStateLayer(args); + } + + void setupScheduler() { + auto eventThread = std::make_unique<mock::EventThread>(); + auto sfEventThread = std::make_unique<mock::EventThread>(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0, + ResyncCallback()))); + + auto vsyncController = std::make_unique<mock::VsyncController>(); + auto vsyncTracker = std::make_unique<mock::VSyncTracker>(); + + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + EXPECT_CALL(*vsyncTracker, currentPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)); + EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0)); + mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker), + std::move(eventThread), std::move(sfEventThread)); + } + + void setupComposer() { + mComposer = new Hwc2::mock::Composer(); + mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); + + Mock::VerifyAndClear(mComposer); + } + + // Mocks the behavior of applying a transaction from WMShell + void setGameModeMetadata(sp<Layer> layer, int gameMode) { + mLayerMetadata.setInt32(METADATA_GAME_MODE, gameMode); + layer->setMetadata(mLayerMetadata); + layer->setGameModeForTree(gameMode); + } + + TestableSurfaceFlinger mFlinger; + Hwc2::mock::Composer* mComposer = nullptr; + client_cache_t mClientCache; + LayerMetadata mLayerMetadata; +}; + +TEST_F(GameModeTest, SetGameModeSetsForAllCurrentChildren) { + sp<BufferStateLayer> rootLayer = createBufferStateLayer(); + sp<BufferStateLayer> childLayer1 = createBufferStateLayer(); + sp<BufferStateLayer> childLayer2 = createBufferStateLayer(); + rootLayer->addChild(childLayer1); + rootLayer->addChild(childLayer2); + rootLayer->setGameModeForTree(/*gameMode*/ 2); + + EXPECT_EQ(rootLayer->getGameMode(), 2); + EXPECT_EQ(childLayer1->getGameMode(), 2); + EXPECT_EQ(childLayer2->getGameMode(), 2); +} + +TEST_F(GameModeTest, AddChildAppliesGameModeFromParent) { + sp<BufferStateLayer> rootLayer = createBufferStateLayer(); + sp<BufferStateLayer> childLayer = createBufferStateLayer(); + rootLayer->setGameModeForTree(/*gameMode*/ 2); + rootLayer->addChild(childLayer); + + EXPECT_EQ(rootLayer->getGameMode(), 2); + EXPECT_EQ(childLayer->getGameMode(), 2); +} + +TEST_F(GameModeTest, RemoveChildResetsGameMode) { + sp<BufferStateLayer> rootLayer = createBufferStateLayer(); + sp<BufferStateLayer> childLayer = createBufferStateLayer(); + rootLayer->setGameModeForTree(/*gameMode*/ 2); + rootLayer->addChild(childLayer); + + EXPECT_EQ(rootLayer->getGameMode(), 2); + EXPECT_EQ(childLayer->getGameMode(), 2); + + rootLayer->removeChild(childLayer); + EXPECT_EQ(childLayer->getGameMode(), 0); +} + +TEST_F(GameModeTest, ReparentingDoesNotOverrideMetadata) { + sp<BufferStateLayer> rootLayer = createBufferStateLayer(); + sp<BufferStateLayer> childLayer1 = createBufferStateLayer(); + sp<BufferStateLayer> childLayer2 = createBufferStateLayer(); + rootLayer->setGameModeForTree(/*gameMode*/ 1); + rootLayer->addChild(childLayer1); + + setGameModeMetadata(childLayer2, /*gameMode*/ 2); + rootLayer->addChild(childLayer2); + + EXPECT_EQ(rootLayer->getGameMode(), 1); + EXPECT_EQ(childLayer1->getGameMode(), 1); + EXPECT_EQ(childLayer2->getGameMode(), 2); + + rootLayer->removeChild(childLayer2); + EXPECT_EQ(childLayer2->getGameMode(), 2); +} +} // namespace android
\ No newline at end of file |