[sf] add debug dump for new front end
Test: window type populated correctly in sf dump
Test: dumpsys SurfaceFlinger
Bug: 238781169
Change-Id: I86e475393c8b157496862fa34420c13fc80d681c
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index 163d345..ab4c15d 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -149,13 +149,33 @@
return debug + "}";
}
-std::string LayerHierarchy::getDebugString(const char* prefix) const {
- std::string debug = prefix + getDebugStringShort();
- for (auto& [child, childVariant] : mChildren) {
- std::string childPrefix = " " + std::string(prefix) + " " + std::to_string(childVariant);
- debug += "\n" + child->getDebugString(childPrefix.c_str());
+void LayerHierarchy::dump(std::ostream& out, const std::string& prefix,
+ LayerHierarchy::Variant variant, bool isLastChild) const {
+ if (!mLayer) {
+ out << " ROOT";
+ } else {
+ out << prefix + (isLastChild ? "└─ " : "├─ ");
+ if (variant == LayerHierarchy::Variant::Relative) {
+ out << "(Relative) ";
+ } else if (variant == LayerHierarchy::Variant::Mirror) {
+ out << "(Mirroring) " << *mLayer << "\n" + prefix + " └─ ...";
+ return;
+ }
+ out << *mLayer;
}
- return debug;
+
+ for (size_t i = 0; i < mChildren.size(); i++) {
+ auto& [child, childVariant] = mChildren[i];
+ if (childVariant == LayerHierarchy::Variant::Detached) continue;
+ const bool lastChild = i == (mChildren.size() - 1);
+ std::string childPrefix = prefix;
+ if (mLayer) {
+ childPrefix += (isLastChild ? " " : "│ ");
+ }
+ out << "\n";
+ child->dump(out, childPrefix, childVariant, lastChild);
+ }
+ return;
}
bool LayerHierarchy::hasRelZLoop(uint32_t& outInvalidRelativeRoot) const {
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index 5389ada..1e48387 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -156,7 +156,12 @@
const RequestedLayerState* getLayer() const;
const LayerHierarchy* getRelativeParent() const;
const LayerHierarchy* getParent() const;
- std::string getDebugString(const char* prefix = "") const;
+ friend std::ostream& operator<<(std::ostream& os, const LayerHierarchy& obj) {
+ std::string prefix = " ";
+ obj.dump(os, prefix, LayerHierarchy::Variant::Attached, /*isLastChild=*/false);
+ return os;
+ }
+
std::string getDebugStringShort() const;
// Traverse the hierarchy and return true if loops are found. The outInvalidRelativeRoot
// will contain the first relative root that was visited twice in a traversal.
@@ -172,6 +177,8 @@
void updateChild(LayerHierarchy*, LayerHierarchy::Variant);
void traverseInZOrder(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const;
void traverse(const Visitor& visitor, LayerHierarchy::TraversalPath& parent) const;
+ void dump(std::ostream& out, const std::string& prefix, LayerHierarchy::Variant variant,
+ bool isLastChild) const;
const RequestedLayerState* mLayer;
LayerHierarchy* mParent = nullptr;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index f0826c6..6f68a92 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -39,6 +39,63 @@
}
}
+std::ostream& operator<<(std::ostream& os, const ui::Transform& transform) {
+ const uint32_t type = transform.getType();
+ const uint32_t orientation = transform.getOrientation();
+ if (type == ui::Transform::IDENTITY) {
+ return os;
+ }
+
+ if (type & ui::Transform::UNKNOWN) {
+ std::string out;
+ transform.dump(out, "", "");
+ os << out;
+ return os;
+ }
+
+ if (type & ui::Transform::ROTATE) {
+ switch (orientation) {
+ case ui::Transform::ROT_0:
+ os << "ROT_0";
+ break;
+ case ui::Transform::FLIP_H:
+ os << "FLIP_H";
+ break;
+ case ui::Transform::FLIP_V:
+ os << "FLIP_V";
+ break;
+ case ui::Transform::ROT_90:
+ os << "ROT_90";
+ break;
+ case ui::Transform::ROT_180:
+ os << "ROT_180";
+ break;
+ case ui::Transform::ROT_270:
+ os << "ROT_270";
+ break;
+ case ui::Transform::ROT_INVALID:
+ default:
+ os << "ROT_INVALID";
+ break;
+ }
+ }
+
+ if (type & ui::Transform::SCALE) {
+ std::string out;
+ android::base::StringAppendF(&out, " scale x=%.4f y=%.4f ", transform.getScaleX(),
+ transform.getScaleY());
+ os << out;
+ }
+
+ if (type & ui::Transform::TRANSLATE) {
+ std::string out;
+ android::base::StringAppendF(&out, " tx=%.4f ty=%.4f ", transform.tx(), transform.ty());
+ os << out;
+ }
+
+ return os;
+}
+
} // namespace
LayerSnapshot::LayerSnapshot(const RequestedLayerState& state,
@@ -59,6 +116,7 @@
}
sequence = static_cast<int32_t>(state.id);
name = state.name;
+ debugName = state.debugName;
textureName = state.textureName;
premultipliedAlpha = state.premultipliedAlpha;
inputInfo.name = state.name;
@@ -180,13 +238,13 @@
if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot";
if (invalidTransform) return "invalidTransform";
if (color.a == 0.0f && !hasBlur()) return "alpha = 0 and no blur";
- if (!hasSomethingToDraw()) return "!hasSomethingToDraw";
+ if (!hasSomethingToDraw()) return "nothing to draw";
// visible
std::stringstream reason;
if (sidebandStream != nullptr) reason << " sidebandStream";
if (externalTexture != nullptr)
- reason << " buffer:" << externalTexture->getId() << " frame:" << frameNumber;
+ 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;
@@ -232,6 +290,36 @@
return debug.str();
}
+std::ostream& operator<<(std::ostream& out, const LayerSnapshot& obj) {
+ out << "Layer [" << obj.path.id;
+ if (obj.path.mirrorRootId != UNASSIGNED_LAYER_ID) {
+ out << " mirrored from " << obj.path.mirrorRootId;
+ }
+ out << "] " << obj.name << "\n " << (obj.isVisible ? "visible" : "invisible")
+ << " reason=" << obj.getIsVisibleReason();
+
+ if (!obj.geomLayerBounds.isEmpty()) {
+ out << "\n bounds={" << obj.transformedBounds.left << "," << obj.transformedBounds.top
+ << "," << obj.transformedBounds.bottom << "," << obj.transformedBounds.right << "}";
+ }
+
+ if (obj.geomLayerTransform.getType() != ui::Transform::IDENTITY) {
+ out << " toDisplayTransform={" << obj.geomLayerTransform << "}";
+ }
+
+ if (obj.hasInputInfo()) {
+ out << "\n input{"
+ << "(" << obj.inputInfo.inputConfig.string() << ")";
+ if (obj.touchCropId != UNASSIGNED_LAYER_ID) out << " touchCropId=" << obj.touchCropId;
+ if (obj.inputInfo.replaceTouchableRegionWithCrop) out << " replaceTouchableRegionWithCrop";
+ auto touchableRegion = obj.inputInfo.touchableRegion.getBounds();
+ out << " touchableRegion={" << touchableRegion.left << "," << touchableRegion.top << ","
+ << touchableRegion.bottom << "," << touchableRegion.right << "}"
+ << "}";
+ }
+ return out;
+}
+
FloatRect LayerSnapshot::sourceBounds() const {
if (!externalTexture) {
return geomLayerBounds;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index 2f45d52..9f0822c 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -67,6 +67,7 @@
// generated from the same layer, for example when mirroring.
int32_t sequence;
std::string name;
+ std::string debugName;
uint32_t textureName;
bool contentOpaque;
bool layerOpaqueFlagSet;
@@ -145,7 +146,7 @@
bool hasInputInfo() const;
FloatRect sourceBounds() const;
Hwc2::IComposerClient::BlendMode getBlendMode(const RequestedLayerState& requested) const;
-
+ friend std::ostream& operator<<(std::ostream& os, const LayerSnapshot& obj);
void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges,
bool forceFullDamage, uint32_t displayRotationFlags);
};
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 065b895..a4777d1 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -127,6 +127,16 @@
gameMode = gui::GameMode::Unsupported;
requestedFrameRate = {};
cachingHint = gui::CachingHint::Enabled;
+
+ if (name.length() > 77) {
+ std::string shortened;
+ shortened.append(name, 0, 36);
+ shortened.append("[...]");
+ shortened.append(name, name.length() - 36);
+ debugName = std::move(shortened);
+ } else {
+ debugName = name;
+ }
}
void RequestedLayerState::merge(const ResolvedComposerState& resolvedComposerState) {
@@ -371,6 +381,13 @@
return debug.str();
}
+std::ostream& operator<<(std::ostream& out, const RequestedLayerState& obj) {
+ out << obj.debugName;
+ if (obj.relativeParentId != UNASSIGNED_LAYER_ID) out << " parent=" << obj.parentId;
+ if (!obj.handleAlive) out << " handleNotAlive";
+ return out;
+}
+
std::string RequestedLayerState::getDebugStringShort() const {
return "[" + std::to_string(id) + "]" + name;
}
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 8ca1cd6..1c19d6d 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -74,6 +74,7 @@
Rect getBufferCrop() const;
std::string getDebugString() const;
std::string getDebugStringShort() const;
+ friend std::ostream& operator<<(std::ostream& os, const RequestedLayerState& obj);
aidl::android::hardware::graphics::composer3::Composition getCompositionType() const;
bool hasValidRelativeParent() const;
bool hasInputInfo() const;
@@ -118,6 +119,7 @@
uint32_t bgColorLayerId = UNASSIGNED_LAYER_ID;
uint64_t barrierFrameNumber = 0;
uint32_t barrierProducerId = 0;
+ std::string debugName;
// book keeping states
bool handleAlive = true;