blob: 1898f43dccaf566f036217de8013fa26b8eba002 [file] [log] [blame]
/*
* 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gui/fake/BufferData.h>
#include "Client.h" // temporarily needed for LayerCreationArgs
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/LayerHierarchy.h"
#include "FrontEnd/LayerLifecycleManager.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<uint32_t> getTraversalPath(const LayerHierarchy& hierarchy) const {
std::vector<uint32_t> layerIds;
hierarchy.traverse([&layerIds = layerIds](const LayerHierarchy& hierarchy,
const LayerHierarchy::TraversalPath&) -> bool {
layerIds.emplace_back(hierarchy.getLayer()->id);
return true;
});
return layerIds;
}
std::vector<uint32_t> getTraversalPathInZOrder(const LayerHierarchy& hierarchy) const {
std::vector<uint32_t> 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<std::unique_ptr<RequestedLayerState>> layers;
layers.emplace_back(std::make_unique<RequestedLayerState>(
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<std::unique_ptr<RequestedLayerState>> layers;
layers.emplace_back(std::make_unique<RequestedLayerState>(
createDisplayMirrorArgs(/*id=*/id, layerStack)));
mLifecycleManager.addLayers(std::move(layers));
}
virtual void createLayer(uint32_t id, uint32_t parentId) {
std::vector<std::unique_ptr<RequestedLayerState>> layers;
layers.emplace_back(std::make_unique<RequestedLayerState>(
createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId,
/*mirror=*/UNASSIGNED_LAYER_ID)));
mLifecycleManager.addLayers(std::move(layers));
}
std::vector<TransactionState> reparentLayerTransaction(uint32_t id, uint32_t newParentId) {
std::vector<TransactionState> 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<TransactionState> relativeLayerTransaction(uint32_t id, uint32_t relativeParentId) {
std::vector<TransactionState> 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<TransactionState> 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);
}
virtual void mirrorLayer(uint32_t id, uint32_t parentId, uint32_t layerIdToMirror) {
std::vector<std::unique_ptr<RequestedLayerState>> layers;
layers.emplace_back(std::make_unique<RequestedLayerState>(
createArgs(/*id=*/id, /*canBeRoot=*/false, /*parent=*/parentId,
/*mirror=*/layerIdToMirror)));
mLifecycleManager.addLayers(std::move(layers));
}
void updateBackgroundColor(uint32_t id, half alpha) {
std::vector<TransactionState> 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) {
if (mLifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy)) {
hierarchyBuilder.update(mLifecycleManager.getLayers(),
mLifecycleManager.getDestroyedLayers());
}
mLifecycleManager.commitChanges();
// rebuild layer hierarchy from scratch and verify that it matches the updated state.
LayerHierarchyBuilder newBuilder(mLifecycleManager.getLayers());
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<TransactionState> setZTransaction(uint32_t id, int32_t z) {
std::vector<TransactionState> 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<TransactionState> 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<TransactionState> 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<TransactionState> 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<half>(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<TransactionState> 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<TransactionState> 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<TransactionState> 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<gui::WindowInfoHandle>::make();
auto inputInfo = transactions.back().states.front().state.windowInfoHandle->editInfo();
inputInfo->touchableRegion = region;
inputInfo->token = sp<BBinder>::make();
mLifecycleManager.applyTransactions(transactions);
}
void setTouchableRegionCrop(uint32_t id, Region region, uint32_t touchCropId,
bool replaceTouchableRegionWithCrop) {
std::vector<TransactionState> 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<gui::WindowInfoHandle>::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<BBinder>::make();
mLifecycleManager.applyTransactions(transactions);
}
void setBackgroundBlurRadius(uint32_t id, uint32_t backgroundBlurRadius) {
std::vector<TransactionState> 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<TransactionState> 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<TransactionState> 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<TransactionState> 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<TransactionState> 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 setRoundedCorners(uint32_t id, float radius) {
std::vector<TransactionState> 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<renderengine::ExternalTexture> texture) {
std::vector<TransactionState> 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<fake::BufferData>(texture->getId(), texture->getWidth(),
texture->getHeight(), texture->getPixelFormat(),
texture->getUsage());
mLifecycleManager.applyTransactions(transactions);
}
void setBufferCrop(uint32_t id, const Rect& bufferCrop) {
std::vector<TransactionState> 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 setDataspace(uint32_t id, ui::Dataspace dataspace) {
std::vector<TransactionState> 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 setShadowRadius(uint32_t id, float shadowRadius) {
std::vector<TransactionState> 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);
}
LayerLifecycleManager mLifecycleManager;
};
} // namespace android::surfaceflinger::frontend