Merge "Remove libhostgraphics from libinput" into udc-qpr-dev
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index a6f503e..62e5f89 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -270,9 +270,9 @@
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 |
- layer_state_t::HIERARCHY_CHANGES | layer_state_t::eInputInfoChanged |
- layer_state_t::eDropInputModeChanged | layer_state_t::eTrustedOverlayChanged;
+ static constexpr uint64_t INPUT_CHANGES = layer_state_t::eInputInfoChanged |
+ layer_state_t::eDropInputModeChanged | layer_state_t::eTrustedOverlayChanged |
+ layer_state_t::eLayerStackChanged;
// Changes that affect the visible region on a display.
static constexpr uint64_t VISIBLE_REGION_CHANGES =
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 0aa1bcb..545f6c2 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -61,7 +61,7 @@
// For older HALs which don't support batching, use a smaller socket buffer size.
#define SOCKET_BUFFER_SIZE_NON_BATCHED (4 * 1024)
-#define SENSOR_REGISTRATIONS_BUF_SIZE 200
+#define SENSOR_REGISTRATIONS_BUF_SIZE 500
// Apps that targets S+ and do not have HIGH_SAMPLING_RATE_SENSORS permission will be capped
// at 200 Hz. The cap also applies to all requests when the mic toggle is flipped to on, regardless
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index f7049b9..c0eb36d 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -20,6 +20,7 @@
#include "AidlComposerHal.h"
+#include <SurfaceFlingerProperties.h>
#include <android-base/file.h>
#include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h>
@@ -249,15 +250,18 @@
ALOGE("getInterfaceVersion for AidlComposer constructor failed %s",
status.getDescription().c_str());
}
- if (version == 1) {
- mClearSlotBuffer = sp<GraphicBuffer>::make(1, 1, PIXEL_FORMAT_RGBX_8888,
- GraphicBuffer::USAGE_HW_COMPOSER |
- GraphicBuffer::USAGE_SW_READ_OFTEN |
- GraphicBuffer::USAGE_SW_WRITE_OFTEN,
- "AidlComposer");
- if (!mClearSlotBuffer || mClearSlotBuffer->initCheck() != ::android::OK) {
- LOG_ALWAYS_FATAL("Failed to allocate a buffer for clearing layer buffer slots");
- return;
+ mSupportsBufferSlotsToClear = version > 1;
+ if (!mSupportsBufferSlotsToClear) {
+ if (sysprop::clear_slots_with_set_layer_buffer(false)) {
+ mClearSlotBuffer = sp<GraphicBuffer>::make(1, 1, PIXEL_FORMAT_RGBX_8888,
+ GraphicBuffer::USAGE_HW_COMPOSER |
+ GraphicBuffer::USAGE_SW_READ_OFTEN |
+ GraphicBuffer::USAGE_SW_WRITE_OFTEN,
+ "AidlComposer");
+ if (!mClearSlotBuffer || mClearSlotBuffer->initCheck() != ::android::OK) {
+ LOG_ALWAYS_FATAL("Failed to allocate a buffer for clearing layer buffer slots");
+ return;
+ }
}
}
@@ -844,12 +848,12 @@
Error error = Error::NONE;
mMutex.lock_shared();
if (auto writer = getWriter(display)) {
- // Backwards compatible way of clearing buffer is to set the layer buffer with a placeholder
- // buffer, using the slot that needs to cleared... tricky.
- if (mClearSlotBuffer == nullptr) {
+ if (mSupportsBufferSlotsToClear) {
writer->get().setLayerBufferSlotsToClear(translate<int64_t>(display),
translate<int64_t>(layer), slotsToClear);
- } else {
+ // Backwards compatible way of clearing buffer slots is to set the layer buffer with a
+ // placeholder buffer, using the slot that needs to cleared... tricky.
+ } else if (mClearSlotBuffer != nullptr) {
for (uint32_t slot : slotsToClear) {
// Don't clear the active buffer slot because we need to restore the active buffer
// after clearing the requested buffer slots with a placeholder buffer.
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index ded91be..8d21b49 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -285,6 +285,8 @@
// threading annotations.
ftl::SharedMutex mMutex;
+ // Whether or not explicitly clearing buffer slots is supported.
+ bool mSupportsBufferSlotsToClear;
// Buffer slots for layers are cleared by setting the slot buffer to this buffer.
sp<GraphicBuffer> mClearSlotBuffer;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index e0f6c45..9b41da5 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -24,12 +24,14 @@
#include "HidlComposerHal.h"
+#include <SurfaceFlingerProperties.h>
#include <android/binder_manager.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
#include <hidl/HidlTransportSupport.h>
#include <hidl/HidlTransportUtils.h>
#include <log/log.h>
#include <utils/Trace.h>
+
#include "HWC2.h"
#include "Hal.h"
@@ -189,6 +191,9 @@
}
sp<GraphicBuffer> allocateClearSlotBuffer() {
+ if (!sysprop::clear_slots_with_set_layer_buffer(false)) {
+ return nullptr;
+ }
sp<GraphicBuffer> buffer = sp<GraphicBuffer>::make(1, 1, PIXEL_FORMAT_RGBX_8888,
GraphicBuffer::USAGE_HW_COMPOSER |
GraphicBuffer::USAGE_SW_READ_OFTEN |
@@ -246,7 +251,7 @@
LOG_ALWAYS_FATAL("failed to create composer client");
}
- if (!mClearSlotBuffer) {
+ if (!mClearSlotBuffer && sysprop::clear_slots_with_set_layer_buffer(false)) {
LOG_ALWAYS_FATAL("Failed to allocate a buffer for clearing layer buffer slots");
return;
}
@@ -716,7 +721,11 @@
if (slotsToClear.empty()) {
return Error::NONE;
}
- // Backwards compatible way of clearing buffer is to set the layer buffer with a placeholder
+ // This can be null when the HAL hasn't explicitly enabled this feature.
+ if (mClearSlotBuffer == nullptr) {
+ return Error::NONE;
+ }
+ // Backwards compatible way of clearing buffer is to set the layer buffer with a placeholder
// buffer, using the slot that needs to cleared... tricky.
for (uint32_t slot : slotsToClear) {
// Don't clear the active buffer slot because we need to restore the active buffer after
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
index 5913d4b..163d345 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp
@@ -16,7 +16,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#undef LOG_TAG
-#define LOG_TAG "LayerHierarchy"
+#define LOG_TAG "SurfaceFlinger"
#include "LayerHierarchy.h"
#include "LayerLog.h"
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index b25b731..5389ada 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -42,10 +42,10 @@
class LayerHierarchy {
public:
enum Variant : uint32_t {
- Attached,
- Detached,
- Relative,
- Mirror,
+ Attached, // child of the parent
+ Detached, // child of the parent but currently relative parented to another layer
+ Relative, // relative child of the parent
+ Mirror, // mirrored from another layer
ftl_first = Attached,
ftl_last = Mirror,
};
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index c9eb9c4..1712137 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -17,7 +17,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#undef LOG_TAG
-#define LOG_TAG "LayerLifecycleManager"
+#define LOG_TAG "SurfaceFlinger"
#include "LayerLifecycleManager.h"
#include "Client.h" // temporarily needed for LayerCreationArgs
@@ -51,6 +51,7 @@
it->second.owner.getDebugString().c_str());
}
mAddedLayers.push_back(newLayer.get());
+ mChangedLayers.push_back(newLayer.get());
layer.parentId = linkLayer(layer.parentId, layer.id);
layer.relativeParentId = linkLayer(layer.relativeParentId, layer.id);
if (layer.layerStackToMirror != ui::INVALID_LAYER_STACK) {
@@ -202,6 +203,10 @@
continue;
}
+ if (layer->changes.get() == 0) {
+ mChangedLayers.push_back(layer);
+ }
+
if (transaction.flags & ISurfaceComposer::eAnimation) {
layer->changes |= RequestedLayerState::Changes::Animation;
}
@@ -244,6 +249,7 @@
bgColorLayer->what |= layer_state_t::eColorChanged |
layer_state_t::eDataspaceChanged | layer_state_t::eAlphaChanged;
bgColorLayer->changes |= RequestedLayerState::Changes::Content;
+ mChangedLayers.push_back(bgColorLayer);
mGlobalChanges |= RequestedLayerState::Changes::Content;
}
}
@@ -290,6 +296,7 @@
}
}
mDestroyedLayers.clear();
+ mChangedLayers.clear();
mGlobalChanges.clear();
}
@@ -310,10 +317,25 @@
return mDestroyedLayers;
}
+const std::vector<RequestedLayerState*>& LayerLifecycleManager::getChangedLayers() const {
+ return mChangedLayers;
+}
+
const ftl::Flags<RequestedLayerState::Changes> LayerLifecycleManager::getGlobalChanges() const {
return mGlobalChanges;
}
+const RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) const {
+ if (id == UNASSIGNED_LAYER_ID) {
+ return nullptr;
+ }
+ auto it = mIdToLayer.find(id);
+ if (it == mIdToLayer.end()) {
+ return nullptr;
+ }
+ return &it->second.owner;
+}
+
RequestedLayerState* LayerLifecycleManager::getLayerFromId(uint32_t id) {
if (id == UNASSIGNED_LAYER_ID) {
return nullptr;
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
index f0d2c22..48571bf 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
@@ -76,7 +76,9 @@
void removeLifecycleListener(std::shared_ptr<ILifecycleListener>);
const std::vector<std::unique_ptr<RequestedLayerState>>& getLayers() const;
const std::vector<std::unique_ptr<RequestedLayerState>>& getDestroyedLayers() const;
+ const std::vector<RequestedLayerState*>& getChangedLayers() const;
const ftl::Flags<RequestedLayerState::Changes> getGlobalChanges() const;
+ const RequestedLayerState* getLayerFromId(uint32_t) const;
private:
friend class LayerLifecycleManagerTest;
@@ -111,6 +113,8 @@
// Keeps track of all the layers that were added in order. Changes will be cleared once
// committed.
std::vector<RequestedLayerState*> mAddedLayers;
+ // Keeps track of new and layers with states changes since last commit.
+ std::vector<RequestedLayerState*> mChangedLayers;
};
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index 3caeebe..f0826c6 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -16,7 +16,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#undef LOG_TAG
-#define LOG_TAG "LayerSnapshot"
+#define LOG_TAG "SurfaceFlinger"
#include "LayerSnapshot.h"
@@ -24,6 +24,23 @@
using namespace ftl::flag_operators;
+namespace {
+
+void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame,
+ bool forceFullDamage, Region& outSurfaceDamageRegion) {
+ if (!hasReadyFrame) {
+ outSurfaceDamageRegion.clear();
+ return;
+ }
+ if (forceFullDamage) {
+ outSurfaceDamageRegion = Region::INVALID_REGION;
+ } else {
+ outSurfaceDamageRegion = requested.surfaceDamageRegion;
+ }
+}
+
+} // namespace
+
LayerSnapshot::LayerSnapshot(const RequestedLayerState& state,
const LayerHierarchy::TraversalPath& path)
: path(path) {
@@ -51,9 +68,11 @@
uid = state.ownerUid;
pid = state.ownerPid;
changes = RequestedLayerState::Changes::Created;
+ clientChanges = 0;
mirrorRootPath = path.variant == LayerHierarchy::Variant::Mirror
? path
: LayerHierarchy::TraversalPath::ROOT;
+ reachablilty = LayerSnapshot::Reachablilty::Unreachable;
}
// As documented in libhardware header, formats in the range
@@ -131,6 +150,10 @@
}
bool LayerSnapshot::getIsVisible() const {
+ if (reachablilty != LayerSnapshot::Reachablilty::Reachable) {
+ return false;
+ }
+
if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) {
return false;
}
@@ -148,12 +171,16 @@
std::string LayerSnapshot::getIsVisibleReason() const {
// not visible
- if (handleSkipScreenshotFlag & outputFilter.toInternalDisplay) return "eLayerSkipScreenshot";
- if (!hasSomethingToDraw()) return "!hasSomethingToDraw";
- if (invalidTransform) return "invalidTransform";
+ if (reachablilty == LayerSnapshot::Reachablilty::Unreachable)
+ return "layer not reachable from root";
+ if (reachablilty == LayerSnapshot::Reachablilty::ReachableByRelativeParent)
+ return "layer only reachable via relative parent";
if (isHiddenByPolicyFromParent) return "hidden by parent or layer flag";
if (isHiddenByPolicyFromRelativeParent) return "hidden by relative parent";
+ 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";
// visible
std::stringstream reason;
@@ -177,8 +204,9 @@
}
bool LayerSnapshot::hasInputInfo() const {
- return inputInfo.token != nullptr ||
- inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL);
+ return (inputInfo.token != nullptr ||
+ inputInfo.inputConfig.test(gui::WindowInfo::InputConfig::NO_INPUT_CHANNEL)) &&
+ reachablilty == Reachablilty::Reachable;
}
std::string LayerSnapshot::getDebugString() const {
@@ -191,8 +219,16 @@
<< " geomLayerTransform={tx=" << geomLayerTransform.tx()
<< ",ty=" << geomLayerTransform.ty() << "}"
<< "}";
- debug << " input{ touchCropId=" << touchCropId
- << " replaceTouchableRegionWithCrop=" << inputInfo.replaceTouchableRegionWithCrop << "}";
+ if (hasInputInfo()) {
+ debug << " input{"
+ << "(" << inputInfo.inputConfig.string() << ")";
+ if (touchCropId != UNASSIGNED_LAYER_ID) debug << " touchCropId=" << touchCropId;
+ if (inputInfo.replaceTouchableRegionWithCrop) debug << " replaceTouchableRegionWithCrop";
+ auto touchableRegion = inputInfo.touchableRegion.getBounds();
+ debug << " touchableRegion={" << touchableRegion.left << "," << touchableRegion.top << ","
+ << touchableRegion.bottom << "," << touchableRegion.right << "}"
+ << "}";
+ }
return debug.str();
}
@@ -203,4 +239,172 @@
return geomBufferSize.toFloatRect();
}
+Hwc2::IComposerClient::BlendMode LayerSnapshot::getBlendMode(
+ const RequestedLayerState& requested) const {
+ auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
+ if (alpha != 1.0f || !contentOpaque) {
+ blendMode = requested.premultipliedAlpha ? Hwc2::IComposerClient::BlendMode::PREMULTIPLIED
+ : Hwc2::IComposerClient::BlendMode::COVERAGE;
+ }
+ return blendMode;
+}
+
+void LayerSnapshot::merge(const RequestedLayerState& requested, bool forceUpdate,
+ bool displayChanges, bool forceFullDamage,
+ uint32_t displayRotationFlags) {
+ clientChanges = requested.what;
+ changes = requested.changes;
+ contentDirty = requested.what & layer_state_t::CONTENT_DIRTY;
+ // TODO(b/238781169) scope down the changes to only buffer updates.
+ hasReadyFrame = requested.hasReadyFrame();
+ sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
+ updateSurfaceDamage(requested, hasReadyFrame, forceFullDamage, surfaceDamage);
+
+ if (forceUpdate || requested.what & layer_state_t::eTransparentRegionChanged) {
+ transparentRegionHint = requested.transparentRegion;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eFlagsChanged) {
+ layerOpaqueFlagSet =
+ (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eBufferTransformChanged) {
+ geomBufferTransform = requested.bufferTransform;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eTransformToDisplayInverseChanged) {
+ geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eDataspaceChanged) {
+ dataspace = requested.dataspace;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eExtendedRangeBrightnessChanged) {
+ currentHdrSdrRatio = requested.currentHdrSdrRatio;
+ desiredHdrSdrRatio = requested.desiredHdrSdrRatio;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eCachingHintChanged) {
+ cachingHint = requested.cachingHint;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eHdrMetadataChanged) {
+ hdrMetadata = requested.hdrMetadata;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eSidebandStreamChanged) {
+ sidebandStream = requested.sidebandStream;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eShadowRadiusChanged) {
+ shadowRadius = requested.shadowRadius;
+ shadowSettings.length = requested.shadowRadius;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eFrameRateSelectionPriority) {
+ frameRateSelectionPriority = requested.frameRateSelectionPriority;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eColorSpaceAgnosticChanged) {
+ isColorspaceAgnostic = requested.colorSpaceAgnostic;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eDimmingEnabledChanged) {
+ dimmingEnabled = requested.dimmingEnabled;
+ }
+ if (forceUpdate || requested.what & layer_state_t::eCropChanged) {
+ geomCrop = requested.crop;
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eFlagsChanged | layer_state_t::eBufferChanged |
+ layer_state_t::eSidebandStreamChanged)) {
+ compositionType = requested.getCompositionType();
+ }
+
+ if (forceUpdate || requested.what & layer_state_t::eInputInfoChanged) {
+ if (requested.windowInfoHandle) {
+ inputInfo = *requested.windowInfoHandle->getInfo();
+ } else {
+ inputInfo = {};
+ // b/271132344 revisit this and see if we can always use the layers uid/pid
+ inputInfo.name = requested.name;
+ inputInfo.ownerUid = requested.ownerUid;
+ inputInfo.ownerPid = requested.ownerPid;
+ }
+ inputInfo.id = static_cast<int32_t>(uniqueSequence);
+ touchCropId = requested.touchCropId;
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eColorChanged | layer_state_t::eBufferChanged |
+ layer_state_t::eSidebandStreamChanged)) {
+ color.rgb = requested.getColor().rgb;
+ }
+
+ if (forceUpdate || requested.what & layer_state_t::eBufferChanged) {
+ acquireFence =
+ (requested.externalTexture &&
+ requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
+ ? requested.bufferData->acquireFence
+ : Fence::NO_FENCE;
+ buffer = requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
+ externalTexture = requested.externalTexture;
+ frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
+ hasProtectedContent = requested.externalTexture &&
+ requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
+ geomUsesSourceCrop = hasBufferOrSidebandStream();
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eCropChanged | layer_state_t::eBufferCropChanged |
+ layer_state_t::eBufferTransformChanged |
+ layer_state_t::eTransformToDisplayInverseChanged) ||
+ requested.changes.test(RequestedLayerState::Changes::BufferSize) || displayChanges) {
+ bufferSize = requested.getBufferSize(displayRotationFlags);
+ geomBufferSize = bufferSize;
+ croppedBufferSize = requested.getCroppedBufferSize(bufferSize);
+ geomContentCrop = requested.getBufferCrop();
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eFlagsChanged | layer_state_t::eDestinationFrameChanged |
+ layer_state_t::ePositionChanged | layer_state_t::eMatrixChanged |
+ layer_state_t::eBufferTransformChanged |
+ layer_state_t::eTransformToDisplayInverseChanged) ||
+ requested.changes.test(RequestedLayerState::Changes::BufferSize) || displayChanges) {
+ localTransform = requested.getTransform(displayRotationFlags);
+ localTransformInverse = localTransform.inverse();
+ }
+
+ if (forceUpdate || requested.what & (layer_state_t::eColorChanged) ||
+ requested.changes.test(RequestedLayerState::Changes::BufferSize)) {
+ color.rgb = requested.getColor().rgb;
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged |
+ layer_state_t::eApiChanged)) {
+ isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
+ requested.api == NATIVE_WINDOW_API_MEDIA &&
+ requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged |
+ layer_state_t::eApiChanged | layer_state_t::eShadowRadiusChanged |
+ layer_state_t::eBlurRegionsChanged | layer_state_t::eStretchChanged)) {
+ forceClientComposition = isHdrY410 || shadowSettings.length > 0 ||
+ requested.blurRegions.size() > 0 || stretchEffect.hasEffect();
+ }
+
+ if (forceUpdate ||
+ requested.what &
+ (layer_state_t::eColorChanged | layer_state_t::eShadowRadiusChanged |
+ layer_state_t::eBlurRegionsChanged | layer_state_t::eBackgroundBlurRadiusChanged |
+ layer_state_t::eCornerRadiusChanged | layer_state_t::eAlphaChanged |
+ layer_state_t::eFlagsChanged | layer_state_t::eBufferChanged |
+ layer_state_t::eSidebandStreamChanged)) {
+ contentOpaque = isContentOpaque();
+ isOpaque = contentOpaque && !roundedCorner.hasRoundedCorners() && color.a == 1.f;
+ blendMode = getBlendMode(requested);
+ }
+}
+
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.h b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
index b167d3e..2f45d52 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.h
@@ -18,6 +18,7 @@
#include <compositionengine/LayerFECompositionState.h>
#include <renderengine/LayerSettings.h>
+#include "DisplayHardware/ComposerHal.h"
#include "LayerHierarchy.h"
#include "RequestedLayerState.h"
#include "Scheduler/LayerInfo.h"
@@ -57,6 +58,7 @@
bool isHiddenByPolicyFromParent = false;
bool isHiddenByPolicyFromRelativeParent = false;
ftl::Flags<RequestedLayerState::Changes> changes;
+ uint64_t clientChanges = 0;
// 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.
@@ -93,11 +95,37 @@
bool handleSkipScreenshotFlag = false;
int32_t frameRateSelectionPriority;
LayerHierarchy::TraversalPath mirrorRootPath;
- bool unreachable = true;
uint32_t touchCropId;
- uid_t uid;
- pid_t pid;
+ gui::Uid uid = gui::Uid::INVALID;
+ gui::Pid pid = gui::Pid::INVALID;
ChildState childState;
+ enum class Reachablilty : uint32_t {
+ // Can traverse the hierarchy from a root node and reach this snapshot
+ Reachable,
+ // Cannot traverse the hierarchy from a root node and reach this snapshot
+ Unreachable,
+ // Can only reach this node from a relative parent. This means the nodes parents are
+ // not reachable.
+ // See example scenario:
+ // ROOT
+ // ├── 1
+ // │ ├── 11
+ // │ │ └── 111
+ // │ ├── 12
+ // │ │ └ - 111 (relative)
+ // │ ├── 13
+ // │ └── 14
+ // │ └ * 12 (mirroring)
+ // └── 2
+ // 111 will create two snapshots, first when visited from 1 -> 12 or 1 -> 11 and the
+ // second when visited from 1 -> 14 -> 12. Because its parent 11 doesn't exist in the
+ // mirrored hierarchy, the second snapshot will be marked as ReachableByRelativeParent.
+ // This snapshot doesn't have any valid properties because it cannot inherit from its
+ // parent. Therefore, snapshots that are not reachable will be ignored for composition
+ // and input.
+ ReachableByRelativeParent
+ };
+ Reachablilty reachablilty;
static bool isOpaqueFormat(PixelFormat format);
static bool isTransformValid(const ui::Transform& t);
@@ -116,6 +144,10 @@
std::string getIsVisibleReason() const;
bool hasInputInfo() const;
FloatRect sourceBounds() const;
+ Hwc2::IComposerClient::BlendMode getBlendMode(const RequestedLayerState& requested) const;
+
+ void merge(const RequestedLayerState& requested, bool forceUpdate, bool displayChanges,
+ bool forceFullDamage, uint32_t displayRotationFlags);
};
} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index a266493..21f0a67 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -17,13 +17,14 @@
// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#undef LOG_TAG
-#define LOG_TAG "LayerSnapshotBuilder"
+#define LOG_TAG "SurfaceFlinger"
#include <numeric>
#include <optional>
#include <ftl/small_map.h>
#include <gui/TraceUtils.h>
+#include <ui/DisplayMap.h>
#include <ui/FloatRect.h>
#include "DisplayHardware/HWC2.h"
@@ -257,19 +258,6 @@
return blendMode;
}
-void updateSurfaceDamage(const RequestedLayerState& requested, bool hasReadyFrame,
- bool forceFullDamage, Region& outSurfaceDamageRegion) {
- if (!hasReadyFrame) {
- outSurfaceDamageRegion.clear();
- return;
- }
- if (forceFullDamage) {
- outSurfaceDamageRegion = Region::INVALID_REGION;
- } else {
- outSurfaceDamageRegion = requested.surfaceDamageRegion;
- }
-}
-
void updateVisibility(LayerSnapshot& snapshot, bool visible) {
snapshot.isVisible = visible;
@@ -287,6 +275,8 @@
const bool visibleForInput =
snapshot.hasInputInfo() ? snapshot.canReceiveInput() : snapshot.isVisible;
snapshot.inputInfo.setInputConfig(gui::WindowInfo::InputConfig::NOT_VISIBLE, !visibleForInput);
+ LLOGV(snapshot.sequence, "updating visibility %s %s", visible ? "true" : "false",
+ snapshot.getDebugString().c_str());
}
bool needsInputInfo(const LayerSnapshot& snapshot, const RequestedLayerState& requested) {
@@ -329,18 +319,31 @@
void clearChanges(LayerSnapshot& snapshot) {
snapshot.changes.clear();
+ snapshot.clientChanges = 0;
snapshot.contentDirty = false;
snapshot.hasReadyFrame = false;
snapshot.sidebandStreamHasFrame = false;
snapshot.surfaceDamage.clear();
}
+// TODO (b/259407931): Remove.
+uint32_t getPrimaryDisplayRotationFlags(
+ const ui::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displays) {
+ for (auto& [_, display] : displays) {
+ if (display.isPrimary) {
+ return display.rotationFlags;
+ }
+ }
+ return 0;
+}
+
} // namespace
LayerSnapshot LayerSnapshotBuilder::getRootSnapshot() {
LayerSnapshot snapshot;
snapshot.path = LayerHierarchy::TraversalPath::ROOT;
snapshot.changes = ftl::Flags<RequestedLayerState::Changes>();
+ snapshot.clientChanges = 0;
snapshot.isHiddenByPolicyFromParent = false;
snapshot.isHiddenByPolicyFromRelativeParent = false;
snapshot.parentTransform.reset();
@@ -374,43 +377,44 @@
}
bool LayerSnapshotBuilder::tryFastUpdate(const Args& args) {
- if (args.forceUpdate != ForceUpdateFlags::NONE || args.displayChanges) {
- // force update requested, or we have display changes, so skip the fast path
- return false;
- }
+ const bool forceUpdate = args.forceUpdate != ForceUpdateFlags::NONE;
- if (args.layerLifecycleManager.getGlobalChanges().get() == 0) {
+ if (args.layerLifecycleManager.getGlobalChanges().get() == 0 && !forceUpdate &&
+ !args.displayChanges) {
return true;
}
- if (args.layerLifecycleManager.getGlobalChanges() != RequestedLayerState::Changes::Content) {
- // We have changes that require us to walk the hierarchy and update child layers.
- // No fast path for you.
- return false;
- }
-
// There are only content changes which do not require any child layer snapshots to be updated.
ALOGV("%s", __func__);
ATRACE_NAME("FastPath");
- // Collect layers with changes
- ftl::SmallMap<uint32_t, RequestedLayerState*, 10> layersWithChanges;
- for (auto& layer : args.layerLifecycleManager.getLayers()) {
- if (layer->changes.test(RequestedLayerState::Changes::Content)) {
- layersWithChanges.emplace_or_replace(layer->id, layer.get());
+ uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
+ if (forceUpdate || args.displayChanges) {
+ for (auto& snapshot : mSnapshots) {
+ const RequestedLayerState* requested =
+ args.layerLifecycleManager.getLayerFromId(snapshot->path.id);
+ if (!requested) continue;
+ snapshot->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
+ primaryDisplayRotationFlags);
+ }
+ return false;
+ }
+
+ // Walk through all the updated requested layer states and update the corresponding snapshots.
+ for (const RequestedLayerState* requested : args.layerLifecycleManager.getChangedLayers()) {
+ auto range = mIdToSnapshots.equal_range(requested->id);
+ for (auto it = range.first; it != range.second; it++) {
+ it->second->merge(*requested, forceUpdate, args.displayChanges, args.forceFullDamage,
+ primaryDisplayRotationFlags);
}
}
- // Walk through the snapshots, clearing previous change flags and updating the snapshots
- // if needed.
- for (auto& snapshot : mSnapshots) {
- 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);
- }
+ if ((args.layerLifecycleManager.getGlobalChanges().get() &
+ ~(RequestedLayerState::Changes::Content | RequestedLayerState::Changes::Buffer).get()) !=
+ 0) {
+ // We have changes that require us to walk the hierarchy and update child layers.
+ // No fast path for you.
+ return false;
}
return true;
}
@@ -429,7 +433,15 @@
if (args.forceUpdate == ForceUpdateFlags::HIERARCHY) {
mRootSnapshot.changes |=
RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Visibility;
+ mRootSnapshot.clientChanges |= layer_state_t::eReparent;
}
+
+ for (auto& snapshot : mSnapshots) {
+ if (snapshot->reachablilty == LayerSnapshot::Reachablilty::Reachable) {
+ snapshot->reachablilty = LayerSnapshot::Reachablilty::Unreachable;
+ }
+ }
+
LayerHierarchy::TraversalPath root = LayerHierarchy::TraversalPath::ROOT;
if (args.root.getLayer()) {
// The hierarchy can have a root layer when used for screenshots otherwise, it will have
@@ -468,13 +480,26 @@
auto it = mSnapshots.begin();
while (it < mSnapshots.end()) {
auto& traversalPath = it->get()->path;
- if (!it->get()->unreachable &&
- destroyedLayerIds.find(traversalPath.id) == destroyedLayerIds.end()) {
+ const bool unreachable =
+ it->get()->reachablilty == LayerSnapshot::Reachablilty::Unreachable;
+ const bool isClone = traversalPath.isClone();
+ const bool layerIsDestroyed =
+ destroyedLayerIds.find(traversalPath.id) != destroyedLayerIds.end();
+ const bool destroySnapshot = (unreachable && isClone) || layerIsDestroyed;
+
+ if (!destroySnapshot) {
it++;
continue;
}
- mIdToSnapshot.erase(traversalPath);
+ mPathToSnapshot.erase(traversalPath);
+
+ auto range = mIdToSnapshots.equal_range(traversalPath.id);
+ auto matchingSnapshot =
+ std::find_if(range.first, range.second, [&traversalPath](auto& snapshotWithId) {
+ return snapshotWithId.second->path == traversalPath;
+ });
+ mIdToSnapshots.erase(matchingSnapshot);
mNeedsTouchableRegionCrop.erase(traversalPath);
mSnapshots.back()->globalZ = it->get()->globalZ;
std::iter_swap(it, mSnapshots.end() - 1);
@@ -507,8 +532,12 @@
const RequestedLayerState* layer = hierarchy.getLayer();
LayerSnapshot* snapshot = getSnapshot(traversalPath);
const bool newSnapshot = snapshot == nullptr;
+ uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
if (newSnapshot) {
snapshot = createSnapshot(traversalPath, *layer, parentSnapshot);
+ snapshot->merge(*layer, /*forceUpdate=*/true, /*displayChanges=*/true, args.forceFullDamage,
+ primaryDisplayRotationFlags);
+ snapshot->changes |= RequestedLayerState::Changes::Created;
}
scheduler::LayerInfo::FrameRate oldFrameRate = snapshot->frameRate;
if (traversalPath.isRelative()) {
@@ -546,8 +575,8 @@
}
LayerSnapshot* LayerSnapshotBuilder::getSnapshot(const LayerHierarchy::TraversalPath& id) const {
- auto it = mIdToSnapshot.find(id);
- return it == mIdToSnapshot.end() ? nullptr : it->second;
+ auto it = mPathToSnapshot.find(id);
+ return it == mPathToSnapshot.end() ? nullptr : it->second;
}
LayerSnapshot* LayerSnapshotBuilder::createSnapshot(const LayerHierarchy::TraversalPath& path,
@@ -559,7 +588,9 @@
if (path.isClone() && path.variant != LayerHierarchy::Variant::Mirror) {
snapshot->mirrorRootPath = parentSnapshot.mirrorRootPath;
}
- mIdToSnapshot[path] = snapshot;
+ mPathToSnapshot[path] = snapshot;
+
+ mIdToSnapshots.emplace(path.id, snapshot);
return snapshot;
}
@@ -574,20 +605,15 @@
}
mResortSnapshots = false;
- for (auto& snapshot : mSnapshots) {
- snapshot->unreachable = snapshot->path.isClone();
- }
-
size_t globalZ = 0;
args.root.traverseInZOrder(
[this, &globalZ](const LayerHierarchy&,
const LayerHierarchy::TraversalPath& traversalPath) -> bool {
LayerSnapshot* snapshot = getSnapshot(traversalPath);
if (!snapshot) {
- return false;
+ return true;
}
- snapshot->unreachable = false;
if (snapshot->getIsVisible() || snapshot->hasInputInfo()) {
updateVisibility(*snapshot, snapshot->getIsVisible());
size_t oldZ = snapshot->globalZ;
@@ -610,7 +636,7 @@
mSnapshots[globalZ]->globalZ = globalZ;
/* mark unreachable snapshots as explicitly invisible */
updateVisibility(*mSnapshots[globalZ], false);
- if (mSnapshots[globalZ]->unreachable) {
+ if (mSnapshots[globalZ]->reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
hasUnreachableSnapshots = true;
}
globalZ++;
@@ -634,7 +660,9 @@
snapshot.relativeLayerMetadata = parentSnapshot.relativeLayerMetadata;
}
}
- snapshot.isVisible = snapshot.getIsVisible();
+ if (snapshot.reachablilty == LayerSnapshot::Reachablilty::Unreachable) {
+ snapshot.reachablilty = LayerSnapshot::Reachablilty::ReachableByRelativeParent;
+ }
}
void LayerSnapshotBuilder::updateChildState(LayerSnapshot& snapshot,
@@ -675,16 +703,6 @@
snapshot.relativeLayerMetadata.mMap.clear();
}
-// TODO (b/259407931): Remove.
-uint32_t getPrimaryDisplayRotationFlags(const DisplayInfos& displays) {
- for (auto& [_, display] : displays) {
- if (display.isPrimary) {
- return display.rotationFlags;
- }
- }
- return 0;
-}
-
void LayerSnapshotBuilder::updateSnapshot(LayerSnapshot& snapshot, const Args& args,
const RequestedLayerState& requested,
const LayerSnapshot& parentSnapshot,
@@ -694,82 +712,69 @@
(RequestedLayerState::Changes::Hierarchy | RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::Visibility | RequestedLayerState::Changes::Metadata |
RequestedLayerState::Changes::AffectsChildren |
- RequestedLayerState::Changes::FrameRate);
- snapshot.changes |= parentChanges | requested.changes;
+ RequestedLayerState::Changes::FrameRate | RequestedLayerState::Changes::GameMode);
+ snapshot.changes |= parentChanges;
+ if (args.displayChanges) snapshot.changes |= RequestedLayerState::Changes::Geometry;
+ snapshot.reachablilty = LayerSnapshot::Reachablilty::Reachable;
+ snapshot.clientChanges |= (parentSnapshot.clientChanges & layer_state_t::AFFECTS_CHILDREN);
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 = requested.hasReadyFrame();
- snapshot.sidebandStreamHasFrame = requested.hasSidebandStreamFrame();
- updateSurfaceDamage(requested, snapshot.hasReadyFrame, args.forceFullDamage,
- snapshot.surfaceDamage);
- snapshot.outputFilter.layerStack = parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
- ? requested.layerStack
- : parentSnapshot.outputFilter.layerStack;
- uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
const bool forceUpdate = args.forceUpdate == ForceUpdateFlags::ALL ||
+ snapshot.clientChanges & layer_state_t::eReparent ||
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) {
- snapshot.acquireFence =
- (requested.externalTexture &&
- requested.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged))
- ? requested.bufferData->acquireFence
- : Fence::NO_FENCE;
- snapshot.buffer =
- requested.externalTexture ? requested.externalTexture->getBuffer() : nullptr;
- snapshot.bufferSize = requested.getBufferSize(primaryDisplayRotationFlags);
- snapshot.geomBufferSize = snapshot.bufferSize;
- snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
- snapshot.dataspace = requested.dataspace;
- snapshot.externalTexture = requested.externalTexture;
- snapshot.frameNumber = (requested.bufferData) ? requested.bufferData->frameNumber : 0;
- snapshot.geomBufferTransform = requested.bufferTransform;
- snapshot.geomBufferUsesDisplayInverseTransform = requested.transformToDisplayInverse;
- snapshot.geomContentCrop = requested.getBufferCrop();
- snapshot.geomUsesSourceCrop = snapshot.hasBufferOrSidebandStream();
- snapshot.hasProtectedContent = requested.externalTexture &&
- requested.externalTexture->getUsage() & GRALLOC_USAGE_PROTECTED;
- snapshot.isHdrY410 = requested.dataspace == ui::Dataspace::BT2020_ITU_PQ &&
- requested.api == NATIVE_WINDOW_API_MEDIA &&
- requested.bufferData->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102;
- snapshot.sidebandStream = requested.sidebandStream;
- snapshot.transparentRegionHint = requested.transparentRegion;
- snapshot.color.rgb = requested.getColor().rgb;
- snapshot.currentHdrSdrRatio = requested.currentHdrSdrRatio;
- snapshot.desiredHdrSdrRatio = requested.desiredHdrSdrRatio;
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eLayerStackChanged) {
+ // If root layer, use the layer stack otherwise get the parent's layer stack.
+ snapshot.outputFilter.layerStack =
+ parentSnapshot.path == LayerHierarchy::TraversalPath::ROOT
+ ? requested.layerStack
+ : parentSnapshot.outputFilter.layerStack;
}
if (snapshot.isHiddenByPolicyFromParent &&
!snapshot.changes.test(RequestedLayerState::Changes::Created)) {
if (forceUpdate ||
- snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
- RequestedLayerState::Changes::Geometry |
+ snapshot.changes.any(RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::Input)) {
updateInput(snapshot, requested, parentSnapshot, path, args);
}
return;
}
- if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
- // If root layer, use the layer stack otherwise get the parent's layer stack.
+ if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Mirror)) {
+ // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
+ // marked as skip capture
+ snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
+ (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
+ }
+
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eAlphaChanged) {
snapshot.color.a = parentSnapshot.color.a * requested.color.a;
snapshot.alpha = snapshot.color.a;
snapshot.inputInfo.alpha = snapshot.color.a;
+ }
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eFlagsChanged) {
snapshot.isSecure =
parentSnapshot.isSecure || (requested.flags & layer_state_t::eLayerSecure);
- snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
snapshot.outputFilter.toInternalDisplay = parentSnapshot.outputFilter.toInternalDisplay ||
(requested.flags & layer_state_t::eLayerSkipScreenshot);
+ }
+
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eTrustedOverlayChanged) {
+ snapshot.isTrustedOverlay = parentSnapshot.isTrustedOverlay || requested.isTrustedOverlay;
+ }
+
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eStretchChanged) {
snapshot.stretchEffect = (requested.stretchEffect.hasEffect())
? requested.stretchEffect
: parentSnapshot.stretchEffect;
+ }
+
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eColorTransformChanged) {
if (!parentSnapshot.colorTransformIsIdentity) {
snapshot.colorTransform = parentSnapshot.colorTransform * requested.colorTransform;
snapshot.colorTransformIsIdentity = false;
@@ -777,16 +782,20 @@
snapshot.colorTransform = requested.colorTransform;
snapshot.colorTransformIsIdentity = !requested.hasColorTransform;
}
+ }
+
+ if (forceUpdate || snapshot.changes.test(RequestedLayerState::Changes::GameMode)) {
snapshot.gameMode = requested.metadata.has(gui::METADATA_GAME_MODE)
? requested.gameMode
: parentSnapshot.gameMode;
- // Display mirrors are always placed in a VirtualDisplay so we never want to capture layers
- // marked as skip capture
- snapshot.handleSkipScreenshotFlag = parentSnapshot.handleSkipScreenshotFlag ||
- (requested.layerStackToMirror != ui::INVALID_LAYER_STACK);
+ updateMetadata(snapshot, requested, args);
+ if (args.includeMetadata) {
+ snapshot.layerMetadata = parentSnapshot.layerMetadata;
+ snapshot.layerMetadata.merge(requested.metadata);
+ }
}
- if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren) ||
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eFixedTransformHintChanged ||
args.displayChanges) {
snapshot.fixedTransformHint = requested.fixedTransformHint != ui::Transform::ROT_INVALID
? requested.fixedTransformHint
@@ -802,9 +811,7 @@
}
}
- if (forceUpdate ||
- snapshot.changes.any(RequestedLayerState::Changes::FrameRate |
- RequestedLayerState::Changes::Hierarchy)) {
+ if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::FrameRate)) {
snapshot.frameRate = (requested.requestedFrameRate.rate.isValid() ||
(requested.requestedFrameRate.type ==
scheduler::LayerInfo::FrameRateCompatibility::NoVote))
@@ -812,23 +819,10 @@
: 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;
- snapshot.layerOpaqueFlagSet =
- (requested.flags & layer_state_t::eLayerOpaque) == layer_state_t::eLayerOpaque;
- snapshot.cachingHint = requested.cachingHint;
- snapshot.frameRateSelectionPriority = requested.frameRateSelectionPriority;
- }
-
- if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Content) ||
- snapshot.changes.any(RequestedLayerState::Changes::AffectsChildren)) {
- snapshot.color.rgb = requested.getColor().rgb;
- snapshot.isColorspaceAgnostic = requested.colorSpaceAgnostic;
+ if (forceUpdate ||
+ snapshot.clientChanges &
+ (layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
+ layer_state_t::eAlphaChanged)) {
snapshot.backgroundBlurRadius = args.supportsBlur
? static_cast<int>(parentSnapshot.color.a * (float)requested.backgroundBlurRadius)
: 0;
@@ -836,29 +830,30 @@
for (auto& region : snapshot.blurRegions) {
region.alpha = region.alpha * snapshot.color.a;
}
- snapshot.hdrMetadata = requested.hdrMetadata;
}
- if (forceUpdate ||
- snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
- RequestedLayerState::Changes::Geometry)) {
+ if (forceUpdate || snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
+ uint32_t primaryDisplayRotationFlags = getPrimaryDisplayRotationFlags(args.displays);
updateLayerBounds(snapshot, requested, parentSnapshot, primaryDisplayRotationFlags);
+ }
+
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eCornerRadiusChanged ||
+ snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
updateRoundedCorner(snapshot, requested, parentSnapshot);
}
+ if (forceUpdate || snapshot.clientChanges & layer_state_t::eShadowRadiusChanged ||
+ snapshot.changes.any(RequestedLayerState::Changes::Geometry)) {
+ updateShadows(snapshot, requested, args.globalShadowSettings);
+ }
+
if (forceUpdate ||
- snapshot.changes.any(RequestedLayerState::Changes::Hierarchy |
- RequestedLayerState::Changes::Geometry |
+ snapshot.changes.any(RequestedLayerState::Changes::Geometry |
RequestedLayerState::Changes::Input)) {
updateInput(snapshot, requested, parentSnapshot, path, args);
}
// computed snapshot properties
- updateShadows(snapshot, requested, args.globalShadowSettings);
- if (args.includeMetadata) {
- snapshot.layerMetadata = parentSnapshot.layerMetadata;
- snapshot.layerMetadata.merge(requested.metadata);
- }
snapshot.forceClientComposition = snapshot.isHdrY410 || snapshot.shadowSettings.length > 0 ||
requested.blurRegions.size() > 0 || snapshot.stretchEffect.hasEffect();
snapshot.contentOpaque = snapshot.isContentOpaque();
@@ -914,10 +909,6 @@
const RequestedLayerState& requested,
const LayerSnapshot& parentSnapshot,
uint32_t primaryDisplayRotationFlags) {
- snapshot.croppedBufferSize = requested.getCroppedBufferSize(snapshot.bufferSize);
- snapshot.geomCrop = requested.crop;
- snapshot.localTransform = requested.getTransform(primaryDisplayRotationFlags);
- snapshot.localTransformInverse = snapshot.localTransform.inverse();
snapshot.geomLayerTransform = parentSnapshot.geomLayerTransform * snapshot.localTransform;
const bool transformWasInvalid = snapshot.invalidTransform;
snapshot.invalidTransform = !LayerSnapshot::isTransformValid(snapshot.geomLayerTransform);
@@ -974,11 +965,8 @@
}
}
-void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot,
- const RequestedLayerState& requested,
+void LayerSnapshotBuilder::updateShadows(LayerSnapshot& snapshot, const RequestedLayerState&,
const renderengine::ShadowSettings& globalShadowSettings) {
- snapshot.shadowRadius = requested.shadowRadius;
- snapshot.shadowSettings.length = requested.shadowRadius;
if (snapshot.shadowRadius > 0.f) {
snapshot.shadowSettings = globalShadowSettings;
@@ -1058,10 +1046,11 @@
snapshot.inputInfo.inputConfig |= gui::WindowInfo::InputConfig::DROP_INPUT;
}
- auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
- if (cropLayerSnapshot) {
+ if (requested.touchCropId != UNASSIGNED_LAYER_ID || path.isClone()) {
mNeedsTouchableRegionCrop.insert(path);
- } else if (snapshot.inputInfo.replaceTouchableRegionWithCrop) {
+ }
+ auto cropLayerSnapshot = getSnapshot(requested.touchCropId);
+ if (!cropLayerSnapshot && snapshot.inputInfo.replaceTouchableRegionWithCrop) {
FloatRect inputBounds = getInputBounds(snapshot, /*fillParentBounds=*/true).first;
Rect inputBoundsInDisplaySpace =
getInputBoundsInDisplaySpace(snapshot, inputBounds, displayInfo.transform);
@@ -1081,8 +1070,6 @@
// Cloned layers shouldn't handle watch outside since their z order is not determined by
// WM or the client.
snapshot.inputInfo.inputConfig.clear(gui::WindowInfo::InputConfig::WATCH_OUTSIDE_TOUCH);
-
- mNeedsTouchableRegionCrop.insert(path);
}
}
@@ -1139,7 +1126,7 @@
RequestedLayerState::Changes::Input;
if (args.forceUpdate != ForceUpdateFlags::ALL &&
- !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT)) {
+ !args.layerLifecycleManager.getGlobalChanges().any(AFFECTS_INPUT) && !args.displayChanges) {
return;
}
@@ -1148,6 +1135,8 @@
if (!snapshot) {
continue;
}
+ LLOGV(snapshot->sequence, "updateTouchableRegionCrop=%s",
+ snapshot->getDebugString().c_str());
const std::optional<frontend::DisplayInfo> displayInfoOpt =
args.displays.get(snapshot->outputFilter.layerStack);
static frontend::DisplayInfo sDefaultInfo = {.isSecure = false};
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 2e46dc6..c81a5d2 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -122,7 +122,9 @@
std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*,
LayerHierarchy::TraversalPathHash>
- mIdToSnapshot;
+ mPathToSnapshot;
+ std::multimap<uint32_t, LayerSnapshot*> mIdToSnapshots;
+
// Track snapshots that needs touchable region crop from other snapshots
std::unordered_set<LayerHierarchy::TraversalPath, LayerHierarchy::TraversalPathHash>
mNeedsTouchableRegionCrop;
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index bde2d05..5738262 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+// #define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#undef LOG_TAG
-#define LOG_TAG "RequestedLayerState"
+#define LOG_TAG "SurfaceFlinger"
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -132,12 +133,16 @@
const half oldAlpha = color.a;
const bool hadBuffer = externalTexture != nullptr;
uint64_t oldFramenumber = hadBuffer ? bufferData->frameNumber : 0;
+ const ui::Size oldBufferSize = hadBuffer
+ ? ui::Size(externalTexture->getWidth(), externalTexture->getHeight())
+ : ui::Size();
const bool hadSideStream = sidebandStream != nullptr;
const layer_state_t& clientState = resolvedComposerState.state;
const bool hadBlur = hasBlur();
uint64_t clientChanges = what | layer_state_t::diff(clientState);
layer_state_t::merge(clientState);
what = clientChanges;
+ LLOGV(layerId, "requested=%" PRIu64 "flags=%" PRIu64, clientState.what, clientChanges);
if (clientState.what & layer_state_t::eFlagsChanged) {
if ((oldFlags ^ flags) & layer_state_t::eLayerHidden) {
@@ -154,6 +159,13 @@
const bool hasBuffer = externalTexture != nullptr;
if (hasBuffer || hasBuffer != hadBuffer) {
changes |= RequestedLayerState::Changes::Buffer;
+ const ui::Size newBufferSize = hasBuffer
+ ? ui::Size(externalTexture->getWidth(), externalTexture->getHeight())
+ : ui::Size();
+ if (oldBufferSize != newBufferSize) {
+ changes |= RequestedLayerState::Changes::BufferSize;
+ changes |= RequestedLayerState::Changes::Geometry;
+ }
}
if (hasBuffer != hadBuffer) {
@@ -281,7 +293,7 @@
// child layers.
if (static_cast<int32_t>(gameMode) != requestedGameMode) {
gameMode = static_cast<gui::GameMode>(requestedGameMode);
- changes |= RequestedLayerState::Changes::AffectsChildren;
+ changes |= RequestedLayerState::Changes::GameMode;
}
}
}
@@ -372,7 +384,7 @@
return (flags & layer_state_t::eLayerHidden) == layer_state_t::eLayerHidden;
};
half4 RequestedLayerState::getColor() const {
- if ((sidebandStream != nullptr) || (externalTexture != nullptr)) {
+ if (sidebandStream || externalTexture) {
return {0._hf, 0._hf, 0._hf, color.a};
}
return color;
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.h b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
index 0ef50bc..02e3bac 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.h
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.h
@@ -54,6 +54,8 @@
Buffer = 1u << 15,
SidebandStream = 1u << 16,
Animation = 1u << 17,
+ BufferSize = 1u << 18,
+ GameMode = 1u << 19,
};
static Rect reduce(const Rect& win, const Region& exclude);
RequestedLayerState(const LayerCreationArgs&);
@@ -91,10 +93,10 @@
const uint32_t textureName;
// The owner of the layer. If created from a non system process, it will be the calling uid.
// If created from a system process, the value can be passed in.
- const uid_t ownerUid;
+ const gui::Uid ownerUid;
// The owner pid of the layer. If created from a non system process, it will be the calling pid.
// If created from a system process, the value can be passed in.
- const pid_t ownerPid;
+ const gui::Pid ownerPid;
bool dataspaceRequested;
bool hasColorTransform;
bool premultipliedAlpha{true};
diff --git a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
index 9cbe0bb..fa8eb3c 100644
--- a/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
+++ b/services/surfaceflinger/FrontEnd/TransactionHandler.cpp
@@ -16,7 +16,7 @@
// #define LOG_NDEBUG 0
#undef LOG_TAG
-#define LOG_TAG "TransactionHandler"
+#define LOG_TAG "SurfaceFlinger"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <cutils/trace.h>
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 427a85c..1c7581b 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -428,7 +428,7 @@
layerInfo->set_is_relative_of(requestedState.isRelativeOf);
- layerInfo->set_owner_uid(requestedState.ownerUid);
+ layerInfo->set_owner_uid(requestedState.ownerUid.val());
if ((traceFlags & LayerTracing::TRACE_INPUT) && snapshot.hasInputInfo()) {
LayerProtoHelper::writeToProto(snapshot.inputInfo, {},
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9c3fb09..8ffc3c3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2172,6 +2172,7 @@
bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, frontend::Update& update,
bool transactionsFlushed,
bool& outTransactionsAreEmpty) {
+ ATRACE_CALL();
bool needsTraversal = false;
if (transactionsFlushed) {
needsTraversal |= commitMirrorDisplays(vsyncId);
@@ -2224,7 +2225,7 @@
bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, frontend::Update& update,
bool transactionsFlushed, bool& outTransactionsAreEmpty) {
using Changes = frontend::RequestedLayerState::Changes;
- ATRACE_NAME("updateLayerSnapshots");
+ ATRACE_CALL();
{
mLayerLifecycleManager.addLayers(std::move(update.newLayers));
mLayerLifecycleManager.applyTransactions(update.transactions);
@@ -8164,7 +8165,7 @@
if (layerStack && snapshot->outputFilter.layerStack != *layerStack) {
return;
}
- if (uid != CaptureArgs::UNSET_UID && snapshot->uid != uid) {
+ if (uid != CaptureArgs::UNSET_UID && snapshot->uid != gui::Uid(uid)) {
return;
}
if (!snapshot->hasSomethingToDraw()) {
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 20fa091..96c8b54 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -375,5 +375,9 @@
return SurfaceFlingerProperties::ignore_hdr_camera_layers().value_or(defaultValue);
}
+bool clear_slots_with_set_layer_buffer(bool defaultValue) {
+ return SurfaceFlingerProperties::clear_slots_with_set_layer_buffer().value_or(defaultValue);
+}
+
} // namespace sysprop
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 080feee..951f8f8 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -102,6 +102,8 @@
bool ignore_hdr_camera_layers(bool defaultValue);
+bool clear_slots_with_set_layer_buffer(bool defaultValue);
+
} // namespace sysprop
} // namespace android
#endif // SURFACEFLINGERPROPERTIES_H_
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index bcbe21a..689f51a 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -470,4 +470,18 @@
scope: Public
access: Readonly
prop_name: "ro.surface_flinger.ignore_hdr_camera_layers"
-}
\ No newline at end of file
+}
+
+# When enabled, SurfaceFlinger will attempt to clear the per-layer HAL buffer cache slots for
+# buffers when they are evicted from the app cache by using additional setLayerBuffer commands.
+# Ideally, this behavior would always be enabled to reduce graphics memory consumption. However,
+# Some HAL implementations may not support the additional setLayerBuffer commands used to clear
+# the cache slots.
+prop {
+ api_name: "clear_slots_with_set_layer_buffer"
+ type: Boolean
+ scope: Public
+ access: Readonly
+ prop_name: "ro.surface_flinger.clear_slots_with_set_layer_buffer"
+}
+
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index 348a462..9660ff3 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -1,6 +1,10 @@
props {
module: "android.sysprop.SurfaceFlingerProperties"
prop {
+ api_name: "clear_slots_with_set_layer_buffer"
+ prop_name: "ro.surface_flinger.clear_slots_with_set_layer_buffer"
+ }
+ prop {
api_name: "color_space_agnostic_dataspace"
type: Long
prop_name: "ro.surface_flinger.color_space_agnostic_dataspace"
diff --git a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 12cf070..5da893e 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -228,6 +228,7 @@
setAlpha(1, 0.5);
setAlpha(122, 0.5);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot(1)->alpha, 0.5f);
EXPECT_EQ(getSnapshot(12)->alpha, 0.5f);
EXPECT_EQ(getSnapshot(1221)->alpha, 0.25f);
}
@@ -236,28 +237,30 @@
TEST_F(LayerSnapshotTest, UpdateClearsPreviousChangeStates) {
setCrop(1, Rect(1, 2, 3, 4));
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- EXPECT_TRUE(getSnapshot(1)->changes.get() != 0);
- EXPECT_TRUE(getSnapshot(11)->changes.get() != 0);
+ EXPECT_TRUE(getSnapshot(1)->changes.test(RequestedLayerState::Changes::Geometry));
+ EXPECT_TRUE(getSnapshot(11)->changes.test(RequestedLayerState::Changes::Geometry));
setCrop(2, Rect(1, 2, 3, 4));
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- EXPECT_TRUE(getSnapshot(2)->changes.get() != 0);
- EXPECT_TRUE(getSnapshot(1)->changes.get() == 0);
- EXPECT_TRUE(getSnapshot(11)->changes.get() == 0);
+ EXPECT_TRUE(getSnapshot(2)->changes.test(RequestedLayerState::Changes::Geometry));
+ EXPECT_FALSE(getSnapshot(1)->changes.test(RequestedLayerState::Changes::Geometry));
+ EXPECT_FALSE(getSnapshot(11)->changes.test(RequestedLayerState::Changes::Geometry));
}
TEST_F(LayerSnapshotTest, FastPathClearsPreviousChangeStates) {
setColor(11, {1._hf, 0._hf, 0._hf});
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- EXPECT_TRUE(getSnapshot(11)->changes.get() != 0);
- EXPECT_TRUE(getSnapshot(1)->changes.get() == 0);
+ EXPECT_EQ(getSnapshot(11)->changes, RequestedLayerState::Changes::Content);
+ EXPECT_EQ(getSnapshot(11)->clientChanges, layer_state_t::eColorChanged);
+ EXPECT_EQ(getSnapshot(1)->changes.get(), 0u);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
- EXPECT_TRUE(getSnapshot(11)->changes.get() == 0);
+ EXPECT_EQ(getSnapshot(11)->changes.get(), 0u);
}
TEST_F(LayerSnapshotTest, FastPathSetsChangeFlagToContent) {
setColor(1, {1._hf, 0._hf, 0._hf});
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
EXPECT_EQ(getSnapshot(1)->changes, RequestedLayerState::Changes::Content);
+ EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eColorChanged);
}
TEST_F(LayerSnapshotTest, GameMode) {
@@ -270,7 +273,9 @@
transactions.back().states.front().layerId = 1;
transactions.back().states.front().state.layerId = static_cast<int32_t>(1);
mLifecycleManager.applyTransactions(transactions);
+ EXPECT_EQ(mLifecycleManager.getGlobalChanges(), RequestedLayerState::Changes::GameMode);
UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+ EXPECT_EQ(getSnapshot(1)->clientChanges, layer_state_t::eMetadataChanged);
EXPECT_EQ(static_cast<int32_t>(getSnapshot(1)->gameMode), 42);
EXPECT_EQ(static_cast<int32_t>(getSnapshot(11)->gameMode), 42);
}
@@ -309,7 +314,7 @@
EXPECT_EQ(getSnapshot(1)->frameRate.type, scheduler::LayerInfo::FrameRateCompatibility::NoVote);
}
-TEST_F(LayerSnapshotTest, canCropTouchableRegion) {
+TEST_F(LayerSnapshotTest, CanCropTouchableRegion) {
// ROOT
// ├── 1
// │ ├── 11