Merge "SF: left/right flip luma calculation 90 deg rot" into qt-dev
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 5427ff8..753d5b4 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2086,8 +2086,8 @@
const char* Parcel::readCString() const
{
- const size_t avail = mDataSize-mDataPos;
- if (avail > 0) {
+ if (mDataPos < mDataSize) {
+ const size_t avail = mDataSize-mDataPos;
const char* str = reinterpret_cast<const char*>(mData+mDataPos);
// is the string's trailing NUL within the parcel's valid bounds?
const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
index 8b33a56..0ad99ce 100644
--- a/libs/binder/Status.cpp
+++ b/libs/binder/Status.cpp
@@ -102,13 +102,23 @@
// Skip over fat response headers. Not used (or propagated) in native code.
if (mException == EX_HAS_REPLY_HEADER) {
// Note that the header size includes the 4 byte size field.
- const int32_t header_start = parcel.dataPosition();
+ const size_t header_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t header_avail = parcel.dataAvail();
+
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
+
+ if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
+
parcel.setDataPosition(header_start + header_size);
// And fat response headers are currently only used when there are no
// exceptions, so act like there was no error.
@@ -135,19 +145,36 @@
setFromStatusT(status);
return status;
}
+ if (remote_stack_trace_header_size < 0 ||
+ static_cast<size_t>(remote_stack_trace_header_size) > parcel.dataAvail()) {
+
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
parcel.setDataPosition(parcel.dataPosition() + remote_stack_trace_header_size);
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
} else if (mException == EX_PARCELABLE) {
// Skip over the blob of Parcelable data
- const int32_t header_start = parcel.dataPosition();
+ const size_t header_start = parcel.dataPosition();
+ // Get available size before reading more
+ const size_t header_avail = parcel.dataAvail();
+
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
+
+ if (header_size < 0 || static_cast<size_t>(header_size) > header_avail) {
+ android_errorWriteLog(0x534e4554, "132650049");
+ setFromStatusT(UNKNOWN_ERROR);
+ return UNKNOWN_ERROR;
+ }
+
parcel.setDataPosition(header_start + header_size);
}
if (status != OK) {
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c0bace8..abc7a72 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -208,6 +208,10 @@
defaults: ["gles_libs_defaults"],
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv2\""],
+
+ // Bug: http://b/133874658 Disable native_coverage as we investigate a
+ // crash in surfaceflinger on coverage-enabled cuttlefish builds.
+ native_coverage: false,
}
//##############################################################################
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index a2b6ab6..9d72399 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -545,6 +545,12 @@
if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled &&
presentTimeIsCurrent) {
point->setFrameAvailable();
+ sp<Layer> requestedSyncLayer = point->getRequestedSyncLayer();
+ if (requestedSyncLayer) {
+ // Need to update the transaction flag to ensure the layer's pending transaction
+ // gets applied.
+ requestedSyncLayer->setTransactionFlags(eTransactionNeeded);
+ }
}
}
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 379b004..898f3bc 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -144,28 +144,47 @@
*/
void Layer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {}
-void Layer::onRemovedFromCurrentState() {
- mRemovedFromCurrentState = true;
+void Layer::removeRemoteSyncPoints() {
+ for (auto& point : mRemoteSyncPoints) {
+ point->setTransactionApplied();
+ }
+ mRemoteSyncPoints.clear();
- // the layer is removed from SF mCurrentState to mLayersPendingRemoval
- if (mCurrentState.zOrderRelativeOf != nullptr) {
- sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
- if (strongRelative != nullptr) {
- strongRelative->removeZOrderRelative(this);
- mFlinger->setTransactionFlags(eTraversalNeeded);
+ {
+ Mutex::Autolock pendingStateLock(mPendingStateMutex);
+ for (State pendingState : mPendingStates) {
+ pendingState.barrierLayer_legacy = nullptr;
}
+ }
+}
+
+void Layer::removeRelativeZ(const std::vector<Layer*>& layersInTree) {
+ if (mCurrentState.zOrderRelativeOf == nullptr) {
+ return;
+ }
+
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative == nullptr) {
+ setZOrderRelativeOf(nullptr);
+ return;
+ }
+
+ if (!std::binary_search(layersInTree.begin(), layersInTree.end(), strongRelative.get())) {
+ strongRelative->removeZOrderRelative(this);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
setZOrderRelativeOf(nullptr);
}
+}
+
+void Layer::removeFromCurrentState() {
+ mRemovedFromCurrentState = true;
// Since we are no longer reachable from CurrentState SurfaceFlinger
// will no longer invoke doTransaction for us, and so we will
// never finish applying transactions. We signal the sync point
// now so that another layer will not become indefinitely
// blocked.
- for (auto& point: mRemoteSyncPoints) {
- point->setTransactionApplied();
- }
- mRemoteSyncPoints.clear();
+ removeRemoteSyncPoints();
{
Mutex::Autolock syncLock(mLocalSyncPointMutex);
@@ -175,13 +194,18 @@
mLocalSyncPoints.clear();
}
- for (const auto& child : mCurrentChildren) {
- child->onRemovedFromCurrentState();
- }
-
mFlinger->markLayerPendingRemovalLocked(this);
}
+void Layer::onRemovedFromCurrentState() {
+ auto layersInTree = getLayersInTree(LayerVector::StateSet::Current);
+ std::sort(layersInTree.begin(), layersInTree.end());
+ for (const auto& layer : layersInTree) {
+ layer->removeFromCurrentState();
+ layer->removeRelativeZ(layersInTree);
+ }
+}
+
void Layer::addToCurrentState() {
mRemovedFromCurrentState = false;
@@ -667,7 +691,7 @@
// to be applied as per normal (no synchronization).
mCurrentState.barrierLayer_legacy = nullptr;
} else {
- auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy);
+ auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber_legacy, this);
if (barrierLayer->addSyncPoint(syncPoint)) {
mRemoteSyncPoints.push_back(std::move(syncPoint));
} else {
@@ -1510,6 +1534,7 @@
if (client != nullptr && parentClient != client) {
child->mLayerDetached = true;
child->detachChildren();
+ child->removeRemoteSyncPoints();
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3712b2a..5c55111 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -571,6 +571,17 @@
virtual bool isBufferLatched() const { return false; }
/*
+ * Remove relative z for the layer if its relative parent is not part of the
+ * provided layer tree.
+ */
+ void removeRelativeZ(const std::vector<Layer*>& layersInTree);
+
+ /*
+ * Remove from current state and mark for removal.
+ */
+ void removeFromCurrentState();
+
+ /*
* called with the state lock from a binder thread when the layer is
* removed from the current list to the pending removal list
*/
@@ -733,8 +744,11 @@
class SyncPoint {
public:
- explicit SyncPoint(uint64_t frameNumber)
- : mFrameNumber(frameNumber), mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+ explicit SyncPoint(uint64_t frameNumber, wp<Layer> requestedSyncLayer)
+ : mFrameNumber(frameNumber),
+ mFrameIsAvailable(false),
+ mTransactionIsApplied(false),
+ mRequestedSyncLayer(requestedSyncLayer) {}
uint64_t getFrameNumber() const { return mFrameNumber; }
@@ -746,10 +760,13 @@
void setTransactionApplied() { mTransactionIsApplied = true; }
+ sp<Layer> getRequestedSyncLayer() { return mRequestedSyncLayer.promote(); }
+
private:
const uint64_t mFrameNumber;
std::atomic<bool> mFrameIsAvailable;
std::atomic<bool> mTransactionIsApplied;
+ wp<Layer> mRequestedSyncLayer;
};
// SyncPoints which will be signaled when the correct frame is at the head
@@ -928,6 +945,8 @@
void setZOrderRelativeOf(const wp<Layer>& relativeOf);
bool mGetHandleCalled = false;
+
+ void removeRemoteSyncPoints();
};
} // namespace android
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 5ebae1e..6b4634a 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*"
+ "filter": "CredentialsTest.*:SurfaceFlingerStress.*:SurfaceInterceptorTest.*:LayerTransactionTest.*:LayerTypeTransactionTest.*:LayerUpdateTest.*:GeometryLatchingTest.*:CropLatchingTest.*:ChildLayerTest.*:ScreenCaptureTest.*:ScreenCaptureChildOnlyTest.*:DereferenceSurfaceControlTest.*:BoundlessLayerTest.*:MultiDisplayLayerBoundsTest.*:InvalidHandleTest.*:VirtualDisplayTest.*:RelativeZTest.*"
}
}
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index ec1ac4b..f83b3ea 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -385,6 +385,18 @@
return createLayer(mClient, name, width, height, flags, parent);
}
+ sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
+ SurfaceControl* parent = nullptr) {
+ auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */,
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceColor, parent);
+ asTransaction([&](Transaction& t) {
+ t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f});
+ t.setAlpha(colorLayer, color.a / 255.0f);
+ });
+ return colorLayer;
+ }
+
ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
// wait for previous transactions (such as setSize) to complete
Transaction().apply(true);
@@ -4725,6 +4737,48 @@
mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED);
}
}
+TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) {
+ sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
+ sp<SurfaceControl> childNewClient =
+ newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
+ PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
+
+ ASSERT_TRUE(childNewClient != nullptr);
+ ASSERT_TRUE(childNewClient->isValid());
+
+ fillSurfaceRGBA8(childNewClient, 200, 200, 200);
+
+ Transaction()
+ .hide(mChild)
+ .show(childNewClient)
+ .setPosition(childNewClient, 10, 10)
+ .setPosition(mFGSurfaceControl, 64, 64)
+ .apply();
+
+ {
+ mCapture = screenshot();
+ Rect rect = Rect(74, 74, 84, 84);
+ mCapture->expectBorder(rect, Color{195, 63, 63, 255});
+ mCapture->expectColor(rect, Color{200, 200, 200, 255});
+ }
+
+ Transaction()
+ .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(),
+ mFGSurfaceControl->getSurface()->getNextFrameNumber())
+ .apply();
+ Transaction().detachChildren(mFGSurfaceControl).apply();
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32));
+
+ // BufferLayer can still dequeue buffers even though there's a detached layer with a
+ // deferred transaction.
+ {
+ SCOPED_TRACE("new buffer");
+ mCapture = screenshot();
+ Rect rect = Rect(74, 74, 84, 84);
+ mCapture->expectBorder(rect, Color::RED);
+ mCapture->expectColor(rect, Color{200, 200, 200, 255});
+ }
+}
TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) {
asTransaction([&](Transaction& t) {
@@ -5833,4 +5887,126 @@
allowedConfigs.end());
}
+class RelativeZTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ const auto display = SurfaceComposerClient::getInternalDisplayToken();
+ ASSERT_FALSE(display == nullptr);
+
+ // Back layer
+ mBackgroundLayer = createColorLayer("Background layer", Color::RED);
+
+ // Front layer
+ mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN);
+
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, 0);
+ t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer);
+ t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer);
+ });
+ }
+
+ virtual void TearDown() {
+ LayerTransactionTest::TearDown();
+ mBackgroundLayer = 0;
+ mForegroundLayer = 0;
+ }
+
+ sp<SurfaceControl> mBackgroundLayer;
+ sp<SurfaceControl> mForegroundLayer;
+};
+
+// When a layer is reparented offscreen, remove relative z order if the relative parent
+// is still onscreen so that the layer is not drawn.
+TEST_F(RelativeZTest, LayerRemoved) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Child layer (WHITE) (relative to foregroud layer)
+ // Foregroud layer (GREEN)
+ sp<SurfaceControl> childLayer =
+ createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get());
+
+ Transaction{}
+ .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1)
+ .show(childLayer)
+ .apply();
+
+ {
+ // The childLayer should be in front of the FG control.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, nullptr).apply();
+
+ // Background layer (RED)
+ // Child layer (WHITE)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply();
+
+ {
+ // The relative z info for child layer should be reset, leaving FG control on top.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+}
+
+// When a layer is reparented offscreen, preseve relative z order if the relative parent
+// is also offscreen. Regression test b/132613412
+TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) {
+ std::unique_ptr<ScreenCapture> sc;
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // child level 1 (WHITE)
+ // child level 2a (BLUE)
+ // child level 3 (GREEN) (relative to child level 2b)
+ // child level 2b (BLACK)
+ sp<SurfaceControl> childLevel1 =
+ createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get());
+ sp<SurfaceControl> childLevel2a =
+ createColorLayer("child level 2a", Color::BLUE, childLevel1.get());
+ sp<SurfaceControl> childLevel2b =
+ createColorLayer("child level 2b", Color::BLACK, childLevel1.get());
+ sp<SurfaceControl> childLevel3 =
+ createColorLayer("child level 3", Color::GREEN, childLevel2a.get());
+
+ Transaction{}
+ .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1)
+ .show(childLevel2a)
+ .show(childLevel2b)
+ .show(childLevel3)
+ .apply();
+
+ {
+ // The childLevel3 should be in front of childLevel2b.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ Transaction{}.reparent(childLevel1, nullptr).apply();
+
+ // Background layer (RED)
+ // Foregroud layer (GREEN)
+ // child level 1 (WHITE)
+ // child level 2 back (BLUE)
+ // child level 3 (GREEN) (relative to child level 2b)
+ // child level 2 front (BLACK)
+ Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply();
+
+ {
+ // Nothing should change at this point since relative z info was preserved.
+ ScreenCapture::captureScreen(&sc);
+ sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b);
+ }
+}
+
} // namespace android