Merge "Native runtime sensors direct connection support." into udc-dev
diff --git a/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp
index 99bf6ba..46fb068 100644
--- a/libs/gui/Choreographer.cpp
+++ b/libs/gui/Choreographer.cpp
@@ -15,8 +15,10 @@
*/
// #define LOG_NDEBUG 0
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <gui/Choreographer.h>
+#include <gui/TraceUtils.h>
#include <jni.h>
#undef LOG_TAG
@@ -297,6 +299,8 @@
mLastVsyncEventData = vsyncEventData;
for (const auto& cb : callbacks) {
if (cb.vsyncCallback != nullptr) {
+ ATRACE_FORMAT("AChoreographer_vsyncCallback %" PRId64,
+ vsyncEventData.preferredVsyncId());
const ChoreographerFrameCallbackDataImpl frameCallbackData =
createFrameCallbackData(timestamp);
registerStartTime();
@@ -306,8 +310,10 @@
cb.data);
mInCallback = false;
} else if (cb.callback64 != nullptr) {
+ ATRACE_FORMAT("AChoreographer_frameCallback64");
cb.callback64(timestamp, cb.data);
} else if (cb.callback != nullptr) {
+ ATRACE_FORMAT("AChoreographer_frameCallback");
cb.callback(timestamp, cb.data);
}
}
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index f6bba16..b391337 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -74,7 +74,7 @@
surfaceDamageRegion(),
api(-1),
colorTransform(mat4()),
- bgColorAlpha(0),
+ bgColor(0),
bgColorDataspace(ui::Dataspace::UNKNOWN),
colorSpaceAgnostic(false),
shadowRadius(0.0f),
@@ -140,7 +140,10 @@
SAFE_PARCEL(output.writeFloat, cornerRadius);
SAFE_PARCEL(output.writeUint32, backgroundBlurRadius);
SAFE_PARCEL(output.writeParcelable, metadata);
- SAFE_PARCEL(output.writeFloat, bgColorAlpha);
+ SAFE_PARCEL(output.writeFloat, bgColor.r);
+ SAFE_PARCEL(output.writeFloat, bgColor.g);
+ SAFE_PARCEL(output.writeFloat, bgColor.b);
+ SAFE_PARCEL(output.writeFloat, bgColor.a);
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(bgColorDataspace));
SAFE_PARCEL(output.writeBool, colorSpaceAgnostic);
SAFE_PARCEL(output.writeVectorSize, listeners);
@@ -259,7 +262,14 @@
SAFE_PARCEL(input.readUint32, &backgroundBlurRadius);
SAFE_PARCEL(input.readParcelable, &metadata);
- SAFE_PARCEL(input.readFloat, &bgColorAlpha);
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ bgColor.r = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ bgColor.g = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ bgColor.b = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ bgColor.a = tmpFloat;
SAFE_PARCEL(input.readUint32, &tmpUint32);
bgColorDataspace = static_cast<ui::Dataspace>(tmpUint32);
SAFE_PARCEL(input.readBool, &colorSpaceAgnostic);
@@ -618,8 +628,7 @@
}
if (other.what & eBackgroundColorChanged) {
what |= eBackgroundColorChanged;
- color.rgb = other.color.rgb;
- bgColorAlpha = other.bgColorAlpha;
+ bgColor = other.bgColor;
bgColorDataspace = other.bgColorDataspace;
}
if (other.what & eMetadataChanged) {
@@ -752,7 +761,7 @@
CHECK_DIFF(diff, eColorTransformChanged, other, colorTransform);
if (other.what & eHasListenerCallbacksChanged) diff |= eHasListenerCallbacksChanged;
if (other.what & eInputInfoChanged) diff |= eInputInfoChanged;
- CHECK_DIFF3(diff, eBackgroundColorChanged, other, color.rgb, bgColorAlpha, bgColorDataspace);
+ CHECK_DIFF2(diff, eBackgroundColorChanged, other, bgColor, bgColorDataspace);
if (other.what & eMetadataChanged) diff |= eMetadataChanged;
CHECK_DIFF(diff, eShadowRadiusChanged, other, shadowRadius);
CHECK_DIFF3(diff, eRenderBorderChanged, other, borderEnabled, borderWidth, borderColor);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 001d475..0f138ca 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1560,8 +1560,8 @@
}
s->what |= layer_state_t::eBackgroundColorChanged;
- s->color.rgb = color;
- s->bgColorAlpha = alpha;
+ s->bgColor.rgb = color;
+ s->bgColor.a = alpha;
s->bgColorDataspace = dataspace;
registerSurfaceControlForCallback(sc);
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index da144bd..29fb989 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -226,9 +226,9 @@
bool hasBufferChanges() const;
// Layer hierarchy updates.
- static constexpr uint64_t HIERARCHY_CHANGES = layer_state_t::eBackgroundColorChanged |
- layer_state_t::eLayerChanged | layer_state_t::eRelativeLayerChanged |
- layer_state_t::eReparent;
+ static constexpr uint64_t HIERARCHY_CHANGES = layer_state_t::eLayerChanged |
+ layer_state_t::eRelativeLayerChanged | layer_state_t::eReparent |
+ layer_state_t::eLayerStackChanged;
// Geometry updates.
static constexpr uint64_t GEOMETRY_CHANGES = layer_state_t::eBufferCropChanged |
@@ -264,9 +264,8 @@
static constexpr uint64_t AFFECTS_CHILDREN = layer_state_t::GEOMETRY_CHANGES |
layer_state_t::HIERARCHY_CHANGES | layer_state_t::eAlphaChanged |
layer_state_t::eColorTransformChanged | layer_state_t::eCornerRadiusChanged |
- layer_state_t::eFlagsChanged | layer_state_t::eLayerStackChanged |
- layer_state_t::eTrustedOverlayChanged | layer_state_t::eFrameRateChanged |
- layer_state_t::eFixedTransformHintChanged;
+ layer_state_t::eFlagsChanged | layer_state_t::eTrustedOverlayChanged |
+ layer_state_t::eFrameRateChanged | layer_state_t::eFixedTransformHintChanged;
// Changes affecting data sent to input.
static constexpr uint64_t INPUT_CHANGES = layer_state_t::GEOMETRY_CHANGES |
@@ -333,7 +332,7 @@
// The following refer to the alpha, and dataspace, respectively of
// the background color layer
- float bgColorAlpha;
+ half4 bgColor;
ui::Dataspace bgColorDataspace;
// A color space agnostic layer means the color of this layer can be
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 8d99f3d..936e316 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -444,8 +444,11 @@
ALOGD("Trying to create Vk device with protectedContent=%d (success)", protectedContent);
VkQueue graphicsQueue;
- VK_GET_DEV_PROC(device, GetDeviceQueue);
- vkGetDeviceQueue(device, graphicsQueueIndex, 0, &graphicsQueue);
+ VK_GET_DEV_PROC(device, GetDeviceQueue2);
+ const VkDeviceQueueInfo2 deviceQueueInfo2 = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2, nullptr,
+ deviceQueueCreateFlags,
+ (uint32_t)graphicsQueueIndex, 0};
+ vkGetDeviceQueue2(device, &deviceQueueInfo2, &graphicsQueue);
VK_GET_DEV_PROC(device, DeviceWaitIdle);
VK_GET_DEV_PROC(device, DestroyDevice);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 0b4d20c..eae5871 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -213,9 +213,7 @@
float currentSdrHdrRatio = 1.f;
float desiredSdrHdrRatio = 1.f;
- bool isInternalDisplayOverlay = false;
gui::CachingHint cachingHint = gui::CachingHint::Enabled;
-
virtual ~LayerFECompositionState();
// Debugging
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 7d94316..175dd1d 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -538,8 +538,8 @@
return;
}
- bool computeAboveCoveredExcludingOverlays =
- coverage.aboveCoveredLayersExcludingOverlays && !layerFEState->isInternalDisplayOverlay;
+ bool computeAboveCoveredExcludingOverlays = coverage.aboveCoveredLayersExcludingOverlays &&
+ !layerFEState->outputFilter.toInternalDisplay;
/*
* opaqueRegion: area of a surface that is fully opaque.
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
index 6d492c0..6659825 100644
--- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
@@ -24,9 +24,13 @@
std::atomic<uint32_t> LayerCreationArgs::sSequence{1};
+uint32_t LayerCreationArgs::getInternalLayerId(uint32_t id) {
+ return id | INTERNAL_LAYER_PREFIX;
+}
+
LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, sp<Client> client, std::string name,
uint32_t flags, gui::LayerMetadata metadataArg,
- std::optional<uint32_t> id)
+ std::optional<uint32_t> id, bool internalLayer)
: flinger(flinger),
client(std::move(client)),
name(std::move(name)),
@@ -46,10 +50,15 @@
if (id) {
sequence = *id;
- sSequence = *id + 1;
+ if (internalLayer) {
+ sequence = getInternalLayerId(*id);
+ } else {
+ sSequence = *id + 1;
+ }
} else {
sequence = sSequence++;
- if (sequence == UNASSIGNED_LAYER_ID) {
+ if (sequence >= INTERNAL_LAYER_PREFIX) {
+ sSequence = 1;
ALOGW("Layer sequence id rolled over.");
sequence = sSequence++;
}
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
index 9d2aaab..2cd6b55 100644
--- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
@@ -25,6 +25,7 @@
#include <optional>
constexpr uint32_t UNASSIGNED_LAYER_ID = std::numeric_limits<uint32_t>::max();
+constexpr uint32_t INTERNAL_LAYER_PREFIX = 1u << 31;
namespace android {
class SurfaceFlinger;
@@ -35,10 +36,11 @@
struct LayerCreationArgs {
static std::atomic<uint32_t> sSequence;
+ static uint32_t getInternalLayerId(uint32_t id);
LayerCreationArgs(android::SurfaceFlinger*, sp<android::Client>, std::string name,
- uint32_t flags, gui::LayerMetadata,
- std::optional<uint32_t> id = std::nullopt);
+ uint32_t flags, gui::LayerMetadata, std::optional<uint32_t> id = std::nullopt,
+ bool internalLayer = false);
LayerCreationArgs(const LayerCreationArgs&);
android::SurfaceFlinger* flinger;
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index afe557e..c30465f 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -130,6 +130,14 @@
return mLayer;
}
+const LayerHierarchy* LayerHierarchy::getRelativeParent() const {
+ return mRelativeParent;
+}
+
+const LayerHierarchy* LayerHierarchy::getParent() const {
+ return mParent;
+}
+
std::string LayerHierarchy::getDebugStringShort() const {
std::string debug = "LayerHierarchy{";
debug += ((mLayer) ? mLayer->getDebugString() : "root") + " ";
@@ -449,7 +457,7 @@
traversalPath.id = layerId;
traversalPath.variant = variant;
if (variant == LayerHierarchy::Variant::Mirror) {
- traversalPath.mirrorRootId = layerId;
+ traversalPath.mirrorRootId = mParentPath.id;
} else if (variant == LayerHierarchy::Variant::Relative) {
if (std::find(traversalPath.relativeRootIds.begin(), traversalPath.relativeRootIds.end(),
layerId) != traversalPath.relativeRootIds.end()) {
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index 2ab897b..3dd89ba 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -128,16 +128,24 @@
// Traverse the hierarchy and visit all child variants.
void traverse(const Visitor& visitor) const {
TraversalPath root = TraversalPath::ROOT;
+ if (mLayer) {
+ root.id = mLayer->id;
+ }
traverse(visitor, root);
}
// Traverse the hierarchy in z-order, skipping children that have relative parents.
void traverseInZOrder(const Visitor& visitor) const {
TraversalPath root = TraversalPath::ROOT;
+ if (mLayer) {
+ root.id = mLayer->id;
+ }
traverseInZOrder(visitor, root);
}
const RequestedLayerState* getLayer() const;
+ const LayerHierarchy* getRelativeParent() const;
+ const LayerHierarchy* getParent() const;
std::string getDebugString(const char* prefix = "") const;
std::string getDebugStringShort() const;
// Traverse the hierarchy and return true if loops are found. The outInvalidRelativeRoot
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index 66197be..360a0a9 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -37,7 +37,6 @@
mGlobalChanges |= RequestedLayerState::Changes::Hierarchy;
for (auto& newLayer : newLayers) {
RequestedLayerState& layer = *newLayer.get();
- LLOGV(layer.id, "%s layer %s", __func__, layer.getDebugStringShort().c_str());
auto [it, inserted] = mIdToLayer.try_emplace(layer.id, References{.owner = layer});
if (!inserted) {
LOG_ALWAYS_FATAL("Duplicate layer id %d found. Existing layer: %s", layer.id,
@@ -68,6 +67,7 @@
if (layer.isRoot()) {
updateDisplayMirrorLayers(layer);
}
+ LLOGV(layer.id, "%s", layer.getDebugString().c_str());
mLayers.emplace_back(std::move(newLayer));
}
}
@@ -81,6 +81,7 @@
continue;
}
RequestedLayerState& layer = it->second.owner;
+ LLOGV(layer.id, "%s", layer.getDebugString().c_str());
layer.handleAlive = false;
if (!layer.canBeDestroyed()) {
continue;
@@ -148,7 +149,7 @@
while (it != mLayers.end()) {
RequestedLayerState* layer = it->get();
if (layer->changes.test(RequestedLayerState::Changes::Destroyed)) {
- LLOGV(layer->id, "destroyed layer %s", layer->getDebugStringShort().c_str());
+ LLOGV(layer->id, "destroyed %s", layer->getDebugStringShort().c_str());
std::iter_swap(it, mLayers.end() - 1);
mDestroyedLayers.emplace_back(std::move(mLayers.back()));
if (it == mLayers.end() - 1) {
@@ -192,35 +193,38 @@
layer->merge(resolvedComposerState);
if (layer->what & layer_state_t::eBackgroundColorChanged) {
- if (layer->bgColorLayerId == UNASSIGNED_LAYER_ID && layer->bgColorAlpha != 0) {
+ if (layer->bgColorLayerId == UNASSIGNED_LAYER_ID && layer->bgColor.a != 0) {
LayerCreationArgs backgroundLayerArgs{nullptr,
nullptr,
layer->name + "BackgroundColorLayer",
ISurfaceComposerClient::eFXSurfaceEffect,
- {}};
+ {},
+ layer->id,
+ /*internalLayer=*/true};
std::vector<std::unique_ptr<RequestedLayerState>> newLayers;
newLayers.emplace_back(
std::make_unique<RequestedLayerState>(backgroundLayerArgs));
RequestedLayerState* backgroundLayer = newLayers.back().get();
+ backgroundLayer->bgColorLayer = true;
backgroundLayer->handleAlive = false;
backgroundLayer->parentId = layer->id;
backgroundLayer->z = std::numeric_limits<int32_t>::min();
- backgroundLayer->color.rgb = layer->color.rgb;
- backgroundLayer->color.a = layer->bgColorAlpha;
+ backgroundLayer->color = layer->bgColor;
backgroundLayer->dataspace = layer->bgColorDataspace;
-
layer->bgColorLayerId = backgroundLayer->id;
addLayers({std::move(newLayers)});
- } else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID &&
- layer->bgColorAlpha == 0) {
+ } else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID && layer->bgColor.a == 0) {
RequestedLayerState* bgColorLayer = getLayerFromId(layer->bgColorLayerId);
- bgColorLayer->parentId = UNASSIGNED_LAYER_ID;
- onHandlesDestroyed({layer->bgColorLayerId});
+ layer->bgColorLayerId = UNASSIGNED_LAYER_ID;
+ bgColorLayer->parentId = unlinkLayer(bgColorLayer->parentId, bgColorLayer->id);
+ onHandlesDestroyed({bgColorLayer->id});
} else if (layer->bgColorLayerId != UNASSIGNED_LAYER_ID) {
RequestedLayerState* bgColorLayer = getLayerFromId(layer->bgColorLayerId);
- bgColorLayer->color.rgb = layer->color.rgb;
- bgColorLayer->color.a = layer->bgColorAlpha;
+ bgColorLayer->color = layer->bgColor;
bgColorLayer->dataspace = layer->bgColorDataspace;
+ bgColorLayer->what |= layer_state_t::eColorChanged |
+ layer_state_t::eDataspaceChanged | layer_state_t::eAlphaChanged;
+ bgColorLayer->changes |= RequestedLayerState::Changes::Content;
mGlobalChanges |= RequestedLayerState::Changes::Content;
}
}
@@ -256,8 +260,7 @@
listener->onLayerAdded(*layer);
}
}
- layer->what = 0;
- layer->changes.clear();
+ layer->clearChanges();
}
for (auto& destroyedLayer : mDestroyedLayers) {
diff --git a/services/surfaceflinger/FrontEnd/LayerLog.h b/services/surfaceflinger/FrontEnd/LayerLog.h
index 47e1e30..4943483 100644
--- a/services/surfaceflinger/FrontEnd/LayerLog.h
+++ b/services/surfaceflinger/FrontEnd/LayerLog.h
@@ -25,3 +25,5 @@
#else
#define LLOGV(LAYER_ID, x, ...) ALOGV("[%d] %s " x, (LAYER_ID), __func__, ##__VA_ARGS__);
#endif
+
+#define LLOGD(LAYER_ID, x, ...) ALOGD("[%d] %s " x, (LAYER_ID), __func__, ##__VA_ARGS__);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index dbb7fbf..8a45093 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -27,14 +27,22 @@
LayerSnapshot::LayerSnapshot(const RequestedLayerState& state,
const LayerHierarchy::TraversalPath& path)
: path(path) {
+ static uint32_t sUniqueSequenceId = 0;
+ // Provide a unique id for clones otherwise keeping using the sequence id.
+ // The seq id can still be useful for debugging if its available.
+ uniqueSequence = (path.isClone()) ? sUniqueSequenceId++ : state.id;
sequence = static_cast<int32_t>(state.id);
name = state.name;
textureName = state.textureName;
premultipliedAlpha = state.premultipliedAlpha;
inputInfo.name = state.name;
- inputInfo.id = static_cast<int32_t>(state.id);
+ inputInfo.id = static_cast<int32_t>(uniqueSequence);
inputInfo.ownerUid = static_cast<int32_t>(state.ownerUid);
inputInfo.ownerPid = state.ownerPid;
+ changes = RequestedLayerState::Changes::Created;
+ mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror
+ ? path
+ : LayerHierarchy::TraversalPath::ROOT;
}
// As documented in libhardware header, formats in the range
@@ -139,7 +147,8 @@
// visible
std::stringstream reason;
if (sidebandStream != nullptr) reason << " sidebandStream";
- if (externalTexture != nullptr) reason << " buffer";
+ if (externalTexture != nullptr)
+ reason << " buffer:" << externalTexture->getId() << " frame:" << frameNumber;
if (fillsColor() || color.a > 0.0f) reason << " color{" << color << "}";
if (drawShadows()) reason << " shadowSettings.length=" << shadowSettings.length;
if (backgroundBlurRadius > 0) reason << " backgroundBlurRadius=" << backgroundBlurRadius;
@@ -164,7 +173,8 @@
std::string LayerSnapshot::getDebugString() const {
std::stringstream debug;
debug << "Snapshot{" << path.toString() << name << " isVisible=" << isVisible << " {"
- << getIsVisibleReason() << "} changes=" << changes.string() << "}";
+ << getIsVisibleReason() << "} changes=" << changes.string()
+ << " layerStack=" << outputFilter.layerStack.id << "}";
return debug.str();
}
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 5d74203..e069a63 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -57,6 +57,12 @@
bool isHiddenByPolicyFromParent = false;
bool isHiddenByPolicyFromRelativeParent = false;
ftl::Flags<RequestedLayerState::Changes> changes;
+ // Some consumers of this snapshot (input, layer traces) rely on each snapshot to be unique.
+ // For mirrored layers, snapshots will have the same sequence so this unique id provides
+ // an alternative identifier when needed.
+ uint32_t uniqueSequence;
+ // Layer id used to create this snapshot. Multiple snapshots will have the same sequence if they
+ // generated from the same layer, for example when mirroring.
int32_t sequence;
std::string name;
uint32_t textureName;
@@ -84,6 +90,8 @@
scheduler::LayerInfo::FrameRate frameRate;
ui::Transform::RotationFlags fixedTransformHint;
bool handleSkipScreenshotFlag = false;
+ LayerHierarchy::TraversalPath mirrorRootPath;
+ bool unreachable = true;
ChildState childState;
static bool isOpaqueFormat(PixelFormat format);
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index d740350..344dab4 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -296,6 +296,26 @@
gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
}
+void updateMetadata(LayerSnapshot& snapshot, const RequestedLayerState& requested,
+ const LayerSnapshotBuilder::Args& args) {
+ snapshot.metadata.clear();
+ for (const auto& [key, mandatory] : args.supportedLayerGenericMetadata) {
+ auto compatIter = args.genericLayerMetadataKeyMap.find(key);
+ if (compatIter == std::end(args.genericLayerMetadataKeyMap)) {
+ continue;
+ }
+ const uint32_t id = compatIter->second;
+ auto it = requested.metadata.mMap.find(id);
+ if (it == std::end(requested.metadata.mMap)) {
+ continue;
+ }
+
+ snapshot.metadata.emplace(key,
+ compositionengine::GenericLayerMetadataEntry{mandatory,
+ it->second});
+ }
+}
+
void clearChanges(LayerSnapshot& snapshot) {
snapshot.changes.clear();
snapshot.contentDirty = false;
@@ -308,6 +328,7 @@
LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
LayerSnapshot snapshot;
+ snapshot.path = LayerHierarchy::TraversalPath::ROOT;
snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
snapshot.isHiddenByPolicyFromParent = false;
snapshot.isHiddenByPolicyFromRelativeParent = false;
@@ -337,21 +358,17 @@
LayerSnapshotBuilder::LayerSnapshotBuilder() : mRootSnapshot(getRootSnapshot()) {}
LayerSnapshotBuilder::LayerSnapshotBuilder(Args args) : LayerSnapshotBuilder() {
- args.forceUpdate = true;
+ args.forceUpdate = ForceUpdateFlags::ALL;
updateSnapshots(args);
}
bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
- if (args.forceUpdate || args.displayChanges) {
+ if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) {
// force update requested, or we have display changes, so skip the fast path
return false;
}
if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
- // there are no changes, so just clear the change flags from before.
- for (auto& snapshot : mSnapshots) {
- clearChanges(*snapshot);
- }
return true;
}
@@ -376,14 +393,12 @@
// Walk through the snapshots, clearing previous change flags and updating the snapshots
// if needed.
for (auto& snapshot : mSnapshots) {
- clearChanges(*snapshot);
auto it = layersWithChanges.find(snapshot->path.id);
if (it != layersWithChanges.end()) {
ALOGV("%s fast path snapshot changes = %s", __func__,
mRootSnapshot.changes.string().c_str());
LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
- updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root,
- /*newSnapshot=*/false);
+ updateSnapshot(*snapshot, args, *it->second, mRootSnapshot, root);
}
}
return true;
@@ -393,37 +408,45 @@
ATRACE_NAME("UpdateSnapshots");
if (args.parentCrop) {
mRootSnapshot.geomLayerBounds = *args.parentCrop;
- } else if (args.forceUpdate || args.displayChanges) {
+ } else if (args.forceUpdate == ForceUpdateFlags::ALL || args.displayChanges) {
mRootSnapshot.geomLayerBounds = getMaxDisplayBounds(args.displays);
}
if (args.displayChanges) {
mRootSnapshot.changes = RequestedLayerState::Changes::AffectsChildren |
RequestedLayerState::Changes::Geometry;
}
+ if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
+ mRootSnapshot.changes |=
+ RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
+ }
LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
- for (auto& [childHierarchy, variant] : args.root.mChildren) {
- LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
- childHierarchy->getLayer()->id,
- variant);
- updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot);
+ if (args.root.getLayer()) {
+ // The hierarchy can have a root layer when used for screenshots otherwise, it will have
+ // multiple children.
+ LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root, args.root.getLayer()->id,
+ LayerHierarchy::Variant::Attached);
+ updateSnapshotsInHierarchy(args, args.root, root, mRootSnapshot);
+ } else {
+ for (auto& [childHierarchy, variant] : args.root.mChildren) {
+ LayerHierarchy::ScopedAddToTraversalPath addChildToPath(root,
+ childHierarchy->getLayer()->id,
+ variant);
+ updateSnapshotsInHierarchy(args, *childHierarchy, root, mRootSnapshot);
+ }
}
- sortSnapshotsByZ(args);
+ const bool hasUnreachableSnapshots = sortSnapshotsByZ(args);
clearChanges(mRootSnapshot);
// Destroy unreachable snapshots
- if (args.layerLifecycleManager.getDestroyedLayers().empty()) {
+ if (!hasUnreachableSnapshots) {
return;
}
- std::unordered_set<uint32_t> destroyedLayerIds;
- for (auto& destroyedLayer : args.layerLifecycleManager.getDestroyedLayers()) {
- destroyedLayerIds.emplace(destroyedLayer->id);
- }
auto it = mSnapshots.begin();
while (it < mSnapshots.end()) {
auto& traversalPath = it->get()->path;
- if (destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
+ if (!it->get()->unreachable) {
it++;
continue;
}
@@ -436,6 +459,10 @@
}
void LayerSnapshotBuilder::update(const Args& args) {
+ for (auto& snapshot : mSnapshots) {
+ clearChanges(*snapshot);
+ }
+
if (tryFastUpdate(args)) {
return;
}
@@ -449,8 +476,9 @@
LayerSnapshot* snapshot = getSnapshot(traversalPath);
const bool newSnapshot = snapshot == nullptr;
if (newSnapshot) {
- snapshot = createSnapshot(traversalPath, *layer);
+ snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
}
+ scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
if (traversalPath.isRelative()) {
bool parentIsRelative = traversalPath.variant == LayerHierarchy::Variant::Relative;
updateRelativeState(*snapshot, parentSnapshot, parentIsRelative, args);
@@ -458,7 +486,7 @@
if (traversalPath.isAttached()) {
resetRelativeState(*snapshot);
}
- updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath, newSnapshot);
+ updateSnapshot(*snapshot, args, *layer, parentSnapshot, traversalPath);
}
for (auto& [childHierarchy, variant] : hierarchy.mChildren) {
@@ -469,6 +497,10 @@
updateSnapshotsInHierarchy(args, *childHierarchy, traversalPath, *snapshot);
updateChildState(*snapshot, childSnapshot, args);
}
+
+ if (oldFrameRate == snapshot->frameRate) {
+ snapshot->changes.clear(RequestedLayerState::Changes::FrameRate);
+ }
return *snapshot;
}
@@ -485,27 +517,34 @@
return it == mIdToSnapshot.end() ? nullptr : it->second;
}
-LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& id,
- const RequestedLayerState& layer) {
- mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, id));
+LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
+ const RequestedLayerState& layer,
+ const LayerSnapshot& parentSnapshot) {
+ mSnapshots.emplace_back(std::make_unique<LayerSnapshot>(layer, path));
LayerSnapshot* snapshot = mSnapshots.back().get();
snapshot->globalZ = static_cast<size_t>(mSnapshots.size()) - 1;
- mIdToSnapshot[id] = snapshot;
+ if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
+ snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
+ }
+ mIdToSnapshot[path] = snapshot;
return snapshot;
}
-void LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
- if (!mResortSnapshots && !args.forceUpdate &&
+bool LayerSnapshotBuilder::sortSnapshotsByZ(const Args& args) {
+ if (!mResortSnapshots && args.forceUpdate == ForceUpdateFlags::NONE &&
!args.layerLifecycleManager.getGlobalChanges().any(
RequestedLayerState::Changes::Hierarchy |
RequestedLayerState::Changes::Visibility)) {
// We are not force updating and there are no hierarchy or visibility changes. Avoid sorting
// the snapshots.
- return;
+ return false;
}
-
mResortSnapshots = false;
+ for (auto& snapshot : mSnapshots) {
+ snapshot->unreachable = true;
+ }
+
size_t globalZ = 0;
args.root.traverseInZOrder(
[this, &globalZ](const LayerHierarchy&,
@@ -515,11 +554,7 @@
return false;
}
- if (snapshot->isHiddenByPolicy() &&
- !snapshot->changes.test(RequestedLayerState::Changes::Visibility)) {
- return false;
- }
-
+ snapshot->unreachable = false;
if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
updateVisibility(*snapshot, snapshot->getIsVisible());
size_t oldZ = snapshot->globalZ;
@@ -537,12 +572,17 @@
return true;
});
mNumInterestingSnapshots = (int)globalZ;
+ bool hasUnreachableSnapshots = false;
while (globalZ < mSnapshots.size()) {
mSnapshots[globalZ]->globalZ = globalZ;
/* mark unreachable snapshots as explicitly invisible */
updateVisibility(*mSnapshots[globalZ], false);
+ if (mSnapshots[globalZ]->unreachable) {
+ hasUnreachableSnapshots = true;
+ }
globalZ++;
}
+ return hasUnreachableSnapshots;
}
void LayerSnapshotBuilder::updateRelativeState(LayerSnapshot& snapshot,
@@ -569,7 +609,8 @@
if (snapshot.childState.hasValidFrameRate) {
return;
}
- if (args.forceUpdate || childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
+ if (args.forceUpdate == ForceUpdateFlags::ALL ||
+ childSnapshot.changes.test(RequestedLayerState::Changes::FrameRate)) {
// We return whether this layer ot its children has a vote. We ignore ExactOrMultiple votes
// for the same reason we are allowing touch boost for those layers. See
// RefreshRateSelector::rankFrameRates for details.
@@ -612,35 +653,32 @@
void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
const RequestedLayerState& requested,
const LayerSnapshot& parentSnapshot,
- const LayerHierarchy::TraversalPath& path,
- bool newSnapshot) {
+ const LayerHierarchy::TraversalPath& path) {
// Always update flags and visibility
ftl::Flags<RequestedLayerState::Changes> parentChanges = parentSnapshot.changes &
(RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
- RequestedLayerState::Changes::AffectsChildren);
- snapshot.changes = parentChanges | requested.changes;
+ RequestedLayerState::Changes::AffectsChildren |
+ RequestedLayerState::Changes::FrameRate);
+ snapshot.changes |= parentChanges | requested.changes;
snapshot.isHiddenByPolicyFromParent = parentSnapshot.isHiddenByPolicyFromParent ||
parentSnapshot.invalidTransform || requested.isHiddenByPolicy() ||
(args.excludeLayerIds.find(path.id) != args.excludeLayerIds.end());
snapshot.contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
// TODO(b/238781169) scope down the changes to only buffer updates.
- snapshot.hasReadyFrame =
- (snapshot.contentDirty || requested.autoRefresh) && (requested.externalTexture);
- // TODO(b/238781169) how is this used? ag/15523870
- snapshot.sidebandStreamHasFrame = false;
+ snapshot.hasReadyFrame = requested.hasReadyFrame();
+ snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
snapshot.surfaceDamage);
-
- const bool forceUpdate = newSnapshot || args.forceUpdate ||
- snapshot.changes.any(RequestedLayerState::Changes::Visibility |
- RequestedLayerState::Changes::Created);
- snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
- ? parentSnapshot.outputFilter.layerStack
- : requested.layerStack;
+ snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
+ ? requested.layerStack
+ : parentSnapshot.outputFilter.layerStack;
uint32_t displayRotationFlags =
getDisplayRotationFlags(args.displays, snapshot.outputFilter.layerStack);
+ const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
+ snapshot.changes.any(RequestedLayerState::Changes::Visibility |
+ RequestedLayerState::Changes::Created);
// always update the buffer regardless of visibility
if (forceUpdate || requested.what & layer_state_t::BUFFER_CHANGES || args.displayChanges) {
@@ -673,7 +711,8 @@
snapshot.desiredSdrHdrRatio = requested.desiredSdrHdrRatio;
}
- if (snapshot.isHiddenByPolicyFromParent && !newSnapshot) {
+ if (snapshot.isHiddenByPolicyFromParent &&
+ !snapshot.changes.test(RequestedLayerState::Changes::Created)) {
if (forceUpdate ||
snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
RequestedLayerState::Changes::Geometry |
@@ -690,9 +729,6 @@
snapshot.isSecure =
parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
- snapshot.outputFilter.layerStack = requested.parentId != UNASSIGNED_LAYER_ID
- ? parentSnapshot.outputFilter.layerStack
- : requested.layerStack;
snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
(requested.flags & layer_state_t::eLayerSkipScreenshot);
snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
@@ -708,11 +744,6 @@
snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
? requested.gameMode
: parentSnapshot.gameMode;
- snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
- (requested.requestedFrameRate.type ==
- scheduler::LayerInfo::FrameRateCompatibility::NoVote))
- ? requested.requestedFrameRate
- : parentSnapshot.frameRate;
snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
? requested.fixedTransformHint
: parentSnapshot.fixedTransformHint;
@@ -722,6 +753,20 @@
(requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
}
+ if (forceUpdate ||
+ snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
+ RequestedLayerState::Changes::Hierarchy)) {
+ snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
+ (requested.requestedFrameRate.type ==
+ scheduler::LayerInfo::FrameRateCompatibility::NoVote))
+ ? requested.requestedFrameRate
+ : parentSnapshot.frameRate;
+ }
+
+ if (forceUpdate || requested.what & layer_state_t::eMetadataChanged) {
+ updateMetadata(snapshot, requested, args);
+ }
+
if (forceUpdate || requested.changes.get() != 0) {
snapshot.compositionType = requested.getCompositionType();
snapshot.dimmingEnabled = requested.dimmingEnabled;
@@ -765,18 +810,16 @@
}
snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
- snapshot.isOpaque = snapshot.isContentOpaque() && !snapshot.roundedCorner.hasRoundedCorners() &&
+ snapshot.contentOpaque = snapshot.isContentOpaque();
+ snapshot.isOpaque = snapshot.contentOpaque && !snapshot.roundedCorner.hasRoundedCorners() &&
snapshot.color.a == 1.f;
snapshot.blendMode = getBlendMode(snapshot, requested);
- // TODO(b/238781169) pass this from flinger
- // snapshot.fps;
- // snapshot.metadata;
LLOGV(snapshot.sequence,
- "%supdated [%d]%s changes parent:%s global:%s local:%s requested:%s %s from parent %s",
- args.forceUpdate ? "Force " : "", requested.id, requested.name.c_str(),
- parentSnapshot.changes.string().c_str(), snapshot.changes.string().c_str(),
- requested.changes.string().c_str(), std::to_string(requested.what).c_str(),
- snapshot.getDebugString().c_str(), parentSnapshot.getDebugString().c_str());
+ "%supdated %s changes:%s parent:%s requested:%s requested:%s from parent %s",
+ args.forceUpdate == ForceUpdateFlags::ALL ? "Force " : "",
+ snapshot.getDebugString().c_str(), snapshot.changes.string().c_str(),
+ parentSnapshot.changes.string().c_str(), requested.changes.string().c_str(),
+ std::to_string(requested.what).c_str(), parentSnapshot.getDebugString().c_str());
}
void LayerSnapshotBuilder::updateRoundedCorner(LayerSnapshot& snapshot,
@@ -912,8 +955,12 @@
} else {
snapshot.inputInfo = {};
}
- snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
+ snapshot.inputInfo.name = requested.name;
+ snapshot.inputInfo.id = static_cast<int32_t>(snapshot.uniqueSequence);
+ snapshot.inputInfo.ownerUid = static_cast<int32_t>(requested.ownerUid);
+ snapshot.inputInfo.ownerPid = requested.ownerPid;
+ snapshot.inputInfo.displayId = static_cast<int32_t>(snapshot.outputFilter.layerStack.id);
if (!needsInputInfo(snapshot, requested)) {
return;
}
@@ -975,7 +1022,7 @@
// touches from going outside the cloned area.
if (path.isClone()) {
snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::CLONE;
- auto clonedRootSnapshot = getSnapshot(path.getMirrorRoot());
+ auto clonedRootSnapshot = getSnapshot(snapshot.mirrorRootPath);
if (clonedRootSnapshot) {
const Rect rect =
displayInfo.transform.transform(Rect{clonedRootSnapshot->transformedBounds});
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 0902ab8..3997a0a 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -35,10 +35,15 @@
// snapshots when there are only buffer updates.
class LayerSnapshotBuilder {
public:
+ enum class ForceUpdateFlags {
+ NONE,
+ ALL,
+ HIERARCHY,
+ };
struct Args {
LayerHierarchy root;
const LayerLifecycleManager& layerLifecycleManager;
- bool forceUpdate = false;
+ ForceUpdateFlags forceUpdate = ForceUpdateFlags::NONE;
bool includeMetadata = false;
const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays;
// Set to true if there were display changes since last update.
@@ -48,6 +53,8 @@
bool forceFullDamage = false;
std::optional<FloatRect> parentCrop = std::nullopt;
std::unordered_set<uint32_t> excludeLayerIds;
+ const std::unordered_map<std::string, bool>& supportedLayerGenericMetadata;
+ const std::unordered_map<std::string, uint32_t>& genericLayerMetadataKeyMap;
};
LayerSnapshotBuilder();
@@ -92,8 +99,7 @@
LayerHierarchy::TraversalPath& traversalPath,
const LayerSnapshot& parentSnapshot);
void updateSnapshot(LayerSnapshot&, const Args&, const RequestedLayerState&,
- const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath&,
- bool newSnapshot);
+ const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath&);
static void updateRelativeState(LayerSnapshot& snapshot, const LayerSnapshot& parentSnapshot,
bool parentIsRelative, const Args& args);
static void resetRelativeState(LayerSnapshot& snapshot);
@@ -106,9 +112,11 @@
void updateInput(LayerSnapshot& snapshot, const RequestedLayerState& requested,
const LayerSnapshot& parentSnapshot, const LayerHierarchy::TraversalPath& path,
const Args& args);
- void sortSnapshotsByZ(const Args& args);
+ // Return true if there are unreachable snapshots
+ bool sortSnapshotsByZ(const Args& args);
LayerSnapshot* createSnapshot(const LayerHierarchy::TraversalPath& id,
- const RequestedLayerState& layer);
+ const RequestedLayerState& layer,
+ const LayerSnapshot& parentSnapshot);
void updateChildState(LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot,
const Args& args);
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 09523d3..e2cbe28 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -165,8 +165,13 @@
if (hadBufferOrSideStream != hasBufferOrSideStream) {
changes |= RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::VisibleRegion |
- RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Input |
- RequestedLayerState::Changes::Buffer;
+ RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Input;
+ }
+ if (clientState.what & layer_state_t::eBufferChanged) {
+ changes |= RequestedLayerState::Changes::Buffer;
+ }
+ if (clientState.what & layer_state_t::eSidebandStreamChanged) {
+ changes |= RequestedLayerState::Changes::SidebandStream;
}
}
if (what & (layer_state_t::eAlphaChanged)) {
@@ -197,7 +202,9 @@
static const mat4 identityMatrix = mat4();
hasColorTransform = colorTransform != identityMatrix;
}
- if (clientState.what & (layer_state_t::eLayerChanged | layer_state_t::eRelativeLayerChanged)) {
+ if (clientState.what &
+ (layer_state_t::eLayerChanged | layer_state_t::eRelativeLayerChanged |
+ layer_state_t::eLayerStackChanged)) {
changes |= RequestedLayerState::Changes::Z;
}
if (clientState.what & layer_state_t::eReparent) {
@@ -453,4 +460,22 @@
return backgroundBlurRadius > 0 || blurRegions.size() > 0;
}
+bool RequestedLayerState::hasFrameUpdate() const {
+ return what & layer_state_t::CONTENT_DIRTY &&
+ (externalTexture || bgColorLayerId != UNASSIGNED_LAYER_ID);
+}
+
+bool RequestedLayerState::hasReadyFrame() const {
+ return hasFrameUpdate() || changes.test(Changes::SidebandStream) || autoRefresh;
+}
+
+bool RequestedLayerState::hasSidebandStreamFrame() const {
+ return hasFrameUpdate() && sidebandStream.get();
+}
+
+void RequestedLayerState::clearChanges() {
+ what = 0;
+ changes.clear();
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 6840b25..8b475a3 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -52,10 +52,13 @@
FrameRate = 1u << 13,
VisibleRegion = 1u << 14,
Buffer = 1u << 15,
+ SidebandStream = 1u << 16,
};
static Rect reduce(const Rect& win, const Region& exclude);
RequestedLayerState(const LayerCreationArgs&);
void merge(const ResolvedComposerState&);
+ void clearChanges();
+
// Currently we only care about the primary display
ui::Transform getTransform(uint32_t displayRotationFlags) const;
ui::Size getUnrotatedBufferSize(uint32_t displayRotationFlags) const;
@@ -72,6 +75,9 @@
bool hasValidRelativeParent() const;
bool hasInputInfo() const;
bool hasBlur() const;
+ bool hasFrameUpdate() const;
+ bool hasReadyFrame() const;
+ bool hasSidebandStreamFrame() const;
// Layer serial number. This gives layers an explicit ordering, so we
// have a stable sort order when their layer stack and Z-order are
@@ -110,6 +116,7 @@
uint32_t touchCropId = UNASSIGNED_LAYER_ID;
uint32_t bgColorLayerId = UNASSIGNED_LAYER_ID;
ftl::Flags<RequestedLayerState::Changes> changes;
+ bool bgColorLayer = false;
};
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9d5c835..433606a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2096,15 +2096,7 @@
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
- ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
-
- // Only populate for the primary display.
- if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
- const auto compositionType = getCompositionType(*display);
- layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
- LayerProtoHelper::writeToProto(getVisibleRegion(display.get()),
- [&]() { return layerProto->mutable_visible_region(); });
- }
+ writeCompositionStateToProto(layerProto);
}
for (const sp<Layer>& layer : mDrawingChildren) {
@@ -2114,6 +2106,18 @@
return layerProto;
}
+void Layer::writeCompositionStateToProto(LayerProto* layerProto) {
+ ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
+
+ // Only populate for the primary display.
+ if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
+ const auto compositionType = getCompositionType(*display);
+ layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
+ LayerProtoHelper::writeToProto(getVisibleRegion(display.get()),
+ [&]() { return layerProto->mutable_visible_region(); });
+ }
+}
+
void Layer::writeToProtoDrawingState(LayerProto* layerInfo) {
const ui::Transform transform = getTransform();
auto buffer = getExternalTexture();
@@ -2511,7 +2515,20 @@
compositionengine::OutputLayer* Layer::findOutputLayerForDisplay(
const DisplayDevice* display) const {
if (!display) return nullptr;
- return display->getCompositionDisplay()->getOutputLayerForLayer(getCompositionEngineLayerFE());
+ if (!mFlinger->mLayerLifecycleManagerEnabled) {
+ return display->getCompositionDisplay()->getOutputLayerForLayer(
+ getCompositionEngineLayerFE());
+ }
+ sp<LayerFE> layerFE;
+ frontend::LayerHierarchy::TraversalPath path{.id = static_cast<uint32_t>(sequence)};
+ for (auto& [p, layer] : mLayerFEs) {
+ if (p == path) {
+ layerFE = layer;
+ }
+ }
+
+ if (!layerFE) return nullptr;
+ return display->getCompositionDisplay()->getOutputLayerForLayer(layerFE);
}
Region Layer::getVisibleRegion(const DisplayDevice* display) const {
@@ -3274,11 +3291,11 @@
(c.buffer != nullptr || c.bgColorLayer != nullptr);
}
-void Layer::updateTexImage(nsecs_t latchTime) {
+void Layer::updateTexImage(nsecs_t latchTime, bool bgColorOnly) {
const State& s(getDrawingState());
if (!s.buffer) {
- if (s.bgColorLayer) {
+ if (bgColorOnly) {
for (auto& handle : mDrawingState.callbackHandles) {
handle->latchTime = latchTime;
}
@@ -3475,7 +3492,7 @@
}
if (s.what & layer_state_t::eBackgroundColorChanged) {
- if (mDrawingState.bgColorLayer || s.bgColorAlpha != 0) {
+ if (mDrawingState.bgColorLayer || s.bgColor.a != 0) {
ALOGV("%s: false [eBackgroundColorChanged changed]", __func__);
return false;
}
@@ -3799,6 +3816,11 @@
}
bool Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+ const bool bgColorOnly = mDrawingState.bgColorLayer != nullptr;
+ return latchBufferImpl(recomputeVisibleRegions, latchTime, bgColorOnly);
+}
+
+bool Layer::latchBufferImpl(bool& recomputeVisibleRegions, nsecs_t latchTime, bool bgColorOnly) {
ATRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(),
getDrawingState().frameNumber);
@@ -3815,8 +3837,7 @@
mFlinger->onLayerUpdate();
return false;
}
-
- updateTexImage(latchTime);
+ updateTexImage(latchTime, bgColorOnly);
if (mDrawingState.buffer == nullptr) {
return false;
}
@@ -4020,7 +4041,6 @@
snapshot->bufferSize = getBufferSize(mDrawingState);
snapshot->externalTexture = mBufferInfo.mBuffer;
snapshot->hasReadyFrame = hasReadyFrame();
- snapshot->isInternalDisplayOverlay = isInternalDisplayOverlay();
preparePerFrameCompositionState();
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 492cf9a..4309aca 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -428,6 +428,9 @@
*/
bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/);
+ bool latchBufferImpl(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
+ bool bgColorOnly);
+
/*
* Calls latchBuffer if the buffer has a frame queued and then releases the buffer.
* This is used if the buffer is just latched and releases to free up the buffer
@@ -605,6 +608,7 @@
bool isRemovedFromCurrentState() const;
LayerProto* writeToProto(LayersProto& layersProto, uint32_t traceFlags);
+ void writeCompositionStateToProto(LayerProto* layerProto);
// Write states that are modified by the main thread. This includes drawing
// state as well as buffer data. This should be called in the main or tracing
@@ -847,6 +851,7 @@
void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
const sp<GraphicBuffer>& buffer, uint64_t framenumber,
const sp<Fence>& releaseFence);
+ bool setFrameRateForLayerTree(FrameRate);
protected:
// For unit tests
@@ -1019,7 +1024,6 @@
void updateTreeHasFrameRateVote();
bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded);
- bool setFrameRateForLayerTree(FrameRate);
void setZOrderRelativeOf(const wp<Layer>& relativeOf);
bool isTrustedOverlay() const;
gui::DropInputMode getDropInputMode() const;
@@ -1047,7 +1051,7 @@
bool hasFrameUpdate() const;
- void updateTexImage(nsecs_t latchTime);
+ void updateTexImage(nsecs_t latchTime, bool bgColorOnly = false);
// Crop that applies to the buffer
Rect computeBufferCrop(const State& s);
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 0506c47..55281fa 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -247,6 +247,153 @@
outRegion.right = proto.right();
outRegion.bottom = proto.bottom();
}
+
+void LayerProtoHelper::writeHierarchyToProto(
+ LayersProto& outLayersProto, const frontend::LayerHierarchy& root,
+ const frontend::LayerSnapshotBuilder& snapshotBuilder,
+ const std::unordered_map<uint32_t, sp<Layer>>& legacyLayers, uint32_t traceFlags) {
+ using Variant = frontend::LayerHierarchy::Variant;
+ frontend::LayerSnapshot defaultSnapshot;
+
+ LayerProto* layerProto = outLayersProto.add_layers();
+ const frontend::RequestedLayerState& layer = *root.getLayer();
+ frontend::LayerSnapshot* snapshot = snapshotBuilder.getSnapshot(layer.id);
+
+ if (!snapshot) {
+ defaultSnapshot.uniqueSequence = layer.id;
+ snapshot = &defaultSnapshot;
+ }
+ writeSnapshotToProto(layerProto, layer, *snapshot, traceFlags);
+ for (const auto& [child, variant] : root.mChildren) {
+ if (variant == Variant::Attached || variant == Variant::Detached) {
+ layerProto->add_children(child->getLayer()->id);
+ } else if (variant == Variant::Relative) {
+ layerProto->add_relatives(child->getLayer()->id);
+ }
+ }
+
+ auto parent = root.getParent();
+ if (parent && parent->getLayer()) {
+ layerProto->set_parent(parent->getLayer()->id);
+ } else {
+ layerProto->set_parent(-1);
+ }
+
+ auto relativeParent = root.getRelativeParent();
+ if (relativeParent && relativeParent->getLayer()) {
+ layerProto->set_z_order_relative_of(relativeParent->getLayer()->id);
+ } else {
+ layerProto->set_z_order_relative_of(-1);
+ }
+
+ if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
+ auto it = legacyLayers.find(layer.id);
+ if (it != legacyLayers.end()) {
+ it->second->writeCompositionStateToProto(layerProto);
+ }
+ }
+
+ for (const auto& [child, variant] : root.mChildren) {
+ // avoid visiting relative layers twice
+ if (variant == Variant::Detached) {
+ continue;
+ }
+ writeHierarchyToProto(outLayersProto, *child, snapshotBuilder, legacyLayers, traceFlags);
+ }
+}
+
+void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo,
+ const frontend::RequestedLayerState& requestedState,
+ const frontend::LayerSnapshot& snapshot,
+ uint32_t traceFlags) {
+ const ui::Transform transform = snapshot.geomLayerTransform;
+ auto buffer = requestedState.externalTexture;
+ if (buffer != nullptr) {
+ LayerProtoHelper::writeToProto(*buffer,
+ [&]() { return layerInfo->mutable_active_buffer(); });
+ LayerProtoHelper::writeToProtoDeprecated(ui::Transform(requestedState.bufferTransform),
+ layerInfo->mutable_buffer_transform());
+ }
+ layerInfo->set_invalidate(snapshot.contentDirty);
+ layerInfo->set_is_protected(snapshot.hasProtectedContent);
+ layerInfo->set_dataspace(dataspaceDetails(static_cast<android_dataspace>(snapshot.dataspace)));
+ layerInfo->set_curr_frame(requestedState.bufferData->frameNumber);
+ layerInfo->set_requested_corner_radius(requestedState.cornerRadius);
+ layerInfo->set_corner_radius(
+ (snapshot.roundedCorner.radius.x + snapshot.roundedCorner.radius.y) / 2.0);
+ layerInfo->set_background_blur_radius(snapshot.backgroundBlurRadius);
+ layerInfo->set_is_trusted_overlay(snapshot.isTrustedOverlay);
+ LayerProtoHelper::writeToProtoDeprecated(transform, layerInfo->mutable_transform());
+ LayerProtoHelper::writePositionToProto(transform.tx(), transform.ty(),
+ [&]() { return layerInfo->mutable_position(); });
+ LayerProtoHelper::writeToProto(snapshot.geomLayerBounds,
+ [&]() { return layerInfo->mutable_bounds(); });
+ LayerProtoHelper::writeToProto(snapshot.surfaceDamage,
+ [&]() { return layerInfo->mutable_damage_region(); });
+
+ if (requestedState.hasColorTransform) {
+ LayerProtoHelper::writeToProto(snapshot.colorTransform,
+ layerInfo->mutable_color_transform());
+ }
+
+ LayerProtoHelper::writeToProto(snapshot.croppedBufferSize.toFloatRect(),
+ [&]() { return layerInfo->mutable_source_bounds(); });
+ LayerProtoHelper::writeToProto(snapshot.transformedBounds,
+ [&]() { return layerInfo->mutable_screen_bounds(); });
+ LayerProtoHelper::writeToProto(snapshot.roundedCorner.cropRect,
+ [&]() { return layerInfo->mutable_corner_radius_crop(); });
+ layerInfo->set_shadow_radius(snapshot.shadowRadius);
+
+ layerInfo->set_id(snapshot.uniqueSequence);
+ layerInfo->set_name(requestedState.name);
+ layerInfo->set_type("Layer");
+
+ LayerProtoHelper::writeToProto(requestedState.transparentRegion,
+ [&]() { return layerInfo->mutable_transparent_region(); });
+
+ layerInfo->set_layer_stack(snapshot.outputFilter.layerStack.id);
+ layerInfo->set_z(requestedState.z);
+
+ ui::Transform requestedTransform = requestedState.getTransform(0);
+ LayerProtoHelper::writePositionToProto(requestedTransform.tx(), requestedTransform.ty(), [&]() {
+ return layerInfo->mutable_requested_position();
+ });
+
+ LayerProtoHelper::writeToProto(requestedState.crop,
+ [&]() { return layerInfo->mutable_crop(); });
+
+ layerInfo->set_is_opaque(snapshot.contentOpaque);
+ if (requestedState.externalTexture)
+ layerInfo->set_pixel_format(
+ decodePixelFormat(requestedState.externalTexture->getPixelFormat()));
+ LayerProtoHelper::writeToProto(snapshot.color, [&]() { return layerInfo->mutable_color(); });
+ LayerProtoHelper::writeToProto(requestedState.color,
+ [&]() { return layerInfo->mutable_requested_color(); });
+ layerInfo->set_flags(requestedState.flags);
+
+ LayerProtoHelper::writeToProtoDeprecated(requestedTransform,
+ layerInfo->mutable_requested_transform());
+
+ layerInfo->set_is_relative_of(requestedState.isRelativeOf);
+
+ layerInfo->set_owner_uid(requestedState.ownerUid);
+
+ if ((traceFlags & LayerTracing::TRACE_INPUT) && snapshot.hasInputInfo()) {
+ LayerProtoHelper::writeToProto(snapshot.inputInfo, {},
+ [&]() { return layerInfo->mutable_input_window_info(); });
+ }
+
+ if (traceFlags & LayerTracing::TRACE_EXTRA) {
+ auto protoMap = layerInfo->mutable_metadata();
+ for (const auto& entry : requestedState.metadata.mMap) {
+ (*protoMap)[entry.first] = std::string(entry.second.cbegin(), entry.second.cend());
+ }
+ }
+
+ LayerProtoHelper::writeToProto(requestedState.destinationFrame,
+ [&]() { return layerInfo->mutable_destination_frame(); });
+}
+
} // namespace surfaceflinger
} // namespace android
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
index 6ade143..de4bd01 100644
--- a/services/surfaceflinger/LayerProtoHelper.h
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -58,6 +58,15 @@
static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix);
static void writeToProto(const android::BlurRegion region, BlurRegion*);
static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion);
+ static void writeHierarchyToProto(LayersProto& layersProto,
+ const frontend::LayerHierarchy& root,
+ const frontend::LayerSnapshotBuilder& snapshotBuilder,
+ const std::unordered_map<uint32_t, sp<Layer>>& mLegacyLayers,
+ uint32_t traceFlags);
+
+ static void writeSnapshotToProto(LayerProto* outProto,
+ const frontend::RequestedLayerState& requestedState,
+ const frontend::LayerSnapshot& snapshot, uint32_t traceFlags);
};
} // namespace surfaceflinger
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 839500f..327ca3f 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -285,46 +285,72 @@
std::unordered_set<sp<IRegionSamplingListener>, SpHash<IRegionSamplingListener>> listeners;
- auto traverseLayers = [&](const LayerVector::Visitor& visitor) {
- bool stopLayerFound = false;
- auto filterVisitor = [&](Layer* layer) {
- // We don't want to capture any layers beyond the stop layer
- if (stopLayerFound) return;
+ auto layerFilterFn = [&](const char* layerName, uint32_t layerId, const Rect& bounds,
+ const ui::Transform transform, bool& outStopTraversal) -> bool {
+ // Likewise if we just found a stop layer, set the flag and abort
+ for (const auto& [area, stopLayerId, listener] : descriptors) {
+ if (stopLayerId != UNASSIGNED_LAYER_ID && layerId == stopLayerId) {
+ outStopTraversal = true;
+ return false;
+ }
+ }
- // Likewise if we just found a stop layer, set the flag and abort
- for (const auto& [area, stopLayerId, listener] : descriptors) {
- if (stopLayerId != UNASSIGNED_LAYER_ID && layer->getSequence() == stopLayerId) {
- stopLayerFound = true;
+ // Compute the layer's position on the screen
+ constexpr bool roundOutwards = true;
+ Rect transformed = transform.transform(bounds, roundOutwards);
+
+ // If this layer doesn't intersect with the larger sampledBounds, skip capturing it
+ Rect ignore;
+ if (!transformed.intersect(sampledBounds, &ignore)) return false;
+
+ // If the layer doesn't intersect a sampling area, skip capturing it
+ bool intersectsAnyArea = false;
+ for (const auto& [area, stopLayer, listener] : descriptors) {
+ if (transformed.intersect(area, &ignore)) {
+ intersectsAnyArea = true;
+ listeners.insert(listener);
+ }
+ }
+ if (!intersectsAnyArea) return false;
+
+ ALOGV("Traversing [%s] [%d, %d, %d, %d]", layerName, bounds.left, bounds.top, bounds.right,
+ bounds.bottom);
+
+ return true;
+ };
+
+ std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshots;
+ if (mFlinger.mLayerLifecycleManagerEnabled) {
+ auto filterFn = [&](const frontend::LayerSnapshot& snapshot,
+ bool& outStopTraversal) -> bool {
+ const Rect bounds =
+ frontend::RequestedLayerState::reduce(Rect(snapshot.geomLayerBounds),
+ snapshot.transparentRegionHint);
+ const ui::Transform transform = snapshot.geomLayerTransform;
+ return layerFilterFn(snapshot.name.c_str(), snapshot.path.id, bounds, transform,
+ outStopTraversal);
+ };
+ getLayerSnapshots =
+ mFlinger.getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
+ filterFn);
+ } else {
+ auto traverseLayers = [&](const LayerVector::Visitor& visitor) {
+ bool stopLayerFound = false;
+ auto filterVisitor = [&](Layer* layer) {
+ // We don't want to capture any layers beyond the stop layer
+ if (stopLayerFound) return;
+
+ if (!layerFilterFn(layer->getDebugName(), layer->getSequence(),
+ Rect(layer->getBounds()), layer->getTransform(),
+ stopLayerFound)) {
return;
}
- }
-
- // Compute the layer's position on the screen
- const Rect bounds = Rect(layer->getBounds());
- const ui::Transform transform = layer->getTransform();
- constexpr bool roundOutwards = true;
- Rect transformed = transform.transform(bounds, roundOutwards);
-
- // If this layer doesn't intersect with the larger sampledBounds, skip capturing it
- Rect ignore;
- if (!transformed.intersect(sampledBounds, &ignore)) return;
-
- // If the layer doesn't intersect a sampling area, skip capturing it
- bool intersectsAnyArea = false;
- for (const auto& [area, stopLayer, listener] : descriptors) {
- if (transformed.intersect(area, &ignore)) {
- intersectsAnyArea = true;
- listeners.insert(listener);
- }
- }
- if (!intersectsAnyArea) return;
-
- ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left,
- bounds.top, bounds.right, bounds.bottom);
- visitor(layer);
+ visitor(layer);
+ };
+ mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor);
};
- mFlinger.traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, filterVisitor);
- };
+ getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
+ }
std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
if (mCachedBuffer && mCachedBuffer->getBuffer()->getWidth() == sampledBounds.getWidth() &&
@@ -344,7 +370,6 @@
renderengine::impl::ExternalTexture::Usage::
WRITEABLE);
}
- auto getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers);
constexpr bool kRegionSampling = true;
constexpr bool kGrayscale = false;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 78be3c0..eecfeb6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2199,18 +2199,22 @@
mLayerLifecycleManager.getDestroyedLayers());
}
- applyAndCommitDisplayTransactionStates(update.transactions);
+ bool mustComposite = false;
+ mustComposite |= applyAndCommitDisplayTransactionStates(update.transactions);
{
ATRACE_NAME("LayerSnapshotBuilder:update");
- frontend::LayerSnapshotBuilder::Args args{.root = mLayerHierarchyBuilder.getHierarchy(),
- .layerLifecycleManager = mLayerLifecycleManager,
- .displays = mFrontEndDisplayInfos,
- .displayChanges = mFrontEndDisplayInfosChanged,
- .globalShadowSettings =
- mDrawingState.globalShadowSettings,
- .supportsBlur = mSupportsBlur,
- .forceFullDamage = mForceFullDamage};
+ frontend::LayerSnapshotBuilder::Args
+ args{.root = mLayerHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLayerLifecycleManager,
+ .displays = mFrontEndDisplayInfos,
+ .displayChanges = mFrontEndDisplayInfosChanged,
+ .globalShadowSettings = mDrawingState.globalShadowSettings,
+ .supportsBlur = mSupportsBlur,
+ .forceFullDamage = mForceFullDamage,
+ .supportedLayerGenericMetadata =
+ getHwComposer().getSupportedLayerGenericMetadata(),
+ .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
mLayerSnapshotBuilder.update(args);
}
@@ -2223,23 +2227,37 @@
mVisibleRegionsDirty = true;
}
outTransactionsAreEmpty = mLayerLifecycleManager.getGlobalChanges().get() == 0;
- const bool mustComposite = mLayerLifecycleManager.getGlobalChanges().get() != 0;
- {
- ATRACE_NAME("LLM:commitChanges");
- mLayerLifecycleManager.commitChanges();
- }
+ mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0;
+ bool newDataLatched = false;
if (!mLegacyFrontEndEnabled) {
ATRACE_NAME("DisplayCallbackAndStatsUpdates");
applyTransactions(update.transactions, vsyncId);
+ const nsecs_t latchTime = systemTime();
+ bool unused = false;
- bool newDataLatched = false;
- for (auto& snapshot : mLayerSnapshotBuilder.getSnapshots()) {
- if (!snapshot->changes.test(Changes::Buffer)) continue;
- auto it = mLegacyLayers.find(snapshot->sequence);
+ for (auto& layer : mLayerLifecycleManager.getLayers()) {
+ if (layer->changes.test(frontend::RequestedLayerState::Changes::Created) &&
+ layer->bgColorLayer) {
+ sp<Layer> bgColorLayer = getFactory().createEffectLayer(
+ LayerCreationArgs(this, nullptr, layer->name,
+ ISurfaceComposerClient::eFXSurfaceEffect, LayerMetadata(),
+ std::make_optional(layer->parentId), true));
+ mLegacyLayers[bgColorLayer->sequence] = bgColorLayer;
+ }
+ if (!layer->hasReadyFrame()) continue;
+
+ auto it = mLegacyLayers.find(layer->id);
LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s",
- snapshot->getDebugString().c_str());
+ layer->getDebugString().c_str());
+ const bool bgColorOnly =
+ !layer->externalTexture && (layer->bgColorLayerId != UNASSIGNED_LAYER_ID);
+ it->second->latchBufferImpl(unused, latchTime, bgColorOnly);
mLayersWithQueuedFrames.emplace(it->second);
+ }
+
+ for (auto& snapshot : mLayerSnapshotBuilder.getSnapshots()) {
+ if (!snapshot->hasReadyFrame) continue;
newDataLatched = true;
if (!snapshot->isVisible) break;
@@ -2252,13 +2270,20 @@
mLegacyLayers.erase(destroyedLayer->id);
}
+ {
+ ATRACE_NAME("LLM:commitChanges");
+ mLayerLifecycleManager.commitChanges();
+ }
+
+ commitTransactions();
+
// enter boot animation on first buffer latch
if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) {
ALOGI("Enter boot animation");
mBootStage = BootStage::BOOTANIMATION;
}
- commitTransactions();
}
+ mustComposite |= (getTransactionFlags() & ~eTransactionFlushNeeded) || newDataLatched;
return mustComposite;
}
@@ -2896,14 +2921,19 @@
}
// We avoid any reverse traversal upwards so this shouldn't be too expensive
- mDrawingState.traverse([&](Layer* layer) {
+ traverseLegacyLayers([&](Layer* layer) {
if (!layer->hasTrustedPresentationListener()) {
return;
}
- const std::optional<const DisplayDevice*> displayOpt =
- layerStackToDisplay.get(layer->getLayerSnapshot()->outputFilter.layerStack);
+ const frontend::LayerSnapshot* snapshot = (mLayerLifecycleManagerEnabled)
+ ? mLayerSnapshotBuilder.getSnapshot(layer->sequence)
+ : layer->getLayerSnapshot();
+ std::optional<const DisplayDevice*> displayOpt = std::nullopt;
+ if (snapshot) {
+ displayOpt = layerStackToDisplay.get(snapshot->outputFilter.layerStack);
+ }
const DisplayDevice* display = displayOpt.value_or(nullptr);
- layer->updateTrustedPresentationState(display, layer->getLayerSnapshot(),
+ layer->updateTrustedPresentationState(display, snapshot,
nanoseconds_to_milliseconds(callTime), false);
});
}
@@ -4480,6 +4510,7 @@
for (const auto& [_, display] : mDisplays) {
mFrontEndDisplayInfos.try_emplace(display->getLayerStack(), display->getFrontEndInfo());
}
+ needsTraversal = true;
}
return needsTraversal;
@@ -4659,7 +4690,7 @@
}
}
if (what & layer_state_t::eBackgroundColorChanged) {
- if (layer->setBackgroundColor(s.color.rgb, s.bgColorAlpha, s.bgColorDataspace)) {
+ if (layer->setBackgroundColor(s.bgColor.rgb, s.bgColor.a, s.bgColorDataspace)) {
flags |= eTraversalNeeded;
}
}
@@ -4904,8 +4935,6 @@
uint64_t transactionId) {
layer_state_t& s = composerState.state;
s.sanitize(permissions);
- const nsecs_t latchTime = systemTime();
- bool unused;
std::vector<ListenerCallbacks> filteredListeners;
for (auto& listener : s.listeners) {
@@ -4958,6 +4987,12 @@
sp<CallbackHandle>::make(listener, callbackIds, s.surface));
}
}
+ // TODO(b/238781169) remove after screenshot refactor, currently screenshots
+ // requires to read drawing state from binder thread. So we need to fix that
+ // before removing this.
+ if (what & layer_state_t::eCropChanged) {
+ if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
+ }
if (what & layer_state_t::eSidebandStreamChanged) {
if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
}
@@ -4965,7 +5000,6 @@
if (layer->setBuffer(composerState.externalTexture, *s.bufferData, postTime,
desiredPresentTime, isAutoTimestamp, dequeueBufferTimestamp,
frameTimelineInfo)) {
- layer->latchBuffer(unused, latchTime);
flags |= eTraversalNeeded;
}
mLayersWithQueuedFrames.emplace(layer);
@@ -4980,11 +5014,22 @@
}
}
- const auto& snapshot = mLayerSnapshotBuilder.getSnapshot(layer->getSequence());
+ const auto& requestedLayerState = mLayerLifecycleManager.getLayerFromId(layer->getSequence());
bool willPresentCurrentTransaction =
- snapshot && (snapshot->hasReadyFrame || snapshot->sidebandStreamHasFrame);
+ requestedLayerState && requestedLayerState->hasReadyFrame();
if (layer->setTransactionCompletedListeners(callbackHandles, willPresentCurrentTransaction))
flags |= eTraversalNeeded;
+
+ for (auto& snapshot : mLayerSnapshotBuilder.getSnapshots()) {
+ if (snapshot->path.isClone() ||
+ !snapshot->changes.test(frontend::RequestedLayerState::Changes::FrameRate))
+ continue;
+ auto it = mLegacyLayers.find(snapshot->sequence);
+ LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s",
+ snapshot->getDebugString().c_str());
+ it->second->setFrameRateForLayerTree(snapshot->frameRate);
+ }
+
return flags;
}
@@ -5073,7 +5118,7 @@
args.name, args.flags, -1 /* parentId */);
}
- {
+ if (mLegacyFrontEndEnabled) {
std::scoped_lock<std::mutex> lock(mMirrorDisplayLock);
mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client);
}
@@ -5183,8 +5228,18 @@
const sp<IBinder> token = display->getDisplayToken().promote();
LOG_ALWAYS_FATAL_IF(token == nullptr);
+ TransactionState state;
+ state.inputWindowCommands = mInputWindowCommands;
+ nsecs_t now = systemTime();
+ state.desiredPresentTime = now;
+ state.postTime = now;
+ state.permissions = layer_state_t::ACCESS_SURFACE_FLINGER;
+ state.originPid = mPid;
+ state.originUid = static_cast<int>(getuid());
+ uint64_t transactionId = (((uint64_t)mPid) << 32) | mUniqueTransactionId++;
+ state.id = transactionId;
+
// reset screen orientation and use primary layer stack
- std::vector<ResolvedComposerState> state;
Vector<DisplayState> displays;
DisplayState d;
d.what = DisplayState::eDisplayProjectionChanged |
@@ -5196,15 +5251,17 @@
d.layerStackSpaceRect.makeInvalid();
d.width = 0;
d.height = 0;
- displays.add(d);
+ state.displays.add(d);
- nsecs_t now = systemTime();
+ std::vector<TransactionState> transactions;
+ transactions.emplace_back(state);
- int64_t transactionId = (((int64_t)mPid) << 32) | mUniqueTransactionId++;
// It should be on the main thread, apply it directly.
- applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
- /* desiredPresentTime */ now, true, {}, /* postTime */ now, true, false,
- {}, mPid, getuid(), transactionId);
+ if (mLegacyFrontEndEnabled) {
+ applyTransactionsLocked(transactions, /*vsyncId=*/{0});
+ } else {
+ applyAndCommitDisplayTransactionStates(transactions);
+ }
setPowerModeInternal(display, hal::PowerMode::ON);
}
@@ -5643,14 +5700,27 @@
}
}
- LayersProto layersProto;
- for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
- if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) {
- continue;
+ if (mLegacyFrontEndEnabled) {
+ LayersProto layersProto;
+ for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) {
+ if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) {
+ continue;
+ }
+ layer->writeToProto(layersProto, traceFlags);
}
- layer->writeToProto(layersProto, traceFlags);
+ return layersProto;
}
+ const frontend::LayerHierarchy& root = mLayerHierarchyBuilder.getHierarchy();
+ LayersProto layersProto;
+ for (auto& [child, variant] : root.mChildren) {
+ if (variant != frontend::LayerHierarchy::Variant::Attached ||
+ stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) {
+ continue;
+ }
+ LayerProtoHelper::writeHierarchyToProto(layersProto, *child, mLayerSnapshotBuilder,
+ mLegacyLayers, traceFlags);
+ }
return layersProto;
}
@@ -6732,7 +6802,8 @@
GetLayerSnapshotsFunction getLayerSnapshots;
if (mLayerLifecycleManagerEnabled) {
- getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, args.uid);
+ getLayerSnapshots =
+ getLayerSnapshotsForScreenshots(layerStack, args.uid, /*snapshotFilterFn=*/nullptr);
} else {
auto traverseLayers = [this, args, layerStack](const LayerVector::Visitor& visitor) {
traverseLayersInLayerStack(layerStack, args.uid, visitor);
@@ -6774,7 +6845,8 @@
GetLayerSnapshotsFunction getLayerSnapshots;
if (mLayerLifecycleManagerEnabled) {
- getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID);
+ getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID,
+ /*snapshotFilterFn=*/nullptr);
} else {
auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) {
traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, visitor);
@@ -6942,7 +7014,7 @@
->schedule([=]() {
bool protectedLayerFound = false;
auto layers = getLayerSnapshots();
- for (auto& [layer, layerFe] : layers) {
+ for (auto& [_, layerFe] : layers) {
protectedLayerFound |=
(layerFe->mSnapshot->isVisible &&
layerFe->mSnapshot->hasProtectedContent);
@@ -7037,7 +7109,7 @@
ATRACE_CALL();
auto layers = getLayerSnapshots();
- for (auto& [layer, layerFE] : layers) {
+ for (auto& [_, layerFE] : layers) {
frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get();
captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure);
captureResults.capturedHdrLayers |= isHdrLayer(*snapshot);
@@ -7153,6 +7225,16 @@
return presentFuture;
}
+void SurfaceFlinger::traverseLegacyLayers(const LayerVector::Visitor& visitor) const {
+ if (mLayerLifecycleManagerEnabled) {
+ for (auto& layer : mLegacyLayers) {
+ visitor(layer.second.get());
+ }
+ } else {
+ mDrawingState.traverse(visitor);
+ }
+}
+
// ---------------------------------------------------------------------------
void SurfaceFlinger::State::traverse(const LayerVector::Visitor& visitor) const {
@@ -7749,6 +7831,7 @@
compositionengine::CompositionRefreshArgs& refreshArgs, bool cursorOnly, int64_t vsyncId) {
std::vector<std::pair<Layer*, LayerFE*>> layers;
if (mLayerLifecycleManagerEnabled) {
+ nsecs_t currentTime = systemTime();
mLayerSnapshotBuilder.forEachVisibleSnapshot(
[&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
if (cursorOnly &&
@@ -7767,6 +7850,7 @@
snapshot->getDebugString().c_str());
auto& legacyLayer = it->second;
sp<LayerFE> layerFE = legacyLayer->getCompositionEngineLayerFE(snapshot->path);
+ snapshot->fps = getLayerFramerate(currentTime, snapshot->sequence);
layerFE->mSnapshot = std::move(snapshot);
refreshArgs.layers.push_back(layerFE);
layers.emplace_back(legacyLayer.get(), layerFE.get());
@@ -7791,29 +7875,40 @@
}
std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()>
-SurfaceFlinger::getLayerSnapshotsForScreenshots(std::optional<ui::LayerStack> layerStack,
- uint32_t uid) {
- return [this, layerStack, uid]() {
+SurfaceFlinger::getLayerSnapshotsForScreenshots(
+ std::optional<ui::LayerStack> layerStack, uint32_t uid,
+ std::function<bool(const frontend::LayerSnapshot&, bool& outStopTraversal)>
+ snapshotFilterFn) {
+ return [&, layerStack, uid]() {
std::vector<std::pair<Layer*, sp<LayerFE>>> layers;
- for (auto& snapshot : mLayerSnapshotBuilder.getSnapshots()) {
- if (layerStack && snapshot->outputFilter.layerStack != *layerStack) {
- continue;
- }
- if (uid != CaptureArgs::UNSET_UID && snapshot->inputInfo.ownerUid != uid) {
- continue;
- }
- if (!snapshot->isVisible || !snapshot->hasSomethingToDraw()) {
- continue;
- }
+ bool stopTraversal = false;
+ mLayerSnapshotBuilder.forEachVisibleSnapshot(
+ [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) {
+ if (stopTraversal) {
+ return;
+ }
+ if (layerStack && snapshot->outputFilter.layerStack != *layerStack) {
+ return;
+ }
+ if (uid != CaptureArgs::UNSET_UID && snapshot->inputInfo.ownerUid != uid) {
+ return;
+ }
+ if (!snapshot->hasSomethingToDraw()) {
+ return;
+ }
+ if (snapshotFilterFn && !snapshotFilterFn(*snapshot, stopTraversal)) {
+ return;
+ }
- auto it = mLegacyLayers.find(snapshot->sequence);
- LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s",
- snapshot->getDebugString().c_str());
- auto& legacyLayer = it->second;
- sp<LayerFE> layerFE = getFactory().createLayerFE(legacyLayer->getName());
- layerFE->mSnapshot = std::make_unique<frontend::LayerSnapshot>(*snapshot);
- layers.emplace_back(legacyLayer.get(), std::move(layerFE));
- }
+ auto it = mLegacyLayers.find(snapshot->sequence);
+ LOG_ALWAYS_FATAL_IF(it == mLegacyLayers.end(),
+ "Couldnt find layer object for %s",
+ snapshot->getDebugString().c_str());
+ Layer* legacyLayer = (it == mLegacyLayers.end()) ? nullptr : it->second.get();
+ sp<LayerFE> layerFE = getFactory().createLayerFE(snapshot->name);
+ layerFE->mSnapshot = std::make_unique<frontend::LayerSnapshot>(*snapshot);
+ layers.emplace_back(legacyLayer, std::move(layerFE));
+ });
return layers;
};
@@ -7823,21 +7918,27 @@
SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t uid,
std::unordered_set<uint32_t> excludeLayerIds,
bool childrenOnly, const FloatRect& parentCrop) {
- return [this, excludeLayerIds = std::move(excludeLayerIds), uid, rootLayerId, childrenOnly,
+ return [&, rootLayerId, uid, excludeLayerIds = std::move(excludeLayerIds), childrenOnly,
parentCrop]() {
+ auto root = mLayerHierarchyBuilder.getPartialHierarchy(rootLayerId, childrenOnly);
frontend::LayerSnapshotBuilder::Args
- args{.root = mLayerHierarchyBuilder.getPartialHierarchy(rootLayerId, childrenOnly),
+ args{.root = root,
.layerLifecycleManager = mLayerLifecycleManager,
+ .forceUpdate = frontend::LayerSnapshotBuilder::ForceUpdateFlags::HIERARCHY,
.displays = mFrontEndDisplayInfos,
.displayChanges = true,
.globalShadowSettings = mDrawingState.globalShadowSettings,
.supportsBlur = mSupportsBlur,
.forceFullDamage = mForceFullDamage,
.parentCrop = {parentCrop},
- .excludeLayerIds = std::move(excludeLayerIds)};
+ .excludeLayerIds = std::move(excludeLayerIds),
+ .supportedLayerGenericMetadata =
+ getHwComposer().getSupportedLayerGenericMetadata(),
+ .genericLayerMetadataKeyMap = getGenericLayerMetadataKeyMap()};
mLayerSnapshotBuilder.update(args);
- auto getLayerSnapshotsFn = getLayerSnapshotsForScreenshots({}, uid);
+ auto getLayerSnapshotsFn =
+ getLayerSnapshotsForScreenshots({}, uid, /*snapshotFilterFn=*/nullptr);
std::vector<std::pair<Layer*, sp<LayerFE>>> layers = getLayerSnapshotsFn();
args.root = mLayerHierarchyBuilder.getHierarchy();
args.parentCrop.reset();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 843d2bf..b353a48 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1127,6 +1127,7 @@
ui::Rotation getPhysicalDisplayOrientation(DisplayId, bool isPrimary) const
REQUIRES(mStateLock);
+ void traverseLegacyLayers(const LayerVector::Visitor& visitor) const;
sp<StartPropertySetThread> mStartPropertySetThread;
surfaceflinger::Factory& mFactory;
@@ -1395,7 +1396,9 @@
[](const auto& display) { return display.isRefreshRateOverlayEnabled(); });
}
std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshotsForScreenshots(
- std::optional<ui::LayerStack> layerStack, uint32_t uid);
+ std::optional<ui::LayerStack> layerStack, uint32_t uid,
+ std::function<bool(const frontend::LayerSnapshot&, bool& outStopTraversal)>
+ snapshotFilterFn);
std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> getLayerSnapshotsForScreenshots(
uint32_t rootLayerId, uint32_t uid, std::unordered_set<uint32_t> excludeLayerIds,
bool childrenOnly, const FloatRect& parentCrop);
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index 475c76b..ba08cee 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -221,12 +221,12 @@
}
}
if (layer.what & layer_state_t::eBackgroundColorChanged) {
- proto.set_bg_color_alpha(layer.bgColorAlpha);
+ proto.set_bg_color_alpha(layer.bgColor.a);
proto.set_bg_color_dataspace(static_cast<int32_t>(layer.bgColorDataspace));
proto::LayerState_Color3* colorProto = proto.mutable_color();
- colorProto->set_r(layer.color.r);
- colorProto->set_g(layer.color.g);
- colorProto->set_b(layer.color.b);
+ colorProto->set_r(layer.bgColor.r);
+ colorProto->set_g(layer.bgColor.g);
+ colorProto->set_b(layer.bgColor.b);
}
if (layer.what & layer_state_t::eColorSpaceAgnosticChanged) {
proto.set_color_space_agnostic(layer.colorSpaceAgnostic);
@@ -510,12 +510,12 @@
layer.windowInfoHandle = sp<gui::WindowInfoHandle>::make(inputInfo);
}
if (proto.what() & layer_state_t::eBackgroundColorChanged) {
- layer.bgColorAlpha = proto.bg_color_alpha();
+ layer.bgColor.a = proto.bg_color_alpha();
layer.bgColorDataspace = static_cast<ui::Dataspace>(proto.bg_color_dataspace());
const proto::LayerState_Color3& colorProto = proto.color();
- layer.color.r = colorProto.r();
- layer.color.g = colorProto.g();
- layer.color.b = colorProto.b();
+ layer.bgColor.r = colorProto.r();
+ layer.bgColor.g = colorProto.g();
+ layer.bgColor.b = colorProto.b();
}
if (proto.what() & layer_state_t::eColorSpaceAgnosticChanged) {
layer.colorSpaceAgnostic = proto.color_space_agnostic();
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index bf7cae9..0b8c51e 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -544,6 +544,7 @@
.apply();
{
+ SCOPED_TRACE("final color");
auto shot = screenshot();
shot->expectColor(Rect(0, 0, width, height), finalColor);
shot->expectBorder(Rect(0, 0, width, height), Color::BLACK);
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index e69db7c..0ea0824 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -18,6 +18,7 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
+#include <android-base/properties.h>
#include <private/android_filesystem_config.h>
#include "LayerTransactionTest.h"
#include "utils/TransactionUtils.h"
@@ -119,15 +120,20 @@
shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK);
}
- // Remove child layer
+ if (base::GetBoolProperty("debug.sf.enable_legacy_frontend", true)) {
+ GTEST_SKIP() << "Skipping test because mirroring behavior changes with legacy frontend";
+ }
+
+ // Remove child layer and verify we can still mirror the layer when
+ // its offscreen.
Transaction().reparent(mChildLayer, nullptr).apply();
{
SCOPED_TRACE("Removed Child Layer");
auto shot = screenshot();
// Grandchild mirror
- shot->expectColor(Rect(550, 550, 750, 750), Color::RED);
+ shot->expectColor(Rect(550, 550, 750, 750), Color::BLACK);
// Child mirror
- shot->expectColor(Rect(750, 750, 950, 950), Color::RED);
+ shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK);
}
// Add grandchild layer to offscreen layer
@@ -136,9 +142,9 @@
SCOPED_TRACE("Added Grandchild Layer");
auto shot = screenshot();
// Grandchild mirror
- shot->expectColor(Rect(550, 550, 750, 750), Color::RED);
+ shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
// Child mirror
- shot->expectColor(Rect(750, 750, 950, 950), Color::RED);
+ shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK);
}
// Add child layer
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
index 763426a..77dc868 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.cpp
@@ -263,6 +263,37 @@
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
}
+TEST_F(LayerHierarchyTest, reparentRelativeLayer) {
+ LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
+ reparentRelativeLayer(11, 2);
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+
+ std::vector<uint32_t> expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 11, 111};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {1, 12, 121, 122, 1221, 13, 2, 11, 111};
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+ reparentLayer(11, 1);
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2, 11, 111};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {1, 12, 121, 122, 1221, 13, 2, 11, 111};
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+
+ setZ(11, 0);
+ UPDATE_AND_VERIFY(hierarchyBuilder);
+ expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
+ expectedTraversalPath = {};
+ EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
+}
+
// mirror tests
TEST_F(LayerHierarchyTest, canTraverseMirrorLayer) {
LayerHierarchyBuilder hierarchyBuilder(mLifecycleManager.getLayers());
@@ -437,10 +468,11 @@
updateBackgroundColor(1, 0.5);
UPDATE_AND_VERIFY(hierarchyBuilder);
-
- std::vector<uint32_t> expectedTraversalPath = {1, 1222, 11, 111, 12, 121, 122, 1221, 13, 2};
+ auto bgLayerId = LayerCreationArgs::getInternalLayerId(1);
+ std::vector<uint32_t> expectedTraversalPath = {1, bgLayerId, 11, 111, 12,
+ 121, 122, 1221, 13, 2};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
- expectedTraversalPath = {1222, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ expectedTraversalPath = {bgLayerId, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
EXPECT_EQ(getTraversalPathInZOrder(hierarchyBuilder.getHierarchy()), expectedTraversalPath);
expectedTraversalPath = {};
EXPECT_EQ(getTraversalPath(hierarchyBuilder.getOffscreenHierarchy()), expectedTraversalPath);
diff --git a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
index 852cb91..b9a6159 100644
--- a/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
+++ b/services/surfaceflinger/tests/unittests/LayerHierarchyTest.h
@@ -172,7 +172,7 @@
transactions.emplace_back();
transactions.back().states.push_back({});
transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
- transactions.back().states.front().state.bgColorAlpha = alpha;
+ transactions.back().states.front().state.bgColor.a = alpha;
transactions.back().states.front().state.surface = mHandles[id];
mLifecycleManager.applyTransactions(transactions);
}
@@ -274,6 +274,22 @@
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().state.surface = mHandles[id];
+ transactions.back().states.front().state.layerId = static_cast<int32_t>(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);
+ }
+
LayerLifecycleManager mLifecycleManager;
std::unordered_map<uint32_t, sp<LayerHandle>> mHandles;
};
diff --git a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
index 89440a6..99c1d23 100644
--- a/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerLifecycleManagerTest.cpp
@@ -372,7 +372,7 @@
std::vector<TransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
- transactions.back().states.front().state.bgColorAlpha = 0.5;
+ transactions.back().states.front().state.bgColor.a = 0.5;
transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
transactions.back().states.front().state.surface = handle;
@@ -383,9 +383,10 @@
EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
lifecycleManager.commitChanges();
- listener->expectLayersAdded({1, 2});
+ auto bgLayerId = LayerCreationArgs::getInternalLayerId(1);
+ listener->expectLayersAdded({1, bgLayerId});
listener->expectLayersDestroyed({});
- EXPECT_EQ(getRequestedLayerState(lifecycleManager, 2)->color.a, 0.5_hf);
+ EXPECT_EQ(getRequestedLayerState(lifecycleManager, bgLayerId)->color.a, 0.5_hf);
}
TEST_F(LayerLifecycleManagerTest, canDestroyBackgroundLayer) {
@@ -400,13 +401,13 @@
std::vector<TransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
- transactions.back().states.front().state.bgColorAlpha = 0.5;
+ transactions.back().states.front().state.bgColor.a = 0.5;
transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
transactions.back().states.front().state.surface = handle;
transactions.emplace_back();
transactions.back().states.push_back({});
- transactions.back().states.front().state.bgColorAlpha = 0;
+ transactions.back().states.front().state.bgColor.a = 0;
transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
transactions.back().states.front().state.surface = handle;
@@ -417,8 +418,9 @@
EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
lifecycleManager.commitChanges();
- listener->expectLayersAdded({1, 2});
- listener->expectLayersDestroyed({2});
+ auto bgLayerId = LayerCreationArgs::getInternalLayerId(1);
+ listener->expectLayersAdded({1, bgLayerId});
+ listener->expectLayersDestroyed({bgLayerId});
}
TEST_F(LayerLifecycleManagerTest, onParentDestroyDestroysBackgroundLayer) {
@@ -433,7 +435,7 @@
std::vector<TransactionState> transactions;
transactions.emplace_back();
transactions.back().states.push_back({});
- transactions.back().states.front().state.bgColorAlpha = 0.5;
+ transactions.back().states.front().state.bgColor.a = 0.5;
transactions.back().states.front().state.what = layer_state_t::eBackgroundColorChanged;
sp<LayerHandle> handle = sp<LayerHandle>::make(1u);
transactions.back().states.front().state.surface = handle;
@@ -446,8 +448,9 @@
EXPECT_TRUE(lifecycleManager.getGlobalChanges().test(RequestedLayerState::Changes::Hierarchy));
lifecycleManager.commitChanges();
- listener->expectLayersAdded({1, 2});
- listener->expectLayersDestroyed({1, 2});
+ auto bgLayerId = LayerCreationArgs::getInternalLayerId(1);
+ listener->expectLayersAdded({1, bgLayerId});
+ listener->expectLayersDestroyed({1, bgLayerId});
}
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index aa6a14e..db0b907 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -75,14 +75,14 @@
mHierarchyBuilder.update(mLifecycleManager.getLayers(),
mLifecycleManager.getDestroyedLayers());
}
- LayerSnapshotBuilder::Args args{
- .root = mHierarchyBuilder.getHierarchy(),
- .layerLifecycleManager = mLifecycleManager,
- .includeMetadata = false,
- .displays = mFrontEndDisplayInfos,
- .displayChanges = hasDisplayChanges,
- .globalShadowSettings = globalShadowSettings,
- };
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .displayChanges = hasDisplayChanges,
+ .globalShadowSettings = globalShadowSettings,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
actualBuilder.update(args);
// rebuild layer snapshots from scratch and verify that it matches the updated state.
@@ -100,6 +100,9 @@
}
LayerSnapshot* getSnapshot(uint32_t layerId) { return mSnapshotBuilder.getSnapshot(layerId); }
+ LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath path) {
+ return mSnapshotBuilder.getSnapshot(path);
+ }
LayerHierarchyBuilder mHierarchyBuilder{{}};
LayerSnapshotBuilder mSnapshotBuilder;
@@ -111,23 +114,25 @@
122, 1221, 13, 2};
TEST_F(LayerSnapshotTest, buildSnapshot) {
- LayerSnapshotBuilder::Args args{
- .root = mHierarchyBuilder.getHierarchy(),
- .layerLifecycleManager = mLifecycleManager,
- .includeMetadata = false,
- .displays = mFrontEndDisplayInfos,
- .globalShadowSettings = globalShadowSettings,
- };
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .globalShadowSettings = globalShadowSettings,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
LayerSnapshotBuilder builder(args);
}
TEST_F(LayerSnapshotTest, updateSnapshot) {
- LayerSnapshotBuilder::Args args{
- .root = mHierarchyBuilder.getHierarchy(),
- .layerLifecycleManager = mLifecycleManager,
- .includeMetadata = false,
- .displays = mFrontEndDisplayInfos,
- .globalShadowSettings = globalShadowSettings,
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .globalShadowSettings = globalShadowSettings,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}
+
};
LayerSnapshotBuilder builder;
@@ -320,7 +325,7 @@
// └── 2
// ROOT (DISPLAY 1)
// └── 3 (mirrors display 0)
-TEST_F(LayerSnapshotTest, displayMirrorRespects) {
+TEST_F(LayerSnapshotTest, displayMirrorRespectsLayerSkipScreenshotFlag) {
setFlags(12, layer_state_t::eLayerSkipScreenshot, layer_state_t::eLayerSkipScreenshot);
createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
setLayerStack(3, 1);
@@ -329,4 +334,96 @@
UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
}
+// ROOT (DISPLAY 0)
+// ├── 1
+// │ ├── 11
+// │ │ └── 111
+// │ └── 13
+// └── 2
+// ROOT (DISPLAY 3)
+// └── 3 (mirrors display 0)
+TEST_F(LayerSnapshotTest, mirrorLayerGetsCorrectLayerStack) {
+ reparentLayer(12, UNASSIGNED_LAYER_ID);
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 3);
+ createDisplayMirrorLayer(4, ui::LayerStack::fromValue(0));
+ setLayerStack(4, 4);
+
+ std::vector<uint32_t> expected = {4, 1, 11, 111, 13, 2, 3, 1, 11,
+ 111, 13, 2, 1, 11, 111, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 3})->outputFilter.layerStack.id, 3u);
+ EXPECT_EQ(getSnapshot({.id = 111, .mirrorRootId = 4})->outputFilter.layerStack.id, 4u);
+}
+
+// ROOT (DISPLAY 0)
+// ├── 1 (crop 50x50)
+// │ ├── 11
+// │ │ └── 111
+// │ └── 13
+// └── 2
+// ROOT (DISPLAY 3)
+// └── 3 (mirrors display 0) (crop 100x100)
+TEST_F(LayerSnapshotTest, mirrorLayerTouchIsCroppedByMirrorRoot) {
+ reparentLayer(12, UNASSIGNED_LAYER_ID);
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 3);
+ setCrop(1, Rect{50, 50});
+ setCrop(3, Rect{100, 100});
+ setCrop(111, Rect{200, 200});
+ Region touch{Rect{0, 0, 1000, 1000}};
+ setTouchableRegion(111, touch);
+ std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ EXPECT_TRUE(getSnapshot({.id = 111})->inputInfo.touchableRegion.hasSameRects(touch));
+ Region touchCroppedByMirrorRoot{Rect{0, 0, 50, 50}};
+ EXPECT_TRUE(getSnapshot({.id = 111, .mirrorRootId = 3})
+ ->inputInfo.touchableRegion.hasSameRects(touchCroppedByMirrorRoot));
+}
+
+TEST_F(LayerSnapshotTest, canRemoveDisplayMirror) {
+ setFlags(12, layer_state_t::eLayerSkipScreenshot, layer_state_t::eLayerSkipScreenshot);
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 1);
+ std::vector<uint32_t> expected = {3, 1, 11, 111, 13, 2, 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ destroyLayerHandle(3);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+}
+
+TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterMirroring) {
+ size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
+ createDisplayMirrorLayer(3, ui::LayerStack::fromValue(0));
+ setLayerStack(3, 1);
+ std::vector<uint32_t> expected = {3, 1, 11, 111, 12, 121, 122, 1221, 13, 2,
+ 1, 11, 111, 12, 121, 122, 1221, 13, 2};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+ destroyLayerHandle(3);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size());
+}
+
+// Rel z doesn't create duplicate snapshots but this is for completeness
+TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterRelZ) {
+ size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
+ reparentRelativeLayer(13, 11);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, {1, 11, 13, 111, 12, 121, 122, 1221, 2});
+ setZ(13, 0);
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ EXPECT_EQ(startingNumSnapshots, mSnapshotBuilder.getSnapshots().size());
+}
+
+TEST_F(LayerSnapshotTest, cleanUpUnreachableSnapshotsAfterLayerDestruction) {
+ size_t startingNumSnapshots = mSnapshotBuilder.getSnapshots().size();
+ destroyLayerHandle(2);
+ destroyLayerHandle(122);
+
+ std::vector<uint32_t> expected = {1, 11, 111, 12, 121, 122, 1221, 13};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, expected);
+
+ EXPECT_LE(startingNumSnapshots - 2, mSnapshotBuilder.getSnapshots().size());
+}
+
} // namespace android::surfaceflinger::frontend