/* * Copyright 2022 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 #include #include #include "Client.h" // temporarily needed for LayerCreationArgs #include "FrontEnd/LayerCreationArgs.h" #include "FrontEnd/LayerHierarchy.h" #include "FrontEnd/LayerLifecycleManager.h" #include "FrontEnd/LayerSnapshotBuilder.h" namespace android::surfaceflinger::frontend { class LayerHierarchyTestBase : public testing::Test { protected: LayerHierarchyTestBase() { // tree with 3 levels of children // ROOT // ├── 1 // │ ├── 11 // │ │ └── 111 // │ ├── 12 // │ │ ├── 121 // │ │ └── 122 // │ │ └── 1221 // │ └── 13 // └── 2 createRootLayer(1); createRootLayer(2); createLayer(11, 1); createLayer(12, 1); createLayer(13, 1); createLayer(111, 11); createLayer(121, 12); createLayer(122, 12); createLayer(1221, 122); } LayerCreationArgs createArgs(uint32_t id, bool canBeRoot, uint32_t parentId, uint32_t layerIdToMirror) { LayerCreationArgs args(std::make_optional(id)); args.name = "testlayer"; args.addToRoot = canBeRoot; args.parentId = parentId; args.layerIdToMirror = layerIdToMirror; return args; } LayerCreationArgs createDisplayMirrorArgs(uint32_t id, ui::LayerStack layerStackToMirror) { LayerCreationArgs args(std::make_optional(id)); args.name = "testlayer"; args.addToRoot = true; args.layerStackToMirror = layerStackToMirror; return args; } std::vector getTraversalPath(const LayerHierarchy& hierarchy) const { std::vector layerIds; hierarchy.traverse([&layerIds = layerIds](const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath&) -> bool { layerIds.emplace_back(hierarchy.getLayer()->id); return true; }); return layerIds; } std::vector getTraversalPathInZOrder(const LayerHierarchy& hierarchy) const { std::vector layerIds; hierarchy.traverseInZOrder( [&layerIds = layerIds](const LayerHierarchy& hierarchy, const LayerHierarchy::TraversalPath&) -> bool { layerIds.emplace_back(hierarchy.getLayer()->id); return true; }); return layerIds; } virtual void createRootLayer(uint32_t id) { std::vector> layers; layers.emplace_back(std::make_unique( createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/UNASSIGNED_LAYER_ID, /*mirror=*/UNASSIGNED_LAYER_ID))); mLifecycleManager.addLayers(std::move(layers)); } void createDisplayMirrorLayer(uint32_t id, ui::LayerStack layerStack) { std::vector> layers; layers.emplace_back(std::make_unique( createDisplayMirrorArgs(/*id=*/id, layerStack))); mLifecycleManager.addLayers(std::move(layers)); } virtual void createLayer(uint32_t id, uint32_t parentId) { std::vector> layers; layers.emplace_back(std::make_unique( createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId, /*mirror=*/UNASSIGNED_LAYER_ID))); mLifecycleManager.addLayers(std::move(layers)); } std::vector reparentLayerTransaction(uint32_t id, uint32_t newParentId) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().parentId = newParentId; transactions.back().states.front().state.what = layer_state_t::eReparent; transactions.back().states.front().relativeParentId = UNASSIGNED_LAYER_ID; transactions.back().states.front().layerId = id; return transactions; } void reparentLayer(uint32_t id, uint32_t newParentId) { mLifecycleManager.applyTransactions(reparentLayerTransaction(id, newParentId)); } std::vector relativeLayerTransaction(uint32_t id, uint32_t relativeParentId) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().relativeParentId = relativeParentId; transactions.back().states.front().state.what = layer_state_t::eRelativeLayerChanged; transactions.back().states.front().layerId = id; return transactions; } void reparentRelativeLayer(uint32_t id, uint32_t relativeParentId) { mLifecycleManager.applyTransactions(relativeLayerTransaction(id, relativeParentId)); } void removeRelativeZ(uint32_t id) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eLayerChanged; transactions.back().states.front().layerId = id; mLifecycleManager.applyTransactions(transactions); } void setPosition(uint32_t id, float x, float y) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::ePositionChanged; transactions.back().states.front().state.x = x; transactions.back().states.front().state.y = y; transactions.back().states.front().layerId = id; mLifecycleManager.applyTransactions(transactions); } virtual void mirrorLayer(uint32_t id, uint32_t parentId, uint32_t layerIdToMirror) { std::vector> layers; layers.emplace_back(std::make_unique( createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId, /*mirror=*/layerIdToMirror))); mLifecycleManager.addLayers(std::move(layers)); } void updateBackgroundColor(uint32_t id, half alpha) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged; transactions.back().states.front().state.bgColor.a = alpha; transactions.back().states.front().layerId = id; mLifecycleManager.applyTransactions(transactions); } void destroyLayerHandle(uint32_t id) { mLifecycleManager.onHandlesDestroyed({{id, "test"}}); } void updateAndVerify(LayerHierarchyBuilder& hierarchyBuilder) { hierarchyBuilder.update(mLifecycleManager); mLifecycleManager.commitChanges(); // rebuild layer hierarchy from scratch and verify that it matches the updated state. LayerHierarchyBuilder newBuilder; newBuilder.update(mLifecycleManager); EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), getTraversalPath(newBuilder.getHierarchy())); EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), getTraversalPathInZOrder(newBuilder.getHierarchy())); EXPECT_FALSE( mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)); } std::vector setZTransaction(uint32_t id, int32_t z) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eLayerChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.z = z; return transactions; } void setZ(uint32_t id, int32_t z) { mLifecycleManager.applyTransactions(setZTransaction(id, z)); } void setCrop(uint32_t id, const Rect& crop) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eCropChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.crop = crop; mLifecycleManager.applyTransactions(transactions); } void setFlags(uint32_t id, uint32_t mask, uint32_t flags) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eFlagsChanged; transactions.back().states.front().state.flags = flags; transactions.back().states.front().state.mask = mask; transactions.back().states.front().layerId = id; mLifecycleManager.applyTransactions(transactions); } void setAlpha(uint32_t id, float alpha) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eAlphaChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.color.a = static_cast(alpha); mLifecycleManager.applyTransactions(transactions); } void hideLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden); } void showLayer(uint32_t id) { setFlags(id, layer_state_t::eLayerHidden, 0); } void setColor(uint32_t id, half3 rgb = half3(1._hf, 1._hf, 1._hf)) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eColorChanged; transactions.back().states.front().state.color.rgb = rgb; transactions.back().states.front().layerId = id; mLifecycleManager.applyTransactions(transactions); } void setLayerStack(uint32_t id, int32_t layerStack) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eLayerStackChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.layerStack = ui::LayerStack::fromValue(layerStack); mLifecycleManager.applyTransactions(transactions); } void setTouchableRegion(uint32_t id, Region region) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.windowInfoHandle = sp::make(); auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); inputInfo->touchableRegion = region; inputInfo->token = sp::make(); mLifecycleManager.applyTransactions(transactions); } void setInputInfo(uint32_t id, std::function configureInput) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.windowInfoHandle = sp::make(); auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); if (!inputInfo->token) { inputInfo->token = sp::make(); } configureInput(*inputInfo); mLifecycleManager.applyTransactions(transactions); } void setTouchableRegionCrop(uint32_t id, Region region, uint32_t touchCropId, bool replaceTouchableRegionWithCrop) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eInputInfoChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.windowInfoHandle = sp::make(); auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo(); inputInfo->touchableRegion = region; inputInfo->replaceTouchableRegionWithCrop = replaceTouchableRegionWithCrop; transactions.back().states.front().touchCropId = touchCropId; inputInfo->token = sp::make(); mLifecycleManager.applyTransactions(transactions); } void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eBackgroundBlurRadiusChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.backgroundBlurRadius = backgroundBlurRadius; mLifecycleManager.applyTransactions(transactions); } void setFrameRateSelectionPriority(uint32_t id, int32_t priority) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eFrameRateSelectionPriority; transactions.back().states.front().layerId = id; transactions.back().states.front().state.frameRateSelectionPriority = priority; mLifecycleManager.applyTransactions(transactions); } void setFrameRate(uint32_t id, float frameRate, int8_t compatibility, int8_t changeFrameRateStrategy) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eFrameRateChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.frameRate = frameRate; transactions.back().states.front().state.frameRateCompatibility = compatibility; transactions.back().states.front().state.changeFrameRateStrategy = changeFrameRateStrategy; mLifecycleManager.applyTransactions(transactions); } void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eFrameRateCategoryChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.frameRateCategory = frameRateCategory; mLifecycleManager.applyTransactions(transactions); } void setFrameRateSelectionStrategy(uint32_t id, int8_t strategy) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eFrameRateSelectionStrategyChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.frameRateSelectionStrategy = strategy; mLifecycleManager.applyTransactions(transactions); } void setDefaultFrameRateCompatibility(uint32_t id, int8_t defaultFrameRateCompatibility) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eDefaultFrameRateCompatibilityChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.defaultFrameRateCompatibility = defaultFrameRateCompatibility; mLifecycleManager.applyTransactions(transactions); } void setRoundedCorners(uint32_t id, float radius) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eCornerRadiusChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.cornerRadius = radius; mLifecycleManager.applyTransactions(transactions); } void setBuffer(uint32_t id, std::shared_ptr texture) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eBufferChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().externalTexture = texture; transactions.back().states.front().state.bufferData = std::make_shared(texture->getId(), texture->getWidth(), texture->getHeight(), texture->getPixelFormat(), texture->getUsage()); mLifecycleManager.applyTransactions(transactions); } void setBuffer(uint32_t id) { static uint64_t sBufferId = 1; setBuffer(id, std::make_shared(1U /*width*/, 1U /*height*/, sBufferId++, HAL_PIXEL_FORMAT_RGBA_8888, GRALLOC_USAGE_PROTECTED /*usage*/)); } void setBufferCrop(uint32_t id, const Rect& bufferCrop) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eBufferCropChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.bufferCrop = bufferCrop; mLifecycleManager.applyTransactions(transactions); } void setDamageRegion(uint32_t id, const Region& damageRegion) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eSurfaceDamageRegionChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.surfaceDamageRegion = damageRegion; mLifecycleManager.applyTransactions(transactions); } void setDataspace(uint32_t id, ui::Dataspace dataspace) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eDataspaceChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.dataspace = dataspace; mLifecycleManager.applyTransactions(transactions); } void setMatrix(uint32_t id, float dsdx, float dtdx, float dtdy, float dsdy) { layer_state_t::matrix22_t matrix{dsdx, dtdx, dtdy, dsdy}; std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eMatrixChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.matrix = matrix; mLifecycleManager.applyTransactions(transactions); } void setShadowRadius(uint32_t id, float shadowRadius) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eShadowRadiusChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.shadowRadius = shadowRadius; mLifecycleManager.applyTransactions(transactions); } void setTrustedOverlay(uint32_t id, gui::TrustedOverlay trustedOverlay) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eTrustedOverlayChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.trustedOverlay = trustedOverlay; mLifecycleManager.applyTransactions(transactions); } void setDropInputMode(uint32_t id, gui::DropInputMode dropInputMode) { std::vector transactions; transactions.emplace_back(); transactions.back().states.push_back({}); transactions.back().states.front().state.what = layer_state_t::eDropInputModeChanged; transactions.back().states.front().layerId = id; transactions.back().states.front().state.dropInputMode = dropInputMode; mLifecycleManager.applyTransactions(transactions); } LayerLifecycleManager mLifecycleManager; }; class LayerSnapshotTestBase : public LayerHierarchyTestBase { protected: LayerSnapshotTestBase() : LayerHierarchyTestBase() {} void createRootLayer(uint32_t id) override { LayerHierarchyTestBase::createRootLayer(id); setColor(id); } void createLayer(uint32_t id, uint32_t parentId) override { LayerHierarchyTestBase::createLayer(id, parentId); setColor(parentId); } void mirrorLayer(uint32_t id, uint32_t parent, uint32_t layerToMirror) override { LayerHierarchyTestBase::mirrorLayer(id, parent, layerToMirror); setColor(id); } void update(LayerSnapshotBuilder& snapshotBuilder) { mHierarchyBuilder.update(mLifecycleManager); LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(), .layerLifecycleManager = mLifecycleManager, .includeMetadata = false, .displays = mFrontEndDisplayInfos, .displayChanges = mHasDisplayChanges, .globalShadowSettings = globalShadowSettings, .supportsBlur = true, .supportedLayerGenericMetadata = {}, .genericLayerMetadataKeyMap = {}}; snapshotBuilder.update(args); mLifecycleManager.commitChanges(); } LayerHierarchyBuilder mHierarchyBuilder; DisplayInfos mFrontEndDisplayInfos; bool mHasDisplayChanges = false; ShadowSettings globalShadowSettings; }; } // namespace android::surfaceflinger::frontend